mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
223 lines
10 KiB
CoffeeScript
223 lines
10 KiB
CoffeeScript
angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [
|
|
"$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey", "Columns"
|
|
($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey, Columns) ->
|
|
$scope.loading = true
|
|
|
|
$scope.initialiseVariables = ->
|
|
start = daysFromToday -7
|
|
end = daysFromToday 1
|
|
$scope.lineItems = []
|
|
$scope.filteredLineItems = []
|
|
$scope.confirmDelete = true
|
|
$scope.startDate = formatDate start
|
|
$scope.endDate = formatDate end
|
|
$scope.quickSearch = ""
|
|
$scope.bulkActions = [ { name: t("bom_actions_delete"), callback: $scope.deleteLineItems } ]
|
|
$scope.selectedBulkAction = $scope.bulkActions[0]
|
|
$scope.selectedUnitsProduct = {};
|
|
$scope.selectedUnitsVariant = {};
|
|
$scope.sharedResource = false
|
|
$scope.columns = Columns.setColumns
|
|
order_no: { name: t("bom_no"), visible: false }
|
|
full_name: { name: t("name"), visible: true }
|
|
email: { name: t("email"), visible: false }
|
|
phone: { name: t("phone"), visible: false }
|
|
order_date: { name: t("bom_date"), visible: true }
|
|
producer: { name: t("producer"), visible: true }
|
|
order_cycle: { name: t("bom_cycle"), visible: false }
|
|
hub: { name: t("bom_hub"), visible: false }
|
|
variant: { name: t("bom_variant"), visible: true }
|
|
quantity: { name: t("bom_quantity"), visible: true }
|
|
max: { name: t("bom_max"), visible: true }
|
|
final_weight_volume: { name: t("bom_final_weigth_volume"), visible: false }
|
|
price: { name: t("price"), visible: false }
|
|
$scope.initialise = ->
|
|
$scope.initialiseVariables()
|
|
authorise_api_reponse = ""
|
|
dataFetcher("/api/users/authorise_api?token=" + SpreeApiKey).then (data) ->
|
|
authorise_api_reponse = data
|
|
$scope.spree_api_key_ok = data.hasOwnProperty("success") and data["success"] == "Use of API Authorised"
|
|
if $scope.spree_api_key_ok
|
|
$http.defaults.headers.common["X-Spree-Token"] = SpreeApiKey
|
|
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_primary_producer_eq]=true").then (data) ->
|
|
$scope.suppliers = $filter('orderBy')(data, 'name')
|
|
$scope.suppliers.unshift blankOption()
|
|
dataFetcher("/api/enterprises/accessible?template=bulk_index&q[sells_in][]=own&q[sells_in][]=any").then (data) ->
|
|
$scope.distributors = $filter('orderBy')(data, 'name')
|
|
$scope.distributors.unshift blankOption()
|
|
ocFetcher = dataFetcher("/api/order_cycles/accessible?as=distributor&q[orders_close_at_gt]=#{formatDate(daysFromToday(-90))}").then (data) ->
|
|
$scope.orderCycles = data
|
|
$scope.orderCyclesByID = []
|
|
$scope.orderCyclesByID[oc.id] = oc for oc in $scope.orderCycles
|
|
$scope.orderCycles.unshift blankOption()
|
|
$scope.fetchOrders()
|
|
ocFetcher.then ->
|
|
$scope.resetSelectFilters()
|
|
else if authorise_api_reponse.hasOwnProperty("error")
|
|
$scope.api_error_msg = authorise_api_reponse("error")
|
|
else
|
|
api_error_msg = "You don't have an API key yet. An attempt was made to generate one, but you are currently not authorised, please contact your site administrator for access."
|
|
|
|
$scope.fetchOrders = ->
|
|
$scope.loading = true
|
|
dataFetcher("/admin/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) ->
|
|
$scope.resetOrders data
|
|
$scope.loading = false
|
|
|
|
$scope.resetOrders = (data) ->
|
|
$scope.orders = data
|
|
$scope.resetLineItems()
|
|
pendingChanges.removeAll()
|
|
|
|
$scope.resetLineItems = ->
|
|
$scope.lineItems = $scope.orders.reduce (lineItems,order) ->
|
|
orderWithoutLineItems = $scope.lineItemOrder order
|
|
for i,line_item of order.line_items
|
|
line_item.checked = false
|
|
line_item.supplier = $scope.matchObject $scope.suppliers, line_item.supplier, null
|
|
line_item.order = orderWithoutLineItems
|
|
line_item.original_final_weight_volume = line_item.final_weight_volume
|
|
line_item.original_quantity = line_item.quantity
|
|
line_item.original_price = line_item.price
|
|
|
|
lineItems.concat order.line_items
|
|
, []
|
|
|
|
$scope.lineItemOrder = (order) ->
|
|
lineItemOrder = angular.copy(order)
|
|
delete lineItemOrder.line_items
|
|
lineItemOrder.distributor = $scope.matchObject $scope.distributors, order.distributor, null
|
|
lineItemOrder.order_cycle = $scope.matchObject $scope.orderCycles, order.order_cycle, null
|
|
lineItemOrder
|
|
|
|
$scope.matchObject = (list, testObject, noMatch) ->
|
|
for i, object of list
|
|
if angular.equals(object, testObject)
|
|
return object
|
|
return noMatch
|
|
|
|
$scope.deleteLineItem = (lineItem) ->
|
|
if ($scope.confirmDelete && confirm("Are you sure?")) || !$scope.confirmDelete
|
|
$http(
|
|
method: "DELETE"
|
|
url: "/api/orders/" + lineItem.order.number + "/line_items/" + lineItem.id
|
|
).success (data) ->
|
|
$scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1
|
|
|
|
$scope.deleteLineItems = (lineItems) ->
|
|
existingState = $scope.confirmDelete
|
|
$scope.confirmDelete = false
|
|
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
|
$scope.confirmDelete = existingState
|
|
|
|
$scope.submit = ->
|
|
if $scope.bulk_order_form.$valid
|
|
pendingChanges.submitAll()
|
|
else
|
|
alert "Some errors must be resolved be before you can update orders.\nAny fields with red borders contain errors."
|
|
|
|
$scope.allBoxesChecked = ->
|
|
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
|
|
count + (if lineItem.checked then 1 else 0 )
|
|
, 0
|
|
checkedCount == $scope.filteredLineItems.length
|
|
|
|
$scope.toggleAllCheckboxes = ->
|
|
changeTo = !$scope.allBoxesChecked()
|
|
lineItem.checked = changeTo for lineItem in $scope.filteredLineItems
|
|
|
|
$scope.setSelectedUnitsVariant = (unitsProduct,unitsVariant) ->
|
|
$scope.selectedUnitsProduct = unitsProduct
|
|
$scope.selectedUnitsVariant = unitsVariant
|
|
|
|
$scope.sumUnitValues = ->
|
|
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
|
sum = sum + lineItem.final_weight_volume
|
|
, 0
|
|
|
|
$scope.sumMaxUnitValues = ->
|
|
sum = $scope.filteredLineItems.reduce (sum,lineItem) ->
|
|
sum = sum + Math.max(lineItem.max_quantity,lineItem.original_quantity) * lineItem.units_variant.unit_value
|
|
, 0
|
|
|
|
$scope.allFinalWeightVolumesPresent = ->
|
|
for i,lineItem of $scope.filteredLineItems
|
|
return false if !lineItem.hasOwnProperty('final_weight_volume') || !(lineItem.final_weight_volume > 0)
|
|
true
|
|
|
|
# How is this different to OptionValueNamer#name?
|
|
# Should it be extracted to that class or VariantUnitManager?
|
|
$scope.formattedValueWithUnitName = (value, unitsProduct, unitsVariant) ->
|
|
# A Units Variant is an API object which holds unit properies of a variant
|
|
if unitsProduct.hasOwnProperty("variant_unit") && (unitsProduct.variant_unit == "weight" || unitsProduct.variant_unit == "volume") && value > 0
|
|
scale = VariantUnitManager.getScale(value, unitsProduct.variant_unit)
|
|
Math.round(value/scale * 1000)/1000 + " " + VariantUnitManager.getUnitName(scale, unitsProduct.variant_unit)
|
|
else
|
|
''
|
|
|
|
$scope.fulfilled = (sumOfUnitValues) ->
|
|
# A Units Variant is an API object which holds unit properies of a variant
|
|
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
|
|
$scope.selectedUnitsProduct.hasOwnProperty("variant_unit") &&
|
|
( $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume" )
|
|
Math.round( sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size * 1000)/1000
|
|
else
|
|
''
|
|
|
|
$scope.unitsVariantSelected = ->
|
|
!angular.equals($scope.selectedUnitsVariant,{})
|
|
|
|
$scope.resetSelectFilters = ->
|
|
$scope.distributorFilter = $scope.distributors[0].id
|
|
$scope.supplierFilter = $scope.suppliers[0].id
|
|
$scope.orderCycleFilter = $scope.orderCycles[0].id
|
|
$scope.quickSearch = ""
|
|
|
|
$scope.weightAdjustedPrice = (lineItem) ->
|
|
if lineItem.final_weight_volume > 0
|
|
unit_value = lineItem.final_weight_volume / lineItem.quantity
|
|
original_unit_value = lineItem.original_final_weight_volume / lineItem.original_quantity
|
|
lineItem.price = lineItem.original_price * (unit_value / original_unit_value)
|
|
|
|
$scope.unitValueLessThanZero = (lineItem) ->
|
|
if lineItem.units_variant.unit_value <= 0
|
|
true
|
|
else
|
|
false
|
|
|
|
$scope.updateOnQuantity = (lineItem) ->
|
|
if lineItem.quantity > 0
|
|
lineItem.final_weight_volume = lineItem.original_final_weight_volume * lineItem.quantity / lineItem.original_quantity
|
|
$scope.weightAdjustedPrice(lineItem)
|
|
|
|
$scope.$watch "orderCycleFilter", (newVal, oldVal) ->
|
|
unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal)
|
|
$scope.startDate = $scope.orderCyclesByID[$scope.orderCycleFilter].first_order
|
|
$scope.endDate = $scope.orderCyclesByID[$scope.orderCycleFilter].last_order
|
|
]
|
|
|
|
daysFromToday = (days) ->
|
|
now = new Date
|
|
now.setHours(0)
|
|
now.setMinutes(0)
|
|
now.setSeconds(0)
|
|
now.setDate( now.getDate() + days )
|
|
now
|
|
|
|
formatDate = (date) ->
|
|
year = date.getFullYear()
|
|
month = twoDigitNumber date.getMonth() + 1
|
|
day = twoDigitNumber date.getDate()
|
|
return year + "-" + month + "-" + day
|
|
|
|
formatTime = (date) ->
|
|
hours = twoDigitNumber date.getHours()
|
|
mins = twoDigitNumber date.getMinutes()
|
|
secs = twoDigitNumber date.getSeconds()
|
|
return hours + ":" + mins + ":" + secs
|
|
|
|
twoDigitNumber = (number) ->
|
|
twoDigits = "" + number
|
|
twoDigits = ("0" + number) if number < 10
|
|
twoDigits
|