Check for duplicate BOM items as part of serializer validation

This commit is contained in:
Oliver 2022-02-07 11:35:07 +11:00
parent a2c48d308f
commit 2ade14c47b
4 changed files with 38 additions and 8 deletions

View File

@ -493,6 +493,22 @@ class BomItemSerializer(InvenTreeModelSerializer):
purchase_price_range = serializers.SerializerMethodField()
def validate(self, data):
# Check for duplicate BOM items
part = data['part']
sub_part = data['sub_part']
if BomItem.objects.get(part=part, sub_part=sub_part).exists():
raise serializers.ValidationError({
'part': _("Duplicate BOM item already exists"),
'sub_part': _("Duplicate BOM items already exists"),
})
data = super().validate(data)
return data
def __init__(self, *args, **kwargs):
# part_detail and sub_part_detail serializers are only included if requested.
# This saves a bunch of database requests
@ -962,8 +978,20 @@ class BomUploadSerializer(serializers.Serializer):
items = data['items']
with transaction.atomic():
try:
with transaction.atomic():
for item in items:
print(item)
for item in items:
part = item['part']
sub_part = item['sub_part']
# Ignore duplicate BOM items
if BomItem.objects.filter(part=part, sub_part=sub_part).exists():
continue
# Create a new BomItem object
BomItem.objects.create(**item)
except Exception as e:
raise serializers.ValidationError(detail=serializers.as_serializer_error(e))

View File

@ -43,6 +43,7 @@ function constructBomUploadTable(data, options={}) {
var field_options = {
hideLabels: true,
hideClearButton: true,
form_classes: 'bom-form-group',
};
function constructRowField(field_name) {
@ -77,7 +78,7 @@ function constructBomUploadTable(data, options={}) {
buttons += `</div>`;
var html = `
<tr id='bom_import_row_${idx}' class='bom-import-row' idx='${idx}'>
<tr id='items_${idx}' class='bom-import-row' idx='${idx}'>
<td id='col_sub_part_${idx}'>${sub_part}</td>
<td id='col_quantity_${idx}'>${quantity}</td>
<td id='col_reference_${idx}'>${reference}</td>

View File

@ -1056,6 +1056,7 @@ function handleNestedErrors(errors, field_name, options={}) {
// Here, error_item is a map of field names to error messages
for (sub_field_name in error_item) {
var errors = error_item[sub_field_name];
// Find the target (nested) field
@ -1919,12 +1920,12 @@ function constructField(name, parameters, options) {
options.current_group = group;
}
var form_classes = 'form-group';
var form_classes = options.form_classes || 'form-group';
if (parameters.errors) {
form_classes += ' form-field-error';
}
// Optional content to render before the field
if (parameters.before) {
html += parameters.before;

View File

@ -161,7 +161,7 @@ function renderPart(name, data, parameters, options) {
html += ` <span>${data.full_name || data.name}</span>`;
if (data.description) {
html += ` - <i>${data.description}</i>`;
html += ` - <i><small>${data.description}</small></i>`;
}
var extra = '';