Fix legacy bulk edit products UI

This commit is contained in:
Gaetan Craig-Riou
2024-07-08 15:37:45 +10:00
parent b1b534aa1b
commit 6ff9650eaf
7 changed files with 134 additions and 162 deletions

View File

@@ -187,9 +187,8 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
product.variants.length > 0
$scope.hasUnit = (product) ->
product.variant_unit_with_scale?
$scope.hasUnit = (variant) ->
variant.variant_unit_with_scale?
$scope.variantSaved = (variant) ->
variant.hasOwnProperty('id') && variant.id > 0
@@ -242,32 +241,28 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$window.location = destination
$scope.packProduct = (product) ->
if product.variant_unit_with_scale
match = product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
product.variant_unit = match[1]
product.variant_unit_scale = parseFloat(match[2])
else
product.variant_unit = product.variant_unit_with_scale
product.variant_unit_scale = null
else
product.variant_unit = product.variant_unit_scale = null
if product.variants
for id, variant of product.variants
$scope.packVariant product, variant
$scope.packVariant variant
$scope.packVariant = (product, variant) ->
$scope.packVariant = (variant) ->
if variant.variant_unit_with_scale
match = variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
variant.variant_unit = match[1]
variant.variant_unit_scale = parseFloat(match[2])
else
variant.variant_unit = variant.variant_unit_with_scale
variant.variant_unit_scale = null
if variant.hasOwnProperty("unit_value_with_description")
match = variant.unit_value_with_description.match(/^([\d\.\,]+(?= |$)|)( |)(.*)$/)
if match
product = BulkProducts.find product.id
variant.unit_value = parseFloat(match[1].replace(",", "."))
variant.unit_value = null if isNaN(variant.unit_value)
if variant.unit_value && product.variant_unit_scale
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, product.variant_unit_scale, 2))
if variant.unit_value && variant.variant_unit_scale
variant.unit_value = parseFloat(window.bigDecimal.multiply(variant.unit_value, variant.variant_unit_scale, 2))
variant.unit_description = match[3]
$scope.incrementLimit = ->
@@ -321,13 +316,6 @@ filterSubmitProducts = (productsToFilter) ->
if product.hasOwnProperty("price")
filteredProduct.price = product.price
hasUpdatableProperty = true
if product.hasOwnProperty("variant_unit_with_scale")
filteredProduct.variant_unit = product.variant_unit
filteredProduct.variant_unit_scale = product.variant_unit_scale
hasUpdatableProperty = true
if product.hasOwnProperty("variant_unit_name")
filteredProduct.variant_unit_name = product.variant_unit_name
hasUpdatableProperty = true
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_hand = product.on_hand
hasUpdatableProperty = true
@@ -383,6 +371,14 @@ filterSubmitVariant = (variant) ->
if variant.hasOwnProperty("producer_id")
filteredVariant.supplier_id = variant.producer_id
hasUpdatableProperty = true
if variant.hasOwnProperty("variant_unit_with_scale")
filteredVariant.variant_unit = variant.variant_unit
filteredVariant.variant_unit_scale = variant.variant_unit_scale
hasUpdatableProperty = true
if variant.hasOwnProperty("variant_unit_name")
filteredVariant.variant_unit_name = variant.variant_unit_name
hasUpdatableProperty = true
{filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty}

View File

@@ -4,31 +4,30 @@ angular.module("ofn.admin").directive "ofnDisplayAs", (OptionValueNamer) ->
scope.$watchCollection ->
return [
scope.$eval(attrs.ofnDisplayAs).unit_value_with_description
scope.product.variant_unit_name
scope.product.variant_unit_with_scale
scope.variant.variant_unit_name
scope.variant.variant_unit_with_scale
]
, ->
[variant_unit, variant_unit_scale] = productUnitProperties()
[unit_value, unit_description] = variantUnitProperties(variant_unit_scale)
variant_object =
variant_object =
unit_value: unit_value
unit_description: unit_description
product:
variant_unit_scale: variant_unit_scale
variant_unit: variant_unit
variant_unit_name: scope.product.variant_unit_name
variant_unit_scale: variant_unit_scale
variant_unit: variant_unit
variant_unit_name: scope.variant.variant_unit_name
scope.placeholder_text = new OptionValueNamer(variant_object).name()
productUnitProperties = ->
# get relevant product properties
if scope.product.variant_unit_with_scale?
match = scope.product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if scope.variant.variant_unit_with_scale?
match = scope.variant.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
variant_unit = match[1]
variant_unit_scale = parseFloat(match[2])
else
variant_unit = scope.product.variant_unit_with_scale
variant_unit = scope.variant.variant_unit_with_scale
variant_unit_scale = null
else
variant_unit = variant_unit_scale = null
@@ -45,4 +44,4 @@ angular.module("ofn.admin").directive "ofnDisplayAs", (OptionValueNamer) ->
unit_value = null if isNaN(unit_value)
unit_value *= variant_unit_scale if unit_value && variant_unit_scale
unit_description = match[3]
[unit_value, unit_description]
[unit_value, unit_description]

View File

@@ -1,8 +0,0 @@
angular.module("ofn.admin").directive "ofnMaintainUnitScale", ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
scope.$watch 'product.variant_unit_with_scale', (newValue, oldValue) ->
if not (oldValue == newValue)
# Triggers track-variant directive to track the unit_value, so that changes to the unit are passed to the server
ngModel.$setViewValue ngModel.$viewValue

View File

@@ -1,8 +0,0 @@
angular.module("ofn.admin").directive "ofnTrackMaster", (DirtyProducts) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
ngModel.$parsers.push (viewValue) ->
if ngModel.$dirty
DirtyProducts.addMasterProperty scope.product.id, scope.product.master.id, attrs.ofnTrackMaster, viewValue
scope.displayDirtyProducts()
viewValue

View File

@@ -11,9 +11,6 @@
%td.name{ 'ng-show' => 'columns.name.visible' }
%input{ 'ng-model' => "product.name", :name => 'product_name', 'ofn-track-product' => 'name', :type => 'text' }
%td.unit{ 'ng-show' => 'columns.unit.visible' }
%select.no-search{ "data-controller": "tom-select", 'ng-model' => 'product.variant_unit_with_scale', :name => 'variant_unit_with_scale', 'ofn-track-product' => 'variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
%input{ 'ng-model' => 'product.master.unit_value_with_description', :name => 'master_unit_value_with_description', 'ofn-track-master' => 'unit_value_with_description', :type => 'text', :placeholder => 'value', 'ng-show' => "!hasVariants(product) && hasUnit(product)", 'ofn-maintain-unit-scale' => true }
%input{ 'ng-model' => 'product.variant_unit_name', :name => 'variant_unit_name', 'ofn-track-product' => 'variant_unit_name', :placeholder => 'unit', 'ng-show' => "product.variant_unit_with_scale == 'items'", :type => 'text' }
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
%td.price{ 'ng-show' => 'columns.price.visible' }
%input{ 'ng-model' => 'product.price', 'ofn-decimal' => :true, :name => 'price', 'ofn-track-product' => 'price', :type => 'text', 'ng-hide' => 'hasVariants(product)' }

View File

@@ -10,7 +10,9 @@
%td{ 'ng-show' => 'columns.name.visible' }
%input{ 'ng-model' => 'variant.display_name', :name => 'variant_display_name', 'ofn-track-variant' => 'display_name', :type => 'text', placeholder: "{{ product.name }}" }
%td.unit_value{ 'ng-show' => 'columns.unit.visible' }
%input{ 'ng-model' => 'variant.unit_value_with_description', :name => 'variant_unit_value_with_description', 'ofn-track-variant' => 'unit_value_with_description', :type => 'text', 'ofn-maintain-unit-scale' => true }
%select.no-search{ "data-controller": "tom-select", 'ng-model' => 'variant.variant_unit_with_scale', :name => 'variant_unit_with_scale', 'ofn-track-variant' => 'variant_unit_with_scale', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
%input{ 'ng-model' => 'variant.unit_value_with_description', :name => 'variant_unit_value_with_description', 'ofn-track-variant' => 'unit_value_with_description', :type => 'text', :placeholder => 'value', 'ng-show' => "hasUnit(variant)" }
%input{ 'ng-model' => 'variant.variant_unit_name', :name => 'variant_unit_name', 'ofn-track-variant' => 'variant_unit_name', :placeholder => 'unit', 'ng-show' => "variant.variant_unit_with_scale == 'items'", :type => 'text' }
%td.display_as{ 'ng-show' => 'columns.unit.visible' }
%input{ 'ofn-display-as' => 'variant', 'ng-model' => 'variant.display_as', name: 'variant_display_as', 'ofn-track-variant' => 'display_as', type: 'text', placeholder: '{{ placeholder_text }}' }
%td{ 'ng-show' => 'columns.price.visible' }

View File

@@ -156,14 +156,20 @@ describe "filtering products for submission to database", ->
it "returns variant_unit_with_scale as variant_unit and variant_unit_scale", ->
testProduct =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'weight_1'
variants: [
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'weight_1'
]
expect(filterSubmitProducts([testProduct])).toEqual [
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variants_attributes: [
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
]
]
it "returns stock properties of a product if no variant is provided", ->
@@ -204,18 +210,15 @@ describe "filtering products for submission to database", ->
display_as: "bottle"
display_name: "nothing"
producer_id: 5
variant_unit: 'volume'
variant_unit_scale: 1
variant_unit_name: 'loaf'
variant_unit_with_scale: 'volume_1'
]
variant_unit: 'volume'
variant_unit_scale: 1
variant_unit_name: 'loaf'
variant_unit_with_scale: 'volume_1'
expect(filterSubmitProducts([testProduct])).toEqual [
id: 1
name: "TestProduct"
variant_unit: 'volume'
variant_unit_scale: 1
variant_unit_name: 'loaf'
variants_attributes: [
id: 1
on_hand: 2
@@ -226,6 +229,9 @@ describe "filtering products for submission to database", ->
display_as: "bottle"
display_name: "nothing"
supplier_id: 5
variant_unit: 'volume'
variant_unit_scale: 1
variant_unit_name: 'loaf'
]
]
@@ -281,7 +287,6 @@ describe "AdminProductEditCtrl", ->
$scope.initialise()
expect($scope.q.query).toBe query
expect($scope.q.producerFilter).toBe producerFilter
expect($scope.q.categoryFilter).toBe categoryFilter
expect($scope.q.sorting).toBe sorting
expect($scope.q.importDateFilter).toBe importDateFilter
@@ -476,13 +481,13 @@ describe "AdminProductEditCtrl", ->
describe "determining whether a product has a unit", ->
it "returns true when it does", ->
product =
variant_unit_with_scale: 'weight_1000'
expect($scope.hasUnit(product)).toBe(true)
variant ={variant_unit_with_scale: 'weight_1000'}
expect($scope.hasUnit(variant)).toBe(true)
it "returns false when its unit is undefined", ->
product = {}
expect($scope.hasUnit(product)).toBe(false)
variant = {}
expect($scope.hasUnit(variant)).toBe(false)
describe "determining whether a variant has been saved", ->
@@ -505,51 +510,6 @@ describe "AdminProductEditCtrl", ->
window.bigDecimal = jasmine.createSpyObj "bigDecimal", ["multiply"]
window.bigDecimal.multiply.and.callFake (a, b, c) -> (a * b).toFixed(c)
it "extracts variant_unit_with_scale into variant_unit and variant_unit_scale", ->
testProduct =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'volume_1000'
$scope.packProduct(testProduct)
expect(testProduct).toEqual
id: 1
variant_unit: 'volume'
variant_unit_scale: 1000
variant_unit_with_scale: 'volume_1000'
it "extracts a null value into null variant_unit and variant_unit_scale", ->
testProduct =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: null
$scope.packProduct(testProduct)
expect(testProduct).toEqual
id: 1
variant_unit: null
variant_unit_scale: null
variant_unit_with_scale: null
it "extracts when variant_unit_with_scale is 'items'", ->
testProduct =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'items'
$scope.packProduct(testProduct)
expect(testProduct).toEqual
id: 1
variant_unit: 'items'
variant_unit_scale: null
variant_unit_with_scale: 'items'
it "packs each variant", ->
spyOn $scope, "packVariant"
testVariant = {id: 1}
@@ -559,120 +519,154 @@ describe "AdminProductEditCtrl", ->
$scope.packProduct(testProduct)
expect($scope.packVariant).toHaveBeenCalledWith(testProduct, testVariant)
expect($scope.packVariant).toHaveBeenCalledWith(testVariant)
describe "packing variants", ->
beforeEach ->
window.bigDecimal = jasmine.createSpyObj "bigDecimal", ["multiply"]
window.bigDecimal.multiply.and.callFake (a, b, c) -> (a * b).toFixed(c)
it "extracts variant_unit_with_scale into variant_unit and variant_unit_scale", ->
testVariant =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'volume_1000'
$scope.packVariant(testVariant)
expect(testVariant).toEqual
id: 1
variant_unit: 'volume'
variant_unit_scale: 1000
variant_unit_with_scale: 'volume_1000'
it "extracts when variant_unit_with_scale is 'items'", ->
testVariant =
id: 1
variant_unit: 'weight'
variant_unit_scale: 1
variant_unit_with_scale: 'items'
$scope.packVariant(testVariant)
expect(testVariant).toEqual
id: 1
variant_unit: 'items'
variant_unit_scale: null
variant_unit_with_scale: 'items'
it "extracts unit_value and unit_description from unit_value_with_description", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
testVariant = {unit_value_with_description: "250.5 (bottle)"}
BulkProducts.products = [testProduct]
$scope.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 250.5
unit_description: "(bottle)"
unit_value_with_description: "250.5 (bottle)"
it "extracts into unit_value when only a number is provided", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
testVariant = {unit_value_with_description: "250.5"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
testVariant = {variant_unit_scale: 1.0, unit_value_with_description: "250.5"}
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 250.5
unit_description: ''
unit_value_with_description: "250.5"
variant_unit_scale: 1.0
it "extracts into unit_description when only a string is provided", ->
testProduct = {id: 123}
testVariant = {unit_value_with_description: "Medium"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: null
unit_description: 'Medium'
unit_value_with_description: "Medium"
it "extracts into unit_description when a string starting with a number is provided", ->
testProduct = {id: 123}
testVariant = {unit_value_with_description: "1kg"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: null
unit_description: '1kg'
unit_value_with_description: "1kg"
it "sets blank values when no value provided", ->
testProduct = {id: 123}
testVariant = {unit_value_with_description: ""}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: null
unit_description: ''
unit_value_with_description: ""
it "sets nothing when the field is undefined", ->
testProduct = {id: 123}
testVariant = {}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
expect(testVariant).toEqual {}
$scope.packVariant(testVariant)
expect(testVariant).toEqual({})
it "sets zero when the field is zero", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
testVariant = {unit_value_with_description: "0"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
testVariant = {variant_unit_scale: 1.0, unit_value_with_description: "0"}
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 0
unit_description: ''
unit_value_with_description: "0"
variant_unit_scale: 1.0
it "converts value from chosen unit to base unit", ->
testProduct = {id: 123, variant_unit_scale: 1000}
testVariant = {unit_value_with_description: "250.5"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
testVariant = {variant_unit_scale: 1000, unit_value_with_description: "250.5"}
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 250500
unit_description: ''
unit_value_with_description: "250.5"
variant_unit_scale: 1000
it "does not convert value when using a non-scaled unit", ->
testProduct = {id: 123}
testVariant = {unit_value_with_description: "12"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 12
unit_description: ''
unit_value_with_description: "12"
it "converts unit_value into a float when a comma separated number is provided", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
testVariant = {unit_value_with_description: "250,5"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
testVariant = {variant_unit_scale: 1.0, unit_value_with_description: "250,5"}
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 250.5
unit_description: ''
unit_value_with_description: "250,5"
variant_unit_scale: 1.0
it "rounds off the unit_value upto 2 decimal places", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
testVariant = {unit_value_with_description: "1234.567"}
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
testVariant = {variant_unit_scale: 1.0, unit_value_with_description: "1234.567"}
$scope.packVariant(testVariant)
expect(testVariant).toEqual
unit_value: 1234.57
unit_description: ''
unit_value_with_description: "1234.567"
variant_unit_scale: 1.0
describe "filtering products", ->