summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLester Caine <lester@lsces.co.uk>2026-06-01 12:34:02 +0100
committerLester Caine <lester@lsces.co.uk>2026-06-01 12:34:02 +0100
commit6b30ab3d3ec23bd3f6056f2d1685159487383378 (patch)
tree8771041a52fadc545c1badbc38c910c56d84d2f3
parenta16e3d92444befcbd857d3bf00381b559d494d20 (diff)
downloadstock-6b30ab3d3ec23bd3f6056f2d1685159487383378.tar.gz
stock-6b30ab3d3ec23bd3f6056f2d1685159487383378.tar.bz2
stock-6b30ab3d3ec23bd3f6056f2d1685159487383378.zip
Stock/movement assembly linkage, view icons, and list_stock fixes
- add_requisition: store ASSEMBLY xref on new movements so they can be filtered by assembly - StockMovement::getList: add assembly_content_id filter via ASSEMBLY xref join - list_movements: pass assemblyContentId to Smarty - view_assembly.tpl: add View Stock and View Movements icons filtered by assembly - list_stock: guard CAST with SIMILAR TO on xkey join; fix %.3g scientific notation to %.0f Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--add_requisition.php90
-rw-r--r--list_movements.php7
-rw-r--r--list_stock.php1
-rw-r--r--templates/list_stock.tpl10
-rwxr-xr-xtemplates/view_assembly.tpl2
5 files changed, 104 insertions, 6 deletions
diff --git a/add_requisition.php b/add_requisition.php
new file mode 100644
index 0000000..db9a9b7
--- /dev/null
+++ b/add_requisition.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @package stock
+ * @subpackage functions
+ */
+
+namespace Bitweaver\Stock;
+
+use Bitweaver\KernelTools;
+
+require_once '../kernel/includes/setup_inc.php';
+
+global $gBitSystem, $gBitSmarty, $gBitUser;
+
+$gBitSystem->verifyPermission( 'p_stock_create' );
+
+if( !empty( $_REQUEST['fCancel'] ) ) {
+ header( 'Location: '.STOCK_PKG_URL.'list_stock.php' );
+ die;
+}
+
+if( !empty( $_REQUEST['fCreate'] ) ) {
+ $assemblyContentId = isset( $_REQUEST['assembly_content_id'] ) && is_numeric( $_REQUEST['assembly_content_id'] )
+ ? (int)$_REQUEST['assembly_content_id'] : null;
+ $kitCount = isset( $_REQUEST['kit_count'] ) && is_numeric( $_REQUEST['kit_count'] ) && (float)$_REQUEST['kit_count'] > 0
+ ? (float)$_REQUEST['kit_count'] : 1;
+
+ $title = trim( $_REQUEST['title'] ?? '' );
+
+ if( !$assemblyContentId ) {
+ $errors[] = KernelTools::tra( 'Please select an assembly.' );
+ } elseif( $title === '' ) {
+ $errors[] = KernelTools::tra( 'Please enter an RQ number.' );
+ } else {
+ // Verify assembly exists without relying on content type registry
+ global $gBitDb;
+ $assemblyExists = $gBitDb->getOne(
+ "SELECT `content_id` FROM `".BIT_DB_PREFIX."liberty_content`
+ WHERE `content_id` = ? AND `content_type_guid` = 'stockassembly'",
+ [ $assemblyContentId ]
+ );
+ if( !$assemblyExists ) {
+ $errors[] = KernelTools::tra( 'Assembly not found.' );
+ } else {
+ $movement = new StockMovement();
+ $paramHash = [
+ 'title' => $title,
+ 'content_type_guid' => STOCKMOVEMENT_CONTENT_TYPE_GUID,
+ ];
+ if( $movement->store( $paramHash ) ) {
+ $reqnHash = [
+ 'content_id' => $movement->mContentId,
+ 'item' => 'REQN',
+ 'xkey' => $title,
+ 'fAddXref' => 1,
+ ];
+ $movement->storeXref( $reqnHash );
+ $assemblyHash = [
+ 'content_id' => $movement->mContentId,
+ 'item' => 'ASSEMBLY',
+ 'xref' => $assemblyContentId,
+ 'fAddXref' => 1,
+ ];
+ $movement->storeXref( $assemblyHash );
+ $movement->explodeFromAssembly( $assemblyContentId, $kitCount );
+ header( 'Location: '.STOCK_PKG_URL.'edit_movement.php?content_id='.$movement->mContentId );
+ die;
+ }
+ $errors = $movement->mErrors;
+ }
+ }
+}
+
+// Assembly list for selector
+$assembly = new StockAssembly();
+$listHash = [ 'show_empty' => true, 'sort_mode' => 'title_asc', 'max_records' => 500 ];
+$assemblyList = $assembly->getList( $listHash );
+
+// Pre-select if coming from list_stock
+$preselect = isset( $_REQUEST['assembly_content_id'] ) && is_numeric( $_REQUEST['assembly_content_id'] )
+ ? (int)$_REQUEST['assembly_content_id'] : null;
+$kitCount = isset( $_REQUEST['kit_count'] ) && is_numeric( $_REQUEST['kit_count'] )
+ ? (float)$_REQUEST['kit_count'] : 1;
+
+$gBitSmarty->assign( 'assemblyList', $assemblyList );
+$gBitSmarty->assign( 'preselect', $preselect );
+$gBitSmarty->assign( 'kitCount', $kitCount );
+$gBitSmarty->assign( 'errors', $errors ?? [] );
+
+$gBitSystem->display( 'bitpackage:stock/add_requisition.tpl', KernelTools::tra( 'Create Requisition' ), [ 'display_mode' => 'edit' ] );
diff --git a/list_movements.php b/list_movements.php
index 6da281b..10d2526 100644
--- a/list_movements.php
+++ b/list_movements.php
@@ -15,8 +15,9 @@ $movement = new StockMovement();
$listHash = $_REQUEST;
$movementList = $movement->getList( $listHash );
-$gBitSmarty->assign( 'listInfo', $listHash['listInfo'] );
-$gBitSmarty->assign( 'movementList', $movementList );
-$gBitSmarty->assign( 'filterType', $_REQUEST['ref_type'] ?? '' );
+$gBitSmarty->assign( 'listInfo', $listHash['listInfo'] );
+$gBitSmarty->assign( 'movementList', $movementList );
+$gBitSmarty->assign( 'filterType', $_REQUEST['ref_type'] ?? '' );
+$gBitSmarty->assign( 'assemblyContentId', isset( $_REQUEST['assembly_content_id'] ) && is_numeric( $_REQUEST['assembly_content_id'] ) ? (int)$_REQUEST['assembly_content_id'] : null );
$gBitSystem->display( 'bitpackage:stock/list_movements.tpl', 'Movements', [ 'display_mode' => 'list' ] );
diff --git a/list_stock.php b/list_stock.php
index 668a401..d55df91 100644
--- a/list_stock.php
+++ b/list_stock.php
@@ -61,6 +61,7 @@ $query = "SELECT lc.`content_id`, lc.`title`, lc.`data`,
$joinSql
INNER JOIN `{$X}liberty_xref` x ON x.`xref` = lc.`content_id`
AND x.`item` IN ('SGL','PCK','SHT','VOL')
+ AND x.`xkey` SIMILAR TO '[0-9]+(\.[0-9]+)?'
INNER JOIN `{$X}liberty_content` mc ON mc.`content_id` = x.`content_id`
AND mc.`content_type_guid` = 'stockmovement'
WHERE lc.`content_type_guid` = 'stockcomponent'
diff --git a/templates/list_stock.tpl b/templates/list_stock.tpl
index 343e426..faac32a 100644
--- a/templates/list_stock.tpl
+++ b/templates/list_stock.tpl
@@ -39,6 +39,10 @@
</label>
</div>
<button type="submit" class="btn btn-default btn-sm">{tr}Go{/tr}</button>
+ {if $showBom && $gBitUser->hasPermission('p_stock_create')}
+ <a class="btn btn-warning btn-sm"
+ href="{$smarty.const.STOCK_PKG_URL}add_requisition.php?assembly_content_id={$assemblyContentId}&amp;kit_count={$kitCount}">{tr}Create Requisition{/tr}</a>
+ {/if}
</div>
{/form}
@@ -66,12 +70,12 @@
<td rowspan="{$comp.stock|@count}">{$comp.data|escape}</td>
<td rowspan="{$comp.stock|@count}">{$comp.part_number|escape}</td>
{/if}
- {if $showBom}<td class="text-right">{math equation="b*k" b=$row.bom_qty k=$kitCount format="%.3g"}</td>{/if}
+ {if $showBom}<td class="text-right">{math equation="b*k" b=$row.bom_qty k=$kitCount format="%.0f"}</td>{/if}
<td>{$qtype|escape}</td>
- <td class="text-right">{$row.level|string_format:"%.3g"}</td>
+ <td class="text-right">{$row.level|string_format:"%.0f"}</td>
{if $showBom}
{assign var=remaining value=$row.level-($row.bom_qty*$kitCount)}
- <td class="text-right{if $remaining < 0} text-danger{/if}">{$remaining|string_format:"%.3g"}</td>
+ <td class="text-right{if $remaining < 0} text-danger{/if}">{$remaining|string_format:"%.0f"}</td>
{/if}
</tr>
{/foreach}
diff --git a/templates/view_assembly.tpl b/templates/view_assembly.tpl
index da9979e..6a7ab9c 100755
--- a/templates/view_assembly.tpl
+++ b/templates/view_assembly.tpl
@@ -4,6 +4,8 @@
{include file="bitpackage:liberty/services_inc.tpl" serviceLocation='icon' serviceHash=$gContent->mInfo}
<a title="{tr}Edit{/tr}" href="{$smarty.const.STOCK_PKG_URL}edit_assembly.php?content_id={$gContent->mContentId}">{booticon iname="fa-pen-to-square" iexplain="Edit Assembly"}</a>
<a title="{tr}Component Order{/tr}" href="{$smarty.const.STOCK_PKG_URL}component_order.php?content_id={$gContent->mContentId}">{booticon iname="fa-sort" iexplain="Component Order"}</a>
+ <a title="{tr}View Stock{/tr}" href="{$smarty.const.STOCK_PKG_URL}list_stock.php?assembly_content_id={$gContent->mContentId}">{booticon iname="fa-boxes-stacked" iexplain="View Stock"}</a>
+ <a title="{tr}View Movements{/tr}" href="{$smarty.const.STOCK_PKG_URL}list_movements.php?assembly_content_id={$gContent->mContentId}">{booticon iname="fa-truck" iexplain="View Movements"}</a>
{if $gContent->hasAdminPermission()}
<a title="{tr}Delete Assembly{/tr}" href="{$smarty.const.STOCK_PKG_URL}edit_assembly.php?content_id={$gContent->mContentId}&amp;delete=1">{booticon iname="fa-trash" iexplain="Delete Assembly"}</a>
{/if}