diff --git a/src/backend/InvenTree/stock/models.py b/src/backend/InvenTree/stock/models.py
index ce9ea98b59..4fc4284587 100644
--- a/src/backend/InvenTree/stock/models.py
+++ b/src/backend/InvenTree/stock/models.py
@@ -1984,9 +1984,18 @@ class StockItem(
Returns:
The new StockItem object
+ Raises:
+ ValidationError: If the stock item cannot be split
+
- The provided quantity will be subtracted from this item and given to the new one.
- The new item will have a different StockItem ID, while this will remain the same.
"""
+ # Run initial checks to test if the stock item can actually be "split"
+
+ # Cannot split a stock item which is in production
+ if self.is_building:
+ raise ValidationError(_('Stock item is currently in production'))
+
notes = kwargs.get('notes', '')
# Do not split a serialized part
diff --git a/src/backend/InvenTree/stock/serializers.py b/src/backend/InvenTree/stock/serializers.py
index e183483f93..6b7ac858b4 100644
--- a/src/backend/InvenTree/stock/serializers.py
+++ b/src/backend/InvenTree/stock/serializers.py
@@ -1565,18 +1565,18 @@ class StockAdjustmentItemSerializer(serializers.Serializer):
help_text=_('StockItem primary key value'),
)
- def validate_pk(self, pk):
+ def validate_pk(self, stock_item: StockItem) -> StockItem:
"""Ensure the stock item is valid."""
allow_out_of_stock_transfer = get_global_setting(
'STOCK_ALLOW_OUT_OF_STOCK_TRANSFER', backup_value=False, cache=False
)
- if not allow_out_of_stock_transfer and not pk.is_in_stock(
+ if not allow_out_of_stock_transfer and not stock_item.is_in_stock(
check_status=False, check_quantity=False
):
raise ValidationError(_('Stock item is not in stock'))
- return pk
+ return stock_item
quantity = serializers.DecimalField(
max_digits=15, decimal_places=5, min_value=Decimal(0), required=True
diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx
index 0f408e0289..c61302d9c1 100644
--- a/src/frontend/src/pages/stock/StockDetail.tsx
+++ b/src/frontend/src/pages/stock/StockDetail.tsx
@@ -659,13 +659,15 @@ export default function StockDetail() {
});
const stockActions = useMemo(() => {
- const inStock =
+ // Can this stock item be transferred to a different location?
+ const canTransfer =
user.hasChangeRole(UserRoles.stock) &&
!stockitem.sales_order &&
!stockitem.belongs_to &&
!stockitem.customer &&
- !stockitem.consumed_by &&
- !stockitem.is_building;
+ !stockitem.consumed_by;
+
+ const isBuilding = stockitem.is_building;
const serial = stockitem.serial;
const serialized =
@@ -696,7 +698,7 @@ export default function StockDetail() {
{
name: t`Count`,
tooltip: t`Count stock`,
- hidden: serialized || !inStock,
+ hidden: serialized || !canTransfer || isBuilding,
icon: (
),
@@ -707,7 +709,7 @@ export default function StockDetail() {
{
name: t`Add`,
tooltip: t`Add Stock`,
- hidden: serialized || !inStock,
+ hidden: serialized || !canTransfer || isBuilding,
icon: ,
onClick: () => {
stockitem.pk && addStockItem.open();
@@ -716,7 +718,11 @@ export default function StockDetail() {
{
name: t`Remove`,
tooltip: t`Remove Stock`,
- hidden: serialized || !inStock || stockitem.quantity <= 0,
+ hidden:
+ serialized ||
+ !canTransfer ||
+ isBuilding ||
+ stockitem.quantity <= 0,
icon: ,
onClick: () => {
stockitem.pk && removeStockItem.open();
@@ -725,7 +731,7 @@ export default function StockDetail() {
{
name: t`Transfer`,
tooltip: t`Transfer Stock`,
- hidden: !inStock,
+ hidden: !canTransfer,
icon: (
),
@@ -737,8 +743,10 @@ export default function StockDetail() {
name: t`Serialize`,
tooltip: t`Serialize stock`,
hidden:
- !inStock ||
+ !canTransfer ||
+ isBuilding ||
serialized ||
+ stockitem?.quantity != 1 ||
stockitem?.part_detail?.trackable != true,
icon: ,
onClick: () => {
diff --git a/src/frontend/src/tables/build/BuildOutputTable.tsx b/src/frontend/src/tables/build/BuildOutputTable.tsx
index e6f71bb891..c5313476a0 100644
--- a/src/frontend/src/tables/build/BuildOutputTable.tsx
+++ b/src/frontend/src/tables/build/BuildOutputTable.tsx
@@ -574,6 +574,7 @@ export default function BuildOutputTable({
props={{
params: {
part_detail: true,
+ location_detail: true,
tests: true,
is_building: true,
build: buildId