mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-03 22:55:43 +00:00 
			
		
		
		
	Adds options to clear existing BOM data when uploading
This commit is contained in:
		@@ -746,6 +746,13 @@ class BomExtractSerializer(serializers.Serializer):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        fields = [
 | 
				
			||||||
 | 
					            'bom_file',
 | 
				
			||||||
 | 
					            'part',
 | 
				
			||||||
 | 
					            'clear_existing',
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # These columns must be present
 | 
					    # These columns must be present
 | 
				
			||||||
    REQUIRED_COLUMNS = [
 | 
					    REQUIRED_COLUMNS = [
 | 
				
			||||||
        'quantity',
 | 
					        'quantity',
 | 
				
			||||||
@@ -940,16 +947,24 @@ class BomExtractSerializer(serializers.Serializer):
 | 
				
			|||||||
            'filename': self.filename,
 | 
					            'filename': self.filename,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True), required=True)
 | 
				
			||||||
        fields = [
 | 
					
 | 
				
			||||||
            'bom_file',
 | 
					    clear_existing = serializers.BooleanField(
 | 
				
			||||||
        ]
 | 
					        label=_("Clear Existing BOM"),
 | 
				
			||||||
 | 
					        help_text=_("Delete existing BOM data first"),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self):
 | 
					    def save(self):
 | 
				
			||||||
        """
 | 
					        
 | 
				
			||||||
        There is no action associated with "saving" this serializer
 | 
					        data = self.validated_data
 | 
				
			||||||
        """
 | 
					
 | 
				
			||||||
        pass
 | 
					        master_part = data['part']
 | 
				
			||||||
 | 
					        clear_existing = data['clear_existing']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if clear_existing:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Remove all existing BOM items
 | 
				
			||||||
 | 
					            master_part.bom_items.all().delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BomUploadSerializer(serializers.Serializer):
 | 
					class BomUploadSerializer(serializers.Serializer):
 | 
				
			||||||
@@ -963,13 +978,14 @@ class BomUploadSerializer(serializers.Serializer):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    def validate(self, data):
 | 
					    def validate(self, data):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data = super().validate(data)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        items = data['items']
 | 
					        items = data['items']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if len(items) == 0:
 | 
					        if len(items) == 0:
 | 
				
			||||||
            raise serializers.ValidationError(_("At least one BOM item is required"))
 | 
					            raise serializers.ValidationError(_("At least one BOM item is required"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = super().validate(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return data
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self):
 | 
					    def save(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -112,7 +112,7 @@ function constructBomUploadTable(data, options={}) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Add callback for "remove row" button
 | 
					        // Add callback for "remove row" button
 | 
				
			||||||
        $(`#button-row-remove-${idx}`).click(function() {
 | 
					        $(`#button-row-remove-${idx}`).click(function() {
 | 
				
			||||||
            $(`#bom_import_row_${idx}`).remove();
 | 
					            $(`#items_${idx}`).remove();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,20 +172,34 @@ function submitBomTable(part_id, options={}) {
 | 
				
			|||||||
    getApiEndpointOptions(url, function(response) {
 | 
					    getApiEndpointOptions(url, function(response) {
 | 
				
			||||||
        var fields = response.actions.POST;
 | 
					        var fields = response.actions.POST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inventreePut(url, data, {
 | 
					        constructForm(url, {
 | 
				
			||||||
            method: 'POST',
 | 
					            method: 'POST',
 | 
				
			||||||
            success: function(response) {
 | 
					            fields: {
 | 
				
			||||||
                // TODO: Return to the "bom" page
 | 
					                clear_existing: {},
 | 
				
			||||||
            },  
 | 
					            },  
 | 
				
			||||||
            error: function(xhr) {
 | 
					            title: '{% trans "Submit BOM Data" %}',
 | 
				
			||||||
                switch (xhr.status) {
 | 
					            onSubmit: function(fields, opts) {
 | 
				
			||||||
                case 400:
 | 
					
 | 
				
			||||||
                    handleFormErrors(xhr.responseJSON, fields, options);
 | 
					                data.clear_existing = getFormFieldValue('clear_existing', {}, opts);
 | 
				
			||||||
                    break;
 | 
					
 | 
				
			||||||
                default:
 | 
					                $(opts.modal).modal('hide');
 | 
				
			||||||
                    showApiError(xhr, url);
 | 
					
 | 
				
			||||||
                    break;
 | 
					                inventreePut(url, data, {
 | 
				
			||||||
                }
 | 
					                    method: 'POST',
 | 
				
			||||||
 | 
					                    success: function(response) {
 | 
				
			||||||
 | 
					                        // TODO: Return to the "bom" page
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    error: function(xhr) {
 | 
				
			||||||
 | 
					                        switch (xhr.status) {
 | 
				
			||||||
 | 
					                        case 400:
 | 
				
			||||||
 | 
					                            handleFormErrors(xhr.responseJSON, fields, options);
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        default:
 | 
				
			||||||
 | 
					                            showApiError(xhr, url);
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });      
 | 
					        });      
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1059,6 +1059,28 @@ function handleNestedErrors(errors, field_name, options={}) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var errors = error_item[sub_field_name];
 | 
					            var errors = error_item[sub_field_name];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (sub_field_name == 'non_field_errors') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var row = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (options.modal) {
 | 
				
			||||||
 | 
					                    row = $(options.modal).find(`#items_${nest_id}`);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    row = $(`#items_${nest_id}`);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (var ii = errors.length - 1; ii >= 0; ii--) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    var html = `
 | 
				
			||||||
 | 
					                    <div id='error_${ii}_non_field_error' class='help-block form-field-error form-error-message'>
 | 
				
			||||||
 | 
					                        <strong>${errors[ii]}</strong>
 | 
				
			||||||
 | 
					                    </div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    row.after(html);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Find the target (nested) field
 | 
					            // Find the target (nested) field
 | 
				
			||||||
            var target = `${field_name}_${sub_field_name}_${nest_id}`;
 | 
					            var target = `${field_name}_${sub_field_name}_${nest_id}`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user