summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLester Caine <lester@lsces.co.uk>2026-06-06 17:22:44 +0100
committerLester Caine <lester@lsces.co.uk>2026-06-06 17:22:44 +0100
commit85add8e6c0fa75baeeee342e6e36051faf923e5c (patch)
tree7340f76fa36f98e0be0837873aa4e3875cb8270f
parent4f2819cc35eaa740dd1b806b038cf95d50d9052f (diff)
downloadstock-85add8e6c0fa75baeeee342e6e36051faf923e5c.tar.gz
stock-85add8e6c0fa75baeeee342e6e36051faf923e5c.tar.bz2
stock-85add8e6c0fa75baeeee342e6e36051faf923e5c.zip
import: cull legacy importers; move data to storage/stock/
Remove old ImportAssembly/Component classes, load_stock, load_components, load_assemblies, load_kitlocker_assemblies/groups (one-off imports). Add STOCK_IMPORT_PATH = STORAGE_PKG_PATH.'stock/' to bit_setup_inc. Update load_simple_assemblies/components/components_2 to use STOCK_IMPORT_PATH instead of __DIR__.'/data/'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--import/ImportAssembly.php94
-rw-r--r--import/ImportComponent.php65
-rw-r--r--import/load_assemblies.php72
-rw-r--r--import/load_components.php58
-rw-r--r--import/load_kitlocker_assemblies.php181
-rw-r--r--import/load_kitlocker_groups.php109
-rw-r--r--import/load_simple_assemblies.php4
-rw-r--r--import/load_simple_components.php4
-rw-r--r--import/load_simple_components_2.php4
-rw-r--r--import/load_stock.php102
-rwxr-xr-xincludes/bit_setup_inc.php1
11 files changed, 7 insertions, 687 deletions
diff --git a/import/ImportAssembly.php b/import/ImportAssembly.php
deleted file mode 100644
index a42e320..0000000
--- a/import/ImportAssembly.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/**
- * Stock assembly / BOM CSV import record loader.
- *
- * CSV column layout (0-based):
- * 0 assembly_title Kit / assembly name
- * 1 component_title Component name (must already exist as a stockcomponent content item)
- * 2 quantity_value Numeric quantity in BOM (optional, default 1)
- * 3 quantity_item SGL / PCK / SHT / VOL (optional, default SGL)
- * 4 item_position Float position (e.g. 1.1, 1.2, 2.1) (optional)
- *
- * Rows are grouped by assembly_title. The assembly record is created once
- * the first time a new title is seen; subsequent rows with the same title
- * add further BOM lines to it.
- *
- * @package stock
- */
-
-use Bitweaver\Stock\StockAssembly;
-use Bitweaver\Liberty\LibertyContent;
-
-/**
- * Process a batch of rows for a single assembly.
- * $pRows is an array of raw CSV row arrays, all sharing the same assembly_title.
- */
-function StockAssemblyBatchLoad( string $assemblyTitle, array $pRows ): array {
- $result = [ 'loaded' => 0, 'skipped' => 0, 'errors' => [] ];
-
- // Create or find the assembly
- $assembly = new StockAssembly();
- $pHash = [
- 'title' => $assemblyTitle,
- 'format_guid' => 'plain',
- 'rows_per_page'=> 5,
- 'cols_per_page'=> 3,
- ];
- if( !$assembly->store( $pHash ) ) {
- $result['errors'][] = "Failed to create assembly: $assemblyTitle";
- $result['skipped'] += count( $pRows );
- return $result;
- }
-
- foreach( $pRows as $rowNum => $data ) {
- $componentTitle = trim( $data[1] ?? '' );
- if( empty( $componentTitle ) ) {
- $result['skipped']++;
- $result['errors'][] = "Row $rowNum: empty component title.";
- continue;
- }
-
- // Look up component by title
- $componentContentId = _stockImportFindComponent( $componentTitle );
- if( !$componentContentId ) {
- $result['skipped']++;
- $result['errors'][] = "Row $rowNum: component not found — '$componentTitle'";
- continue;
- }
-
- $qtyValue = isset( $data[2] ) && is_numeric( trim($data[2]) ) ? (float)trim( $data[2] ) : 1.0;
- $qtySrc = strtoupper( trim( $data[3] ?? 'SGL' ) );
- if( !in_array( $qtySrc, [ 'SGL', 'PCK', 'SHT', 'VOL' ] ) ) {
- $qtySrc = 'SGL';
- }
- $position = isset( $data[4] ) && is_numeric( trim($data[4]) ) ? (float)trim( $data[4] ) : null;
-
- // Insert BOM row directly — addItem() handles the assembly_content_id reference
- $assembly->addItem( $componentContentId, $position );
-
- // Update quantity_value and quantity_item on the map row just inserted
- global $gBitDb;
- $gBitDb->query(
- "UPDATE `".BIT_DB_PREFIX."stock_assembly_map`
- SET `quantity_value` = ?, `quantity_item` = ?
- WHERE `assembly_content_id` = ? AND `item_content_id` = ?",
- [ $qtyValue, $qtySrc, $assembly->mContentId, $componentContentId ]
- );
-
- $result['loaded']++;
- }
-
- return $result;
-}
-
-/** Finds a component's content_id by exact title match. */
-function _stockImportFindComponent( string $title ): ?int {
- global $gBitDb;
- $contentId = $gBitDb->getOne(
- "SELECT lc.`content_id`
- FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.`content_type_guid` = '".STOCKCOMPONENT_CONTENT_TYPE_GUID."' AND lc.`title` = ?",
- [ $title ]
- );
- return $contentId ? (int)$contentId : null;
-}
diff --git a/import/ImportComponent.php b/import/ImportComponent.php
deleted file mode 100644
index 15f87e7..0000000
--- a/import/ImportComponent.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/**
- * Stock component CSV import record loader.
- *
- * CSV column layout (0-based):
- * 0 title Component name / description
- * 1 data Long description (optional)
- * 2 part_number Supplier part number → #SUP xkey (optional)
- * 3 quantity_value Numeric stock quantity (optional, default 1)
- * 4 quantity_item SGL / PCK / SHT / VOL (optional, default SGL)
- *
- * @package stock
- */
-
-use Bitweaver\Stock\StockComponent;
-use Bitweaver\Liberty\LibertyContent;
-
-function StockComponentRecordLoad( array $data ): bool {
- $title = trim( $data[0] ?? '' );
- if( empty( $title ) ) {
- return false;
- }
-
- $component = new StockComponent();
-
- $pHash = [
- 'title' => $title,
- 'edit' => trim( $data[1] ?? '' ),
- 'format_guid' => 'plain',
- ];
-
- if( !$component->store( $pHash ) ) {
- return false;
- }
-
- // Supplier xref (#SUP) — part number in xkey; xref (contact_id) left empty for manual linking
- $partNumber = trim( $data[2] ?? '' );
- if( $partNumber !== '' ) {
- $xrefHash = [
- 'content_id' => $component->mContentId,
- 'item' => '#SUP',
- 'xkey' => $partNumber,
- 'fAddXref' => 1,
- ];
- $component->storeXref( $xrefHash );
- }
-
- // Quantity xref (SGL/PCK/SHT/VOL)
- $qtyValue = isset( $data[3] ) && is_numeric( trim( $data[3] ) ) ? (float)trim( $data[3] ) : null;
- $qtySrc = strtoupper( trim( $data[4] ?? 'SGL' ) );
- if( !in_array( $qtySrc, [ 'SGL', 'PCK', 'SHT', 'VOL' ] ) ) {
- $qtySrc = 'SGL';
- }
- if( $qtyValue !== null ) {
- $xrefHash = [
- 'content_id' => $component->mContentId,
- 'item' => $qtySrc,
- 'xkey' => $qtyValue,
- 'fAddXref' => 1,
- ];
- $component->storeXref( $xrefHash );
- }
-
- return true;
-}
diff --git a/import/load_assemblies.php b/import/load_assemblies.php
deleted file mode 100644
index 140b424..0000000
--- a/import/load_assemblies.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * Load stock assemblies and their BOM from a CSV file.
- *
- * Place your CSV at: stock/import/data/assemblies.csv
- *
- * CSV columns (with header row skipped):
- * assembly_title, component_title, quantity_value, quantity_item, item_position
- *
- * Rows are grouped by assembly_title. Components must already exist
- * (run load_components.php first).
- *
- * @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 __DIR__.'/ImportAssembly.php';
-
-$csvFile = __DIR__.'/data/simple_assemblies.csv';
-$loaded = 0;
-$skipped = 0;
-$errors = [];
-
-if( !file_exists( $csvFile ) ) {
- $errors[] = 'CSV file not found: '.$csvFile;
-} else {
- $handle = fopen( $csvFile, 'r' );
- if( $handle === false ) {
- $errors[] = 'Cannot open CSV file.';
- } else {
- // Group rows by assembly title
- $batches = [];
- $rowNum = 0;
- while( ( $data = fgetcsv( $handle, 1000, ',', '"', '\\' ) ) !== false ) {
- $rowNum++;
- if( $rowNum === 1 ) {
- continue; // skip header
- }
- $assemblyTitle = trim( $data[0] ?? '' );
- if( empty( $assemblyTitle ) ) {
- $skipped++;
- $errors[] = "Row $rowNum: empty assembly title, skipped.";
- continue;
- }
- $batches[$assemblyTitle][] = array_merge( [ $rowNum ], $data );
- }
- fclose( $handle );
-
- // Process each assembly batch
- foreach( $batches as $assemblyTitle => $rows ) {
- $result = StockAssemblyBatchLoad( $assemblyTitle, $rows );
- $loaded += $result['loaded'];
- $skipped += $result['skipped'];
- $errors = array_merge( $errors, $result['errors'] );
- }
- }
-}
-
-$gBitSmarty->assign( 'loaded', $loaded );
-$gBitSmarty->assign( 'skipped', $skipped );
-$gBitSmarty->assign( 'errors', $errors );
-$gBitSmarty->assign( 'csvFile', $csvFile );
-
-$gBitSystem->display( 'bitpackage:stock/import_results.tpl', 'Import Assemblies' );
diff --git a/import/load_components.php b/import/load_components.php
deleted file mode 100644
index d70ea4e..0000000
--- a/import/load_components.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * Load stock components from a CSV file.
- *
- * Place your CSV at: stock/import/data/components.csv
- *
- * CSV columns (with header row skipped):
- * title, description, part_number, quantity_value, quantity_item
- *
- * @package stock
- */
-
-namespace Bitweaver\Stock;
-
-require_once '../../kernel/includes/setup_inc.php';
-
-global $gBitSystem, $gBitSmarty;
-
-$gBitSystem->verifyPackage( 'stock' );
-$gBitSystem->verifyPermission( 'p_stock_admin' );
-
-require_once __DIR__.'/ImportComponent.php';
-
-$csvFile = __DIR__.'/data/components.csv';
-$loaded = 0;
-$skipped = 0;
-$errors = [];
-
-if( !file_exists( $csvFile ) ) {
- $errors[] = 'CSV file not found: '.$csvFile;
-} else {
- $handle = fopen( $csvFile, 'r' );
- if( $handle === false ) {
- $errors[] = 'Cannot open CSV file.';
- } else {
- $row = 0;
- while( ( $data = fgetcsv( $handle, 1000, ',', '"', '\\' ) ) !== false ) {
- $row++;
- if( $row === 1 ) {
- continue; // skip header
- }
- if( StockComponentRecordLoad( $data ) ) {
- $loaded++;
- } else {
- $skipped++;
- $errors[] = "Row $row skipped: ".( trim( $data[0] ?? '' ) ?: '(empty title)' );
- }
- }
- fclose( $handle );
- }
-}
-
-$gBitSmarty->assign( 'loaded', $loaded );
-$gBitSmarty->assign( 'skipped', $skipped );
-$gBitSmarty->assign( 'errors', $errors );
-$gBitSmarty->assign( 'csvFile', $csvFile );
-
-$gBitSystem->display( 'bitpackage:stock/import_results.tpl', 'Import Components' );
diff --git a/import/load_kitlocker_assemblies.php b/import/load_kitlocker_assemblies.php
deleted file mode 100644
index 00627a5..0000000
--- a/import/load_kitlocker_assemblies.php
+++ /dev/null
@@ -1,181 +0,0 @@
-<?php
-/**
- * Phase 2: Import KitlockerAssemblies.csv under their KitLocker group assemblies.
- *
- * CSV columns: Title, KLID, Data, KLSGL, KL3M, Group
- * Group is numeric — 'G' is prepended to match the KLID xref stored by
- * load_kitlocker_groups.php.
- *
- * Existing assemblies are matched by KLID xref so the title can be updated to
- * a tidier version. Old kitlocker xrefs are wiped and replaced on each run.
- *
- * Run load_kitlocker_groups.php first.
- *
- * @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.'StockAssembly.php';
-
-$csvFile = __DIR__.'/data/KitlockerAssemblies.csv';
-$loaded = $skipped = $updated = 0;
-$errors = [];
-
-// KLID → content_id map for group assemblies (G1, G2, …)
-$klidMap = $gBitDb->getAssoc(
- "SELECT lx.xkey, lx.content_id FROM `".BIT_DB_PREFIX."liberty_xref` lx
- INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON lc.content_id=lx.content_id
- WHERE lx.item=? AND lc.content_type_guid=?",
- [ 'KLID', STOCKASSEMBLY_CONTENT_TYPE_GUID ]
-);
-
-$kitlockerXrefItems = [ 'KLID', 'KLPR', 'KLSGL', 'KL3M', 'KLURL', 'KLSGL' ];
-
-if( empty( $klidMap ) ) {
- $errors[] = 'No KLID xref entries found — run load_kitlocker_groups.php first.';
-} elseif( !file_exists( $csvFile ) ) {
- $errors[] = "File not found: $csvFile";
-} else {
- $fh = fopen( $csvFile, 'r' );
- $rowNum = 0;
- while( ($cols = fgetcsv( $fh, 0, ',', '"', '' )) !== false ) {
- $rowNum++;
- if( $rowNum === 1 ) continue; // header: Title, KLID, Data, KLSGL, KL3M, Group
-
- $title = trim( $cols[0] ?? '' );
- $klid = trim( $cols[1] ?? '' );
- $data = trim( $cols[2] ?? '' );
- $klsgl = trim( $cols[3] ?? '' );
- $kl3m = trim( $cols[4] ?? '' );
- $groupNum = trim( $cols[5] ?? '' );
- $groupKey = 'G'.$groupNum;
-
- if( $title === '' || $klid === '' || $groupNum === '' ) {
- $skipped++;
- continue;
- }
-
- if( !isset( $klidMap[$groupKey] ) ) {
- $errors[] = "Row $rowNum: '$title' — group '$groupKey' not in KLID map, skipped.";
- $skipped++;
- continue;
- }
-
- $groupContentId = (int)$klidMap[$groupKey];
- $contentId = 0;
-
- if( $title === $klid ) {
- // Title unchanged — find by KLID xref, fall back to title if xref not yet stored
- $contentId = (int)$gBitDb->getOne(
- "SELECT lx.content_id FROM `".BIT_DB_PREFIX."liberty_xref` lx
- INNER JOIN `".BIT_DB_PREFIX."liberty_content` lc ON lc.content_id=lx.content_id
- WHERE lx.item=? AND lx.xkey=? AND lc.content_type_guid=?",
- [ 'KLID', $klid, STOCKASSEMBLY_CONTENT_TYPE_GUID ]
- );
- if( !$contentId ) {
- $contentId = (int)$gBitDb->getOne(
- "SELECT lc.content_id FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.content_type_guid=? AND lc.title=?",
- [ STOCKASSEMBLY_CONTENT_TYPE_GUID, $title ]
- );
- }
- } else {
- // Title is a tidier replacement for the old title (= col1/KLID).
- // Find the keeper by new title; find the old stale record by old title.
- $contentId = (int)$gBitDb->getOne(
- "SELECT lc.content_id FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.content_type_guid=? AND lc.title=?",
- [ STOCKASSEMBLY_CONTENT_TYPE_GUID, $title ]
- );
- $oldContentId = (int)$gBitDb->getOne(
- "SELECT lc.content_id FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.content_type_guid=? AND lc.title=?",
- [ STOCKASSEMBLY_CONTENT_TYPE_GUID, $klid ]
- );
- if( $contentId && $oldContentId && $oldContentId !== $contentId ) {
- // Both exist — expunge the stale col1 record
- $stale = new StockAssembly( null, $oldContentId );
- $stale->load();
- $stale->expunge();
- } elseif( !$contentId && $oldContentId ) {
- // Only old record exists — rename it to the tidy title
- $contentId = $oldContentId;
- }
- }
-
- if( $contentId ) {
- // Update title/description and wipe old kitlocker xrefs
- $assembly = new StockAssembly( null, $contentId );
- $assembly->load();
- $pHash = [ 'content_id' => $contentId, 'title' => $title, 'edit' => $data, 'format_guid' => 'bithtml' ];
- $assembly->store( $pHash );
- $gBitDb->query(
- "DELETE FROM `".BIT_DB_PREFIX."liberty_xref`
- WHERE content_id=? AND item IN ('KLID','KLPR','KLSGL','KL3M','KLURL')",
- [ $contentId ]
- );
- $updated++;
- } else {
- // No existing record — create fresh
- $assembly = new StockAssembly();
- $pHash = [ 'title' => $title, 'edit' => $data, 'format_guid' => 'bithtml' ];
- if( !$assembly->store( $pHash ) ) {
- $errors[] = "Row $rowNum: failed to create '$title'";
- $skipped++;
- continue;
- }
- $contentId = $assembly->mContentId;
- $loaded++;
- }
-
- // Ensure parent group link exists
- $alreadyLinked = (int)$gBitDb->getOne(
- "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."stock_assembly_map`
- WHERE assembly_content_id=? AND item_content_id=?",
- [ $groupContentId, $contentId ]
- );
- if( !$alreadyLinked ) {
- $gBitDb->query(
- "INSERT INTO `".BIT_DB_PREFIX."stock_assembly_map`
- (assembly_content_id, item_content_id, item_position) VALUES (?,?,NULL)",
- [ $groupContentId, $contentId ]
- );
- }
-
- // Store kitlocker xrefs
- foreach( [ 'KLID' => $klid, 'KLSGL' => $klsgl, 'KL3M' => $kl3m ] as $item => $value ) {
- if( $value !== '' ) {
- $xrefId = $gBitDb->GenID( 'liberty_xref_seq' );
- $gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [
- 'xref_id' => $xrefId,
- 'content_id' => $contentId,
- 'item' => $item,
- 'xorder' => 0,
- 'xkey' => $value,
- 'last_update_date' => $gBitDb->NOW(),
- ] );
- }
- }
-
- // Keep contentId in klidMap for subsequent lookups within this run
- $klidMap[$klid] = $contentId;
- }
- fclose( $fh );
-}
-
-$gBitSmarty->assign( 'loaded', $loaded );
-$gBitSmarty->assign( 'skipped', $skipped );
-$gBitSmarty->assign( 'deleted', $updated );
-$gBitSmarty->assign( 'errors', $errors );
-$gBitSmarty->assign( 'csvFile', $csvFile );
-$gBitSmarty->assign( 'movement', null );
-
-$gBitSystem->display( 'bitpackage:stock/import_results.tpl', 'Import KitLocker Assemblies' );
diff --git a/import/load_kitlocker_groups.php b/import/load_kitlocker_groups.php
deleted file mode 100644
index 96333e7..0000000
--- a/import/load_kitlocker_groups.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-/**
- * Phase 1: Import KitlockerGroups.csv as child assemblies of a parent assembly.
- *
- * CSV columns: KLID, Title
- * Each group assembly is tagged with a KLID xref so load_kitlocker_assemblies.php
- * can locate the correct parent by KLID lookup.
- *
- * Safe to re-run: existing groups (matched by KLID xref) are skipped but their
- * parent link is always checked and added if missing.
- *
- * @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.'StockAssembly.php';
-
-$csvFile = __DIR__.'/data/KitlockerGroups.csv';
-$loaded = $skipped = $linked = 0;
-$errors = [];
-
-// Find the kitlocker parent assembly by title
-$parentContentId = (int)$gBitDb->getOne(
- "SELECT lc.content_id FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.content_type_guid='stockassembly' AND LOWER(lc.title)='kitlocker'"
-);
-
-$parent = $parentContentId ? new StockAssembly( null, $parentContentId ) : new StockAssembly();
-if( $parentContentId ) $parent->load();
-
-if( !$parentContentId || !$parent->isValid() || empty( $parent->mContentId ) ) {
- $errors[] = "Parent assembly 'kitlocker' not found — create it first.";
-} elseif( !file_exists( $csvFile ) ) {
- $errors[] = "File not found: $csvFile";
-} else {
- $fh = fopen( $csvFile, 'r' );
- $rowNum = 0;
- while( ($cols = fgetcsv( $fh, 0, ',', '"', '' )) !== false ) {
- $rowNum++;
- if( $rowNum === 1 ) continue; // header: KLID, Title
-
- $klid = trim( $cols[0] ?? '' );
- $title = trim( $cols[1] ?? '' );
- if( $klid === '' || $title === '' ) continue;
-
- // Get existing content_id from KLID xref, or create new assembly
- $contentId = (int)$gBitDb->getOne(
- "SELECT `content_id` FROM `".BIT_DB_PREFIX."liberty_xref` WHERE `item`=? AND `xkey`=?",
- [ 'KLID', $klid ]
- );
-
- if( $contentId ) {
- $skipped++;
- } else {
- $assembly = new StockAssembly();
- $pHash = [ 'title' => $title, 'edit' => '', 'format_guid' => 'bithtml' ];
- if( !$assembly->store( $pHash ) ) {
- $errors[] = "Row $rowNum: failed to create '$title'";
- continue;
- }
- $contentId = $assembly->mContentId;
-
- // Tag with KLID xref
- $xrefId = $gBitDb->GenID( 'liberty_xref_seq' );
- $gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [
- 'xref_id' => $xrefId,
- 'content_id' => $contentId,
- 'item' => 'KLID',
- 'xorder' => 0,
- 'xkey' => $klid,
- 'last_update_date' => $gBitDb->NOW(),
- ] );
- $loaded++;
- }
-
- // Always ensure parent link exists (safe to re-run)
- $alreadyLinked = (int)$gBitDb->getOne(
- "SELECT COUNT(*) FROM `".BIT_DB_PREFIX."stock_assembly_map`
- WHERE `assembly_content_id`=? AND `item_content_id`=?",
- [ $parentContentId, $contentId ]
- );
- if( !$alreadyLinked ) {
- $gBitDb->getOne(
- "INSERT INTO `".BIT_DB_PREFIX."stock_assembly_map`
- (`assembly_content_id`, `item_content_id`, `item_position`) VALUES (?,?,NULL)",
- [ $parentContentId, $contentId ]
- );
- $linked++;
- }
- }
- fclose( $fh );
-}
-
-$gBitSmarty->assign( 'loaded', $loaded );
-$gBitSmarty->assign( 'skipped', $skipped );
-$gBitSmarty->assign( 'deleted', $linked );
-$gBitSmarty->assign( 'errors', $errors );
-$gBitSmarty->assign( 'csvFile', $csvFile );
-$gBitSmarty->assign( 'movement', null );
-
-$gBitSystem->display( 'bitpackage:stock/import_results.tpl', 'Import KitLocker Groups' );
diff --git a/import/load_simple_assemblies.php b/import/load_simple_assemblies.php
index 792a8af..06b320d 100644
--- a/import/load_simple_assemblies.php
+++ b/import/load_simple_assemblies.php
@@ -3,7 +3,7 @@
* Load assemblies from a simple 4-column CSV (title, description, KLPR, KLURL).
* No header row. Existing assemblies (by title) are skipped unless clear=y.
*
- * Place your CSV at: stock/import/data/simple_assemblies.csv
+ * Place your CSV at: storage/stock/simple_assemblies.csv
* Append ?clear=y to the URL to delete and re-import all rows.
*
* @package stock
@@ -20,7 +20,7 @@ $gBitSystem->verifyPermission( 'p_stock_admin' );
require_once __DIR__.'/ImportSimpleAssembly.php';
-$csvFile = __DIR__.'/data/simple_assemblies.csv';
+$csvFile = STOCK_IMPORT_PATH . 'simple_assemblies.csv';
$doClear = ( ( $_REQUEST['clear'] ?? '' ) === 'y' );
$loaded = 0;
$skipped = 0;
diff --git a/import/load_simple_components.php b/import/load_simple_components.php
index 7aafe25..1d2ff30 100644
--- a/import/load_simple_components.php
+++ b/import/load_simple_components.php
@@ -4,7 +4,7 @@
* First row is a header and is skipped. Existing components (by title) are skipped
* unless clear=y is passed.
*
- * Place your CSV at: stock/import/data/simple_components.csv
+ * Place your CSV at: storage/stock/simple_components.csv
* Append ?clear=y to the URL to delete and re-import all rows.
*
* @package stock
@@ -21,7 +21,7 @@ $gBitSystem->verifyPermission( 'p_stock_admin' );
require_once __DIR__.'/ImportSimpleComponent.php';
-$csvFile = __DIR__.'/data/simple_components.csv';
+$csvFile = STOCK_IMPORT_PATH . 'simple_components.csv';
$doClear = ( ( $_REQUEST['clear'] ?? '' ) === 'y' );
$loaded = 0;
$skipped = 0;
diff --git a/import/load_simple_components_2.php b/import/load_simple_components_2.php
index 6b2fcdf..ab40540 100644
--- a/import/load_simple_components_2.php
+++ b/import/load_simple_components_2.php
@@ -4,7 +4,7 @@
* First row is a header and is skipped. Existing components (by title) are skipped
* unless clear=y is passed.
*
- * Place your CSV at: stock/import/data/simple_components_2.csv
+ * Place your CSV at: storage/stock/simple_components_2.csv
* Append ?clear=y to the URL to delete and re-import all rows.
*
* @package stock
@@ -21,7 +21,7 @@ $gBitSystem->verifyPermission( 'p_stock_admin' );
require_once __DIR__.'/ImportSimpleComponent.php';
-$csvFile = __DIR__.'/data/simple_components_2.csv';
+$csvFile = STOCK_IMPORT_PATH . 'simple_components_2.csv';
$doClear = ( ( $_REQUEST['clear'] ?? '' ) === 'y' );
$loaded = 0;
$skipped = 0;
diff --git a/import/load_stock.php b/import/load_stock.php
deleted file mode 100644
index 19cd0d3..0000000
--- a/import/load_stock.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?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 lc.`content_id`
- FROM `".BIT_DB_PREFIX."liberty_content` lc
- WHERE lc.`content_type_guid` = '".STOCKCOMPONENT_CONTENT_TYPE_GUID."' AND 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' );
diff --git a/includes/bit_setup_inc.php b/includes/bit_setup_inc.php
index f4864c0..88c6415 100755
--- a/includes/bit_setup_inc.php
+++ b/includes/bit_setup_inc.php
@@ -14,6 +14,7 @@ define( 'STOCK_PKG_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path
define( 'STOCK_PKG_INCLUDE_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/includes/');
define( 'STOCK_PKG_CLASS_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/includes/classes/');
define( 'STOCK_PKG_ADMIN_PATH', BIT_ROOT_PATH . basename( $pRegisterHash['package_path'] ) . '/admin/');
+define( 'STOCK_IMPORT_PATH', STORAGE_PKG_PATH . 'stock/' );
$gBitSystem->registerPackage( $pRegisterHash );