mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
PO receive fix (#8423)
* Add "active" filter to PurchaseOrderLineItem.part field * Fix for allocation serial numbers to incoming items * Validate serial numbers per line item
This commit is contained in:
parent
c9079d9a0e
commit
4df42cd776
@ -845,6 +845,20 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
|
|||||||
except DjangoValidationError as e:
|
except DjangoValidationError as e:
|
||||||
raise ValidationError({'serial_numbers': e.messages})
|
raise ValidationError({'serial_numbers': e.messages})
|
||||||
|
|
||||||
|
invalid_serials = []
|
||||||
|
|
||||||
|
# Check the serial numbers are valid
|
||||||
|
for serial in data['serials']:
|
||||||
|
try:
|
||||||
|
base_part.validate_serial_number(serial, raise_error=True)
|
||||||
|
except (ValidationError, DjangoValidationError):
|
||||||
|
invalid_serials.append(serial)
|
||||||
|
|
||||||
|
if len(invalid_serials) > 0:
|
||||||
|
msg = _('The following serial numbers already exist or are invalid')
|
||||||
|
msg += ': ' + ', '.join(invalid_serials)
|
||||||
|
raise ValidationError({'serial_numbers': msg})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@ -259,6 +259,7 @@ function poLineItemFields(options={}) {
|
|||||||
part: {
|
part: {
|
||||||
icon: 'fa-shapes',
|
icon: 'fa-shapes',
|
||||||
filters: {
|
filters: {
|
||||||
|
active: true,
|
||||||
part_detail: true,
|
part_detail: true,
|
||||||
supplier_detail: true,
|
supplier_detail: true,
|
||||||
supplier: options.supplier,
|
supplier: options.supplier,
|
||||||
|
@ -237,6 +237,12 @@ function LineItemFormRow({
|
|||||||
onClose: () => props.changeFn(props.idx, 'location', undefined)
|
onClose: () => props.changeFn(props.idx, 'location', undefined)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Is this a trackable part?
|
||||||
|
const trackable: boolean = useMemo(
|
||||||
|
() => record.part_detail?.trackable ?? false,
|
||||||
|
[record]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!!record.destination) {
|
if (!!record.destination) {
|
||||||
props.changeFn(props.idx, 'location', record.destination);
|
props.changeFn(props.idx, 'location', record.destination);
|
||||||
@ -303,6 +309,14 @@ function LineItemFormRow({
|
|||||||
props.changeFn(props.idx, 'barcode', barcode);
|
props.changeFn(props.idx, 'barcode', barcode);
|
||||||
}, [barcode]);
|
}, [barcode]);
|
||||||
|
|
||||||
|
const batchToolTip: string = useMemo(() => {
|
||||||
|
if (trackable) {
|
||||||
|
return t`Assign Batch Code and Serial Numbers`;
|
||||||
|
} else {
|
||||||
|
return t`Assign Batch Code`;
|
||||||
|
}
|
||||||
|
}, [trackable]);
|
||||||
|
|
||||||
// Update location field description on state change
|
// Update location field description on state change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
@ -418,9 +432,7 @@ function LineItemFormRow({
|
|||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => batchHandlers.toggle()}
|
onClick={() => batchHandlers.toggle()}
|
||||||
icon={<InvenTreeIcon icon="batch_code" />}
|
icon={<InvenTreeIcon icon="batch_code" />}
|
||||||
tooltip={t`Assign Batch Code${
|
tooltip={batchToolTip}
|
||||||
record.trackable && ' and Serial Numbers'
|
|
||||||
}`}
|
|
||||||
tooltipAlignment="top"
|
tooltipAlignment="top"
|
||||||
variant={batchOpen ? 'filled' : 'transparent'}
|
variant={batchOpen ? 'filled' : 'transparent'}
|
||||||
/>
|
/>
|
||||||
@ -552,18 +564,20 @@ function LineItemFormRow({
|
|||||||
fieldDefinition={{
|
fieldDefinition={{
|
||||||
field_type: 'string',
|
field_type: 'string',
|
||||||
label: t`Batch Code`,
|
label: t`Batch Code`,
|
||||||
|
description: t`Enter batch code for received items`,
|
||||||
value: props.item.batch_code
|
value: props.item.batch_code
|
||||||
}}
|
}}
|
||||||
error={props.rowErrors?.batch_code?.message}
|
error={props.rowErrors?.batch_code?.message}
|
||||||
/>
|
/>
|
||||||
<TableFieldExtraRow
|
<TableFieldExtraRow
|
||||||
visible={batchOpen && record.trackable}
|
visible={batchOpen && trackable}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) =>
|
||||||
props.changeFn(props.idx, 'serial_numbers', value)
|
props.changeFn(props.idx, 'serial_numbers', value)
|
||||||
}
|
}
|
||||||
fieldDefinition={{
|
fieldDefinition={{
|
||||||
field_type: 'string',
|
field_type: 'string',
|
||||||
label: t`Serial numbers`,
|
label: t`Serial Numbers`,
|
||||||
|
description: t`Enter serial numbers for received items`,
|
||||||
value: props.item.serial_numbers
|
value: props.item.serial_numbers
|
||||||
}}
|
}}
|
||||||
error={props.rowErrors?.serial_numbers?.message}
|
error={props.rowErrors?.serial_numbers?.message}
|
||||||
|
@ -302,6 +302,10 @@ export function PurchaseOrderLineItemTable({
|
|||||||
);
|
);
|
||||||
}, [order, poStatus]);
|
}, [order, poStatus]);
|
||||||
|
|
||||||
|
const orderPlaced: boolean = useMemo(() => {
|
||||||
|
return order.status == poStatus.PLACED;
|
||||||
|
}, [order, poStatus]);
|
||||||
|
|
||||||
const rowActions = useCallback(
|
const rowActions = useCallback(
|
||||||
(record: any): RowAction[] => {
|
(record: any): RowAction[] => {
|
||||||
let received = (record?.received ?? 0) >= (record?.quantity ?? 0);
|
let received = (record?.received ?? 0) >= (record?.quantity ?? 0);
|
||||||
@ -370,10 +374,10 @@ export function PurchaseOrderLineItemTable({
|
|||||||
icon={<IconSquareArrowRight />}
|
icon={<IconSquareArrowRight />}
|
||||||
onClick={() => receiveLineItems.open()}
|
onClick={() => receiveLineItems.open()}
|
||||||
disabled={table.selectedRecords.length === 0}
|
disabled={table.selectedRecords.length === 0}
|
||||||
hidden={!orderOpen || !user.hasChangeRole(UserRoles.purchase_order)}
|
hidden={!orderPlaced || !user.hasChangeRole(UserRoles.purchase_order)}
|
||||||
/>
|
/>
|
||||||
];
|
];
|
||||||
}, [orderId, user, table, orderOpen]);
|
}, [orderId, user, table, orderOpen, orderPlaced]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user