diff options
| author | Lester Caine <lester@lsces.co.uk> | 2026-06-08 20:56:56 +0100 |
|---|---|---|
| committer | Lester Caine <lester@lsces.co.uk> | 2026-06-08 20:56:56 +0100 |
| commit | a838a2d3963738b2e9bc496b31e078ead79d4a43 (patch) | |
| tree | bafe061903e4a076b92eb6d00813661f21f64ae8 /import | |
| parent | 5e0af09c649b90a0963bd4e6b62f24b8cbf8edd9 (diff) | |
| download | stock-a838a2d3963738b2e9bc496b31e078ead79d4a43.tar.gz stock-a838a2d3963738b2e9bc496b31e078ead79d4a43.tar.bz2 stock-a838a2d3963738b2e9bc496b31e078ead79d4a43.zip | |
stock: requisition system, movement BOM editor, autocomplete dropdowns
Requisitions:
- add_requisition.php: create REQN movements linked to assemblies or
kitlocker components; Ordered date stored on REQN xref start_date
- ASSEMBLY xref group registered in schema (sort_order=1, template=assembly);
ASSEMBLY item registered with multiple=1 for future multi-item reqns
- StockMovement::loadXrefInfo() enriches assembly group rows with
linked_title/linked_desc from liberty_content
- view_xref_assembly_group/item templates: Assembly tab with qty, title
link, type; Add item form on edit_movement for REQNs; hidden on I-direction
- view_movement/edit_movement: isReqn flag hides assembly tab and type
selector on ORDER/TRANS; add another assembly from edit_movement
BOM editor:
- stockmovement/view_xref_bom_group: Add component links to new
add_movement_component.php instead of generic liberty/add_xref.php
- add_movement_component.php/.tpl: movement-aware add component page;
uses movement_lookup_inc, STOCKMOVEMENT_CONTENT_TYPE_GUID, sequential
xorder, redirects back to edit_movement
Autocomplete dropdowns (replace <select> everywhere):
- add_requisition: hidden+text+dropdown widget; KLID in JSON for matching
- add_supplier: AJAX contact lookup replaces static supplier list
- list_stock: assembly selector replaced with autocomplete dropdown
- edit_movement: From field proper dropdown replacing datalist;
Movement Type radio fixed (was reading non-existent mInfo[reference])
- view_xref_assembly_group: Add item inline form with same widget
Import:
- ImportKitlockerAssemblies: upsert xrefs on reload; KLID/KLSGL/KL3M
now stored on both assemblies and components (not assembly-only)
- StockComponent::getList: kitlocker_only filter via EXISTS(KLID xref)
list_movements: Add Requisition icon alongside Add Movement in header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'import')
| -rw-r--r-- | import/ImportKitlockerAssemblies.php | 110 |
1 files changed, 58 insertions, 52 deletions
diff --git a/import/ImportKitlockerAssemblies.php b/import/ImportKitlockerAssemblies.php index aa96a1e..9c12200 100644 --- a/import/ImportKitlockerAssemblies.php +++ b/import/ImportKitlockerAssemblies.php @@ -4,19 +4,47 @@ * * CSV column layout (0-based, header row skipped by loader): * 0 Title MERG product code / designation (used as lc.title) - * 1 KLID Kitlocker numeric ID code (stored as KLID xref on assemblies) + * 1 KLID Kitlocker numeric ID code (stored as KLID xref on both types) * 2 Description Long description (stored as content body) - * 3 KLSGL Kitlocker single-unit stock count (assemblies only → KLSGL xref) - * 4 KL3M 3-month sales count (assemblies only → KL3M xref) - * 5 Group Group number 1–28 → KLG01–KLG28 stgrp xref (both types) + * 3 KLSGL Kitlocker single-unit stock count (stored as KLSGL xref on both types) + * 4 KL3M 3-month sales count (stored as KL3M xref on both types) + * 5 Group Group number 1–99 → KLG01–KLG99 stgrp xref (both types) * 6 Type 'A' = StockAssembly, 'C' = StockComponent * + * On reload, existing records are not re-created but their kitlocker xrefs are upserted, + * so a fresh import run will tag components that were previously missing KLID etc. + * * @package stock */ use Bitweaver\Stock\StockAssembly; use Bitweaver\Stock\StockComponent; +function stockKitlockerXrefUpsert( int $contentId, string $item, string $value ): void { + global $gBitDb; + $existingId = $gBitDb->getOne( + "SELECT `xref_id` FROM `".BIT_DB_PREFIX."liberty_xref` + WHERE `content_id` = ? AND `item` = ?", + [ $contentId, $item ] + ); + if( $existingId ) { + $gBitDb->associateUpdate( + BIT_DB_PREFIX.'liberty_xref', + [ 'xkey' => substr( $value, 0, 32 ), 'last_update_date' => $gBitDb->NOW() ], + [ 'xref_id' => $existingId ] + ); + } else { + $gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [ + 'xref_id' => $gBitDb->GenID( 'liberty_xref_seq' ), + 'content_id' => $contentId, + 'item' => $item, + 'xkey' => substr( $value, 0, 32 ), + 'xorder' => 0, + 'last_update_date' => $gBitDb->NOW(), + ] ); + } +} + function stockExpungeKitlockerItemByTitle( string $title, string $type ): bool { global $gBitDb; @@ -53,65 +81,43 @@ function stockImportKitlockerItem( array $data, int $rowNum ): array { return $result; } - $guid = ( $type === 'A' ) ? 'stockassembly' : 'stockcomponent'; - - $exists = $gBitDb->getOne( - "SELECT lc.`content_id` FROM `".BIT_DB_PREFIX."liberty_content` lc - WHERE lc.`content_type_guid` = ? AND lc.`title` = ?", - [ $guid, $title ] - ); - if( $exists ) { - $result['skipped']++; - $result['errors'][] = "Row $rowNum: '$title' already exists, skipped."; - return $result; - } - + $guid = ( $type === 'A' ) ? 'stockassembly' : 'stockcomponent'; $klid = trim( $data[1] ?? '' ); $desc = trim( $data[2] ?? '' ); $klsgl = trim( $data[3] ?? '' ); $kl3m = trim( $data[4] ?? '' ); $group = (int)( $data[5] ?? 0 ); - $obj = ( $type === 'A' ) ? new StockAssembly() : new StockComponent(); - $pHash = [ - 'title' => $title, - 'edit' => $desc, - 'format_guid' => 'bithtml', - ]; - if( !$obj->store( $pHash ) ) { - $result['skipped']++; - $result['errors'][] = "Row $rowNum: failed to store '$title'."; - return $result; - } + $contentId = (int)$gBitDb->getOne( + "SELECT lc.`content_id` FROM `".BIT_DB_PREFIX."liberty_content` lc + WHERE lc.`content_type_guid` = ? AND lc.`title` = ?", + [ $guid, $title ] + ); - $contentId = $obj->mContentId; + if( !$contentId ) { + $obj = ( $type === 'A' ) ? new StockAssembly() : new StockComponent(); + $pHash = [ + 'title' => $title, + 'edit' => $desc, + 'format_guid' => 'bithtml', + ]; + if( !$obj->store( $pHash ) ) { + $result['skipped']++; + $result['errors'][] = "Row $rowNum: failed to store '$title'."; + return $result; + } + $contentId = $obj->mContentId; + } - // Group tag — shared across both types via 'stock' package-level stgrp + // Group tag — both types if( $group >= 1 && $group <= 99 ) { - $xrefId = $gBitDb->GenID( 'liberty_xref_seq' ); - $gBitDb->associateInsert( BIT_DB_PREFIX.'liberty_xref', [ - 'xref_id' => $xrefId, - 'content_id' => $contentId, - 'item' => sprintf( 'KLG%02d', $group ), - 'xorder' => 0, - 'last_update_date' => $gBitDb->NOW(), - ] ); + stockKitlockerXrefUpsert( $contentId, sprintf( 'KLG%02d', $group ), '' ); } - // Assembly-specific kitlocker xrefs - if( $type === 'A' ) { - 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' => substr( $value, 0, 32 ), - 'last_update_date' => $gBitDb->NOW(), - ] ); - } + // Kitlocker xrefs — same set for assemblies and components + foreach( [ 'KLID' => $klid, 'KLSGL' => $klsgl, 'KL3M' => $kl3m ] as $item => $value ) { + if( $value !== '' ) { + stockKitlockerXrefUpsert( $contentId, $item, $value ); } } |
