Skip to content

Commit

Permalink
Add errors when attempting to update non-updatable fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt-Yorkley committed Aug 27, 2018
1 parent 44faa11 commit dd36e27
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 83 deletions.
113 changes: 43 additions & 70 deletions app/assets/stylesheets/admin/product_import.css.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
@import "variables";

div.panel-section {
$pi-red: $warning-red;
$pi-green: lighten($spree-green, 10%);
$pi-orange: $bright-orange;
$pi-blue: lighten($spree-blue, 10%);
$pi-light-yellow: #faffaf;

// scss-lint:disable NestingDepth

.neutral {
color: #bfbfbf;
div.panel-section {
.error {
color: $pi-red;
}
.warning {
color: $warning-red;
color: $bright-orange;
}
.success {
color: #86d83a;
color: $pi-green;
}
.info {
color: #68b7c0;
Expand Down Expand Up @@ -85,21 +92,29 @@ div.panel-section {
td, th {
white-space: nowrap;
}
tr.error {
color: #c84C4c;
}
tr:hover td.invalid {
background-color: #ed5135;
}
tr i {
display: block;
margin-bottom: -0.2em;
font-size: 1.4em !important;

tr {
&.error {
color: #c84C4c;
}

&:hover td.invalid {
background-color: darken(#f05c51, 5%);
}

i {
display: block;
margin-bottom: -0.2em;
font-size: 1.4em !important;
}
}
td.invalid {
background-color: #f05c51;
box-shadow: inset 0px 0px 1px red;
color: white;

td {
&.invalid {
background-color: #f05c51;
box-shadow: inset 0px 0px 1px red;
color: white;
}
}
}

Expand All @@ -123,52 +138,6 @@ br.panels.clearfix {
clear: both;
}

table.import-settings {
background-color: transparent !important;
width: auto;

tbody tr:hover td {
background-color: #f3f3f3;
}
td {
border: 0;
border-bottom: 1px solid #eee;
text-align: left;

input {
width: 15em;
}
input[type="checkbox"] {
width: auto;
}

}
td.description {
font-weight: bold;
padding-right: 2.5em;
}
tr:first-child td {
border-top: 0;
}
tr:last-child td {
border-bottom: 0;
}
div.select2-container {
width: 13.5em;
}
div.select2-container.select2-container-disabled {
a.select2-choice, span.select2-arrow {
background-color: #d5d5d5;
}
}
input[disabled], input:disabled {
background-color: #d5d5d5;
opacity: 1;
border-color: transparent;
color: white !important;
}
}

.panel-section.import-settings {

.header-description {
Expand All @@ -177,7 +146,7 @@ table.import-settings {

span.header-error {
font-size: 0.85em;
color: $warning-red;
color: $pi-red;
}

.select2-search {
Expand Down Expand Up @@ -208,10 +177,10 @@ table.import-settings {
}

i.fa-check-circle {
color: #86d83a;
color: $pi-green;
}
i.fa-info-circle {
color: #68b7c0;
color: $pi-blue;
}
}

Expand All @@ -234,6 +203,10 @@ form.product-import, div.post-save-results, div.import-wrapper {

div.import-wrapper {

.alert-box {
margin: 0 0 1.75em;
}

.ng-hide:not(.ng-hide-animate) {
// We have to use !important here to override angular's display properties
// scss-lint:disable ImportantRule
Expand Down Expand Up @@ -281,7 +254,7 @@ div.progress-bar {

span.progress-track{
display: block;
background: #b7ea53;
background: lighten($pi-green, 10%);
height: 100%;
border-radius: 0.3em;
box-shadow: inset 0 0 3px rgba(0,0,0,0.3);
Expand Down Expand Up @@ -312,7 +285,7 @@ div.progress-bar {

span.category {
display: inline-block;
background-color: lighten($spree-blue, 10%);
background-color: $pi-blue;
color: white;
padding: 0.3em 0.6em;
margin: 0 0.4em 0.5em 0;
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/admin/variables.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ $spree-light-blue: #eff5fc;

$warning-red: #da5354;
$warning-orange: #da7f52;
$bright-orange: #ffa92e;
$medium-grey: #919191;
$pale-blue: #cee1f4;

Expand Down
1 change: 1 addition & 0 deletions app/controllers/admin/product_import_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ def import
@filepath = save_uploaded_file(params[:file])
@importer = ProductImport::ProductImporter.new(File.new(@filepath), spree_current_user, params[:settings])
@original_filename = params[:file].try(:original_filename)
@non_updatable_fields = ProductImport::EntryValidator.non_updatable_fields

check_file_errors @importer
check_spreadsheet_has_data @importer
Expand Down
41 changes: 37 additions & 4 deletions app/models/product_import/entry_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ def initialize(current_user, import_time, spreadsheet_data, editable_enterprises
@import_settings = import_settings
end

def self.non_updatable_fields
{
category: :primary_taxon_id,
unit_type: :variant_unit_scale,
variant_unit_name: :variant_unit_name,
tax_category: :tax_category_id,
shipping_category: :shipping_category_id
}
end

def validate_all(entries)
entries.each do |entry|
supplier_validation(entry)
Expand Down Expand Up @@ -177,23 +187,25 @@ def tax_and_shipping_validation(entry, type, category, index)

def product_validation(entry)
# Find product with matching supplier and name
match = Spree::Product.where(supplier_id: entry.supplier_id, name: entry.name, deleted_at: nil).first
existing_product = Spree::Product.where(supplier_id: entry.supplier_id, name: entry.name, deleted_at: nil).first

# If no matching product was found, create a new product
if match.nil?
if existing_product.nil?
mark_as_new_product(entry)
return
end

product_field_errors(entry, existing_product)

# Otherwise, if a variant exists with matching display_name and unit_value, update it
match.variants.each do |existing_variant|
existing_product.variants.each do |existing_variant|
if entry_matches_existing_variant?(entry, existing_variant) && existing_variant.deleted_at.nil?
return mark_as_existing_variant(entry, existing_variant)
end
end

# Otherwise, a variant with sufficiently matching attributes doesn't exist; create a new one
mark_as_new_variant(entry, match.id)
mark_as_new_variant(entry, existing_product.id)
end

def mark_as_new_product(entry)
Expand All @@ -220,6 +232,27 @@ def mark_as_existing_variant(entry, existing_variant)
end
end

def product_field_errors(entry, existing_product)
non_updatable_fields.each do |display_name, attribute|
next if attributes_match? attribute, existing_product, entry
next if attributes_blank? attribute, existing_product, entry

mark_as_invalid(entry, attribute: display_name, error: I18n.t('admin.product_import.model.not_updatable'))
end
end

def non_updatable_fields
EntryValidator.non_updatable_fields
end

def attributes_match?(attribute, existing_product, entry)
existing_product.send(attribute) == entry.send(attribute)
end

def attributes_blank?(attribute, existing_product, entry)
existing_product.send(attribute).blank? && entry.send(attribute).blank?
end

def permission_by_name?(supplier_name)
@editable_enterprises.key?(supplier_name)
end
Expand Down
7 changes: 7 additions & 0 deletions app/models/product_import/product_importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ def item_count
@sheet ? @sheet.last_row - 1 : 0
end

def product_field_errors?
@entries.each do |entry|
return true if entry.errors.messages.values.include? [I18n.t('admin.product_import.model.not_updatable')]
end
false
end

def reset_counts
# Return indexed data about existing product count, reset count, and updates count per supplier
@reset_counts.each do |supplier_id, values|
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/product_import/_entries_table.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
%th= heading
%tr{ng: {repeat: "(line_number, entry) in (entries | entriesFilterValid:'#{entries}')"}}
%td
%i{ng: {class: "{'fa fa-warning warning': (count(entry.errors) > 0), 'fa fa-check-circle success': (count(entry.errors) == 0)}"}}
%i{ng: {class: "{'fa fa-warning error': (count(entry.errors) > 0), 'fa fa-check-circle success': (count(entry.errors) == 0)}"}}
%td
{{line_number}}
%td{ng: {repeat: "(attribute, value) in entry.attributes", class: "{'invalid': attribute_invalid(attribute, line_number)}"}}
Expand Down
8 changes: 7 additions & 1 deletion app/views/admin/product_import/_import_review.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

%div{ng: {controller: 'ImportFeedbackCtrl'}}

- if @importer.product_field_errors?
.alert-box.warning
= t('.not_updatable_tip')
%em= @non_updatable_fields.keys.join(', ') + "."
= t('.fields_ignored')

%div.panel-section{ng: {controller: 'DropdownPanelsCtrl'}}
%div.panel-header{ng: {click: 'togglePanel()', class: '{active: active && count((entries | entriesFilterValid:"all"))}'}}
%div.header-caret
Expand All @@ -21,7 +27,7 @@
%div.panel-header{ng: {click: 'togglePanel()', class: '{active: active && count((entries | entriesFilterValid:"invalid"))}'}}
%div.header-caret
%i{ng: {class: "{'icon-chevron-down': active, 'icon-chevron-right': !active}", hide: 'count((entries | entriesFilterValid:"invalid")) == 0'}}
%div.header-icon.warning
%div.header-icon.error
%i.fa.fa-warning
%div.header-count
%strong.invalid-count
Expand Down
6 changes: 6 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ en:
conditional_blank: can't be blank if unit_type is blank
no_product: did not match any products in the database
not_found: not found in database
not_updatable: cannot be updated on existing products via product import
blank: can't be blank
products_no_permission: you do not have permission to manage products for this enterprise
inventory_no_permission: you do not have permission to create inventory for this producer
Expand Down Expand Up @@ -547,6 +548,11 @@ en:
inventory_to_reset: Existing inventory items will have their stock reset to zero
line: Line
item_line: Item line
import_review:
not_updatable_tip: "The following fields cannot be updated via bulk import for existing products:"
fields_ignored: These fields will be ignored when the imported products are saved.
entries_table:
not_updatable: This field is not updatable via bulk import on existing products
save_results:
final_results: Import final results
products_created: Products created
Expand Down
Loading

0 comments on commit dd36e27

Please sign in to comment.