diff options
| author | Lester Caine <lester@lsces.co.uk> | 2026-05-27 17:45:10 +0100 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2026-05-27 17:45:10 +0100 |
| commit | 6c360a42b7f45078c9256cbbc48d2aa8741e57ea (patch) | |
| tree | 2c2b341af2adba73a9b4c58709ab70012e1db6b1 /import | |
| parent | b334d4bf4168012d1f4c7c580ee317cb439648b1 (diff) | |
| download | stock-6c360a42b7f45078c9256cbbc48d2aa8741e57ea.tar.gz stock-6c360a42b7f45078c9256cbbc48d2aa8741e57ea.tar.bz2 stock-6c360a42b7f45078c9256cbbc48d2aa8741e57ea.zip | |
Add initial stock load importer and improve import results template
load_stock.php creates a pending StockMovement IN from a 3-column CSV
(component_title, desc[ignored], qty), then ?process=y commits via
processMovement(). import_results.tpl now shows movement status and
the ?process=y hint when a pending movement is waiting.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'import')
| -rw-r--r-- | import/load_stock.php | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/import/load_stock.php b/import/load_stock.php new file mode 100644 index 0000000..d8bd2e6 --- /dev/null +++ b/import/load_stock.php @@ -0,0 +1,103 @@ +<?php +/** + * Load initial stock from a 3-column CSV (component_title, description[ignored], quantity). + * No header row. Creates one IN movement and adds each row as an item. + * + * Place your CSV at: stock/import/data/stock.csv + * Browse to this page to create/reload the movement in draft status. + * Append ?process=y to commit stock levels and mark the movement complete. + * + * @package stock + */ + +namespace Bitweaver\Stock; + +require_once '../../kernel/includes/setup_inc.php'; + +global $gBitSystem, $gBitSmarty, $gBitDb; + +$gBitSystem->verifyPackage( 'stock' ); +$gBitSystem->verifyPermission( 'p_stock_admin' ); + +require_once STOCK_PKG_CLASS_PATH.'StockMovement.php'; + +$csvFile = __DIR__.'/data/stock.csv'; +$doProcess = ( ( $_REQUEST['process'] ?? '' ) === 'y' ); +$loaded = 0; +$skipped = 0; +$errors = []; +$movement = null; + +if( !file_exists( $csvFile ) ) { + $errors[] = 'CSV file not found: '.$csvFile; +} else { + $handle = fopen( $csvFile, 'r' ); + if( $handle === false ) { + $errors[] = 'Cannot open CSV file.'; + } else { + $rows = []; + while( ( $data = fgetcsv( $handle, 1000, ',', '"', '' ) ) !== false ) { + $rows[] = $data; + } + fclose( $handle ); + + // Create the movement + $movement = new StockMovement(); + $pHash = [ + 'title' => 'Initial Stock Load', + 'direction' => STOCK_MOVEMENT_IN, + 'status' => 'pending', + ]; + if( !$movement->store( $pHash ) ) { + $errors[] = 'Failed to create stock movement.'; + } else { + foreach( $rows as $rowNum => $data ) { + $componentTitle = trim( $data[0] ?? '' ); + $qty = isset( $data[2] ) && is_numeric( trim( $data[2] ) ) ? (float)trim( $data[2] ) : null; + + if( empty( $componentTitle ) ) { + $skipped++; + $errors[] = "Row ".($rowNum+1).": empty title, skipped."; + continue; + } + if( $qty === null || $qty <= 0 ) { + $skipped++; + $errors[] = "Row ".($rowNum+1).": '$componentTitle' — invalid quantity, skipped."; + continue; + } + + $contentId = $gBitDb->getOne( + "SELECT sc.`content_id` + FROM `".BIT_DB_PREFIX."stock_component` sc + INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON lc.`content_id` = sc.`content_id` + WHERE lc.`title` = ?", + [ $componentTitle ] + ); + if( !$contentId ) { + $skipped++; + $errors[] = "Row ".($rowNum+1).": component '$componentTitle' not found, skipped."; + continue; + } + + $movement->addItem( (int)$contentId, $qty, 'SGL' ); + $loaded++; + } + + if( $doProcess && $loaded > 0 ) { + if( !$movement->processMovement() ) { + $errors[] = 'processMovement() failed: '.implode( ', ', $movement->mErrors ); + } + } + } + } +} + +$gBitSmarty->assign( 'loaded', $loaded ); +$gBitSmarty->assign( 'skipped', $skipped ); +$gBitSmarty->assign( 'deleted', 0 ); +$gBitSmarty->assign( 'errors', $errors ); +$gBitSmarty->assign( 'csvFile', $csvFile ); +$gBitSmarty->assign( 'movement', $movement ); +$gBitSmarty->assign( 'doProcess', $doProcess ); + +$gBitSystem->display( 'bitpackage:stock/import_results.tpl', 'Import Stock' ); |
