From cc666bcf43f024287aef97c4041dc94b010201db Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 7 Sep 2022 16:36:13 +0000 Subject: [PATCH 1/9] [IMP] delivery_hibou: weight or volumetric package selection --- delivery_hibou/models/delivery.py | 33 ++++++++++++- delivery_hibou/models/stock.py | 12 +++++ delivery_hibou/tests/test_delivery_hibou.py | 55 +++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index c604c02a..fd6fb9e7 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -17,9 +17,40 @@ class DeliveryCarrier(models.Model): string='Procurement Priority', help='Priority for this carrier. Will affect pickings ' 'and procurements related to this carrier.') + package_by_field = fields.Selection([ + ('', 'Use Default Package Type'), + ('weight', 'Weight'), + ('volume', 'Volume'), + ], string='Packaging by Product Field') + + # Package selection + def get_package_type_for_order(self, order): + if self.package_by_field == 'weight': + return self._get_package_type_for_order(order, 'max_weight', 'weight') + elif self.package_by_field == 'volume': + return self._get_package_type_for_order(order, 'package_volume', 'volume') + attr = getattr(self, '%s_default_packaging_id' % (self.delivery_type, ), None) + if attr: + return attr() + attr = getattr(self, '%s_default_package_type_id' % (self.delivery_type, ), None) + if attr: + return attr() + return self.env['stock.package.type'] + + def _get_package_type_for_order(self, order, package_type_field, product_field): + order_total = sum(order.order_line.filtered(lambda ol: ol.product_id.type in ('product', 'consu')).mapped(lambda ol: ol.product_id[product_field] * ol.product_uom_qty)) + if order_total: + package_types = self.env['stock.package.type'].search([ + ('package_carrier_type', 'in', ('none', False, self.delivery_type)), + ('use_in_package_selection', '=', True), + ], order=package_type_field) + package_type = None + for package_type in package_types: + if package_type[package_type_field] >= order_total: + return package_type + return package_types if not package_type else package_type # Utility - def get_insurance_value(self, order=None, picking=None, package=None): value = 0.0 if order: diff --git a/delivery_hibou/models/stock.py b/delivery_hibou/models/stock.py index 050a7f03..b045dc4b 100644 --- a/delivery_hibou/models/stock.py +++ b/delivery_hibou/models/stock.py @@ -2,6 +2,18 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError +class StockPackageType(models.Model): + _inherit = 'stock.package.type' + + use_in_package_selection = fields.Boolean() + package_volume = fields.Float(compute='_compute_package_volume', store=True) + + @api.depends('packaging_length', 'width', 'height') + def _compute_package_volume(self): + for pt in self: + pt.package_volume = pt.packaging_length * pt.width * pt.height + + class StockQuantPackage(models.Model): _inherit = 'stock.quant.package' diff --git a/delivery_hibou/tests/test_delivery_hibou.py b/delivery_hibou/tests/test_delivery_hibou.py index 1dd9aa99..43d1de71 100644 --- a/delivery_hibou/tests/test_delivery_hibou.py +++ b/delivery_hibou/tests/test_delivery_hibou.py @@ -7,6 +7,11 @@ class TestDeliveryHibou(common.TransactionCase): super(TestDeliveryHibou, self).setUp() self.partner = self.env.ref('base.res_partner_address_13') self.product = self.env.ref('product.product_product_7') + self.product.write({ + 'type': 'product', + 'weight': 1.0, + 'volume': 15.0, + }) # Create Shipping Account self.shipping_account = self.env['partner.shipping.account'].create({ 'name': '123123', @@ -20,6 +25,26 @@ class TestDeliveryHibou(common.TransactionCase): self.carrier = self.env['delivery.carrier'].create({ 'name': 'Test Carrier1', 'product_id': self.delivery_product.id, + 'delivery_type': 'fixed', + }) + # update all other package types to have + self.package_type_large = self.env['stock.package.type'].create({ + 'name': 'Large 15x15x15', + 'packaging_length': 15.0, + 'height': 15.0, + 'width': 15.0, + 'max_weight': 50.0, + 'package_carrier_type': 'none', + 'use_in_package_selection': True, + }) + self.package_type_small = self.env['stock.package.type'].create({ + 'name': 'Small 2x2x4', + 'packaging_length': 4.0, + 'height': 2.0, + 'width': 2.0, + 'max_weight': 1.0, + 'package_carrier_type': 'none', + 'use_in_package_selection': True, }) def test_delivery_hibou(self): @@ -40,6 +65,7 @@ class TestDeliveryHibou(common.TransactionCase): 'shipping_account_id': self.shipping_account.id, 'order_line': [(0, 0, { 'product_id': self.product.id, + 'product_uom_qty': 2.0, })] }) self.assertFalse(sale_order.carrier_id) @@ -62,6 +88,35 @@ class TestDeliveryHibou(common.TransactionCase): self.assertEqual(sale_order.picking_ids.shipping_account_id, self.shipping_account) self.assertEqual(sale_order.carrier_id.get_third_party_account(order=sale_order), self.shipping_account) + # Test Package selection + default_package_type = sale_order.carrier_id.get_package_type_for_order(sale_order) + self.assertFalse(default_package_type, 'Fixed should not have a default packaging type.') + + # by product weight + sale_order.carrier_id.package_by_field = 'weight' + + default_package_type = sale_order.carrier_id.get_package_type_for_order(sale_order) + self.assertTrue(default_package_type) + self.assertEqual(default_package_type, self.package_type_large) + + # change qty ordered to try to get the small package type + sale_order.order_line.write({ + 'product_uom_qty': 1.0, + }) + default_package_type = sale_order.carrier_id.get_package_type_for_order(sale_order) + self.assertEqual(default_package_type, self.package_type_small) + + # by product volume + sale_order.carrier_id.package_by_field = 'volume' + default_package_type = sale_order.carrier_id.get_package_type_for_order(sale_order) + self.assertEqual(default_package_type, self.package_type_small) + + sale_order.order_line.write({ + 'product_uom_qty': 2.0, + }) + default_package_type = sale_order.carrier_id.get_package_type_for_order(sale_order) + self.assertEqual(default_package_type, self.package_type_large) + # Test attn test_ref = 'TEST100' self.assertEqual(sale_order.carrier_id.get_attn(order=sale_order), False) From a35f412a8869ccac77df2cdfec7dd3d19cd549ae Mon Sep 17 00:00:00 2001 From: Cedric Collins Date: Wed, 31 Aug 2022 23:02:37 -0500 Subject: [PATCH 2/9] [FIX] delivery_hibou: remove implicit dependency on `sale_sourced_by_line` --- delivery_hibou/models/delivery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index fd6fb9e7..d0f9ae10 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -254,7 +254,7 @@ class DeliveryCarrier(models.Model): else: if packages: raise UserError(_('Cannot rate package without picking.')) - self = self.with_context(date_planned=(order.date_planned or fields.Datetime.now())) + self = self.with_context(date_planned=('date_planned' in order._fields and order.date_planned or fields.Datetime.now())) res = [] for carrier in self: From 8e7f7ef04bdaf6a9596f50c8901c76be638e1032 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 14 Sep 2022 00:41:30 +0000 Subject: [PATCH 3/9] [IMP] delivery_hibou: add get_to_ship_picking_packages utility I find that this must be in the pre-amble of iteration on pickings to ensure they have the correct output when package carriers are in play. Specifically, we need to be able to 're-enter' the send to shipper method with a new package for a different carrier and not even try to ship if all packages have tracking numbers. --- delivery_hibou/models/delivery.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index d0f9ae10..b3f928e2 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -51,6 +51,20 @@ class DeliveryCarrier(models.Model): return package_types if not package_type else package_type # Utility + def get_to_ship_picking_packages(self, picking): + # Will return a stock.quant.package record set if the picking has packages + # in the case of multi-packing and none applicable, will return None + # Additionally, will not return packages that have a tracking number (because they have shipped) + picking_packages = picking.package_ids + package_carriers = picking_packages.mapped('carrier_id') + if package_carriers: + # only ship ours + picking_packages = picking_packages.filtered(lambda p: p.carrier_id == self and not p.carrier_tracking_ref) + + if package_carriers and not picking_packages: + return None + return picking_packages + def get_insurance_value(self, order=None, picking=None, package=None): value = 0.0 if order: From 4ed68bbf7f9a6d84708ec0e4ce0874c172872d38 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Mon, 19 Sep 2022 23:16:06 +0000 Subject: [PATCH 4/9] [ADD] delivery_partner_purolator: add for 15.0 --- delivery_partner_purolator/README.rst | 22 +++++++++++++++++++ delivery_partner_purolator/__init__.py | 1 + delivery_partner_purolator/__manifest__.py | 17 ++++++++++++++ delivery_partner_purolator/models/__init__.py | 1 + delivery_partner_purolator/models/delivery.py | 7 ++++++ delivery_partner_purolator/tests/__init__.py | 1 + .../tests/test_purolator_account.py | 20 +++++++++++++++++ 7 files changed, 69 insertions(+) create mode 100644 delivery_partner_purolator/README.rst create mode 100644 delivery_partner_purolator/__init__.py create mode 100755 delivery_partner_purolator/__manifest__.py create mode 100644 delivery_partner_purolator/models/__init__.py create mode 100644 delivery_partner_purolator/models/delivery.py create mode 100644 delivery_partner_purolator/tests/__init__.py create mode 100644 delivery_partner_purolator/tests/test_purolator_account.py diff --git a/delivery_partner_purolator/README.rst b/delivery_partner_purolator/README.rst new file mode 100644 index 00000000..7438616a --- /dev/null +++ b/delivery_partner_purolator/README.rst @@ -0,0 +1,22 @@ +******************************************* +Hibou - Purolator Partner Shipping Accounts +******************************************* + +Adds Purolator shipping accounts. + +For more information and add-ons, visit `Hibou.io `_. + + +============= +Main Features +============= + +* Adds Purolator to the delivery type selection field. + +======= +License +======= + +Please see `LICENSE `_. + +Copyright Hibou Corp. 2022 diff --git a/delivery_partner_purolator/__init__.py b/delivery_partner_purolator/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/delivery_partner_purolator/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/delivery_partner_purolator/__manifest__.py b/delivery_partner_purolator/__manifest__.py new file mode 100755 index 00000000..9419f4ac --- /dev/null +++ b/delivery_partner_purolator/__manifest__.py @@ -0,0 +1,17 @@ +{ + 'name': 'Purolator Partner Shipping Accounts', + 'author': 'Hibou Corp. ', + 'version': '15.0.1.0.0', + 'license': 'LGPL-3', + 'category': 'Stock', + 'sequence': 95, + 'summary': 'Purolator Partner Shipping Accounts', + 'website': 'https://hibou.io/', + 'depends': [ + 'delivery_partner', + ], + 'data': [ + ], + 'installable': True, + 'application': False, +} diff --git a/delivery_partner_purolator/models/__init__.py b/delivery_partner_purolator/models/__init__.py new file mode 100644 index 00000000..be8cabd6 --- /dev/null +++ b/delivery_partner_purolator/models/__init__.py @@ -0,0 +1 @@ +from . import delivery diff --git a/delivery_partner_purolator/models/delivery.py b/delivery_partner_purolator/models/delivery.py new file mode 100644 index 00000000..5f1a03ee --- /dev/null +++ b/delivery_partner_purolator/models/delivery.py @@ -0,0 +1,7 @@ +from odoo import fields, models + + +class PartnerShippingAccount(models.Model): + _inherit = 'partner.shipping.account' + + delivery_type = fields.Selection(selection_add=[('purolator', 'Purolator')], ondelete={'purolator': 'set default'}) diff --git a/delivery_partner_purolator/tests/__init__.py b/delivery_partner_purolator/tests/__init__.py new file mode 100644 index 00000000..edd5b88a --- /dev/null +++ b/delivery_partner_purolator/tests/__init__.py @@ -0,0 +1 @@ +from . import test_purolator_account diff --git a/delivery_partner_purolator/tests/test_purolator_account.py b/delivery_partner_purolator/tests/test_purolator_account.py new file mode 100644 index 00000000..c52c917e --- /dev/null +++ b/delivery_partner_purolator/tests/test_purolator_account.py @@ -0,0 +1,20 @@ +from odoo.tests.common import TransactionCase +from odoo.exceptions import ValidationError + + +class TestAccount(TransactionCase): + + def setUp(self): + super(TestAccount, self).setUp() + self.PartnerShippingAccount = self.env['partner.shipping.account'] + self.partner = self.env.ref('base.res_partner_12') + + def test_purolator_account_information(self): + # Create object and confirm that validation error raises if fedex account is blank or not 8 digits + _ = self.PartnerShippingAccount.create({ + 'name': '123456789', + 'description': 'Test Account', + 'partner_id': self.partner.id, + 'delivery_type': 'purolator', + 'note': 'This is a note' + }) From 358feb34e1fb96754959dee14325a03f12494e0f Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 20 Sep 2022 00:48:16 +0000 Subject: [PATCH 5/9] [FIX] delivery_hibou: default attr for package_type --- delivery_hibou/models/delivery.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index b3f928e2..cc19fe83 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -31,10 +31,10 @@ class DeliveryCarrier(models.Model): return self._get_package_type_for_order(order, 'package_volume', 'volume') attr = getattr(self, '%s_default_packaging_id' % (self.delivery_type, ), None) if attr: - return attr() + return attr attr = getattr(self, '%s_default_package_type_id' % (self.delivery_type, ), None) if attr: - return attr() + return attr return self.env['stock.package.type'] def _get_package_type_for_order(self, order, package_type_field, product_field): From b08e05df1707b7f00bd7714fc75eaa692341de7e Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 20 Sep 2022 02:52:35 +0000 Subject: [PATCH 6/9] [IMP] delivery_hibou: logging around package types, views Fix, default attr return. --- delivery_hibou/models/delivery.py | 25 +++++++++++++++++++++---- delivery_hibou/views/stock_views.xml | 13 +++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index cc19fe83..220eaae3 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -1,9 +1,13 @@ +import logging from odoo import api, fields, models, _ from odoo.tools.float_utils import float_compare from odoo.addons.stock.models.stock_move import PROCUREMENT_PRIORITIES from odoo.exceptions import UserError +_logger = logging.getLogger(__name__) + + class DeliveryCarrier(models.Model): _inherit = 'delivery.carrier' @@ -26,19 +30,31 @@ class DeliveryCarrier(models.Model): # Package selection def get_package_type_for_order(self, order): if self.package_by_field == 'weight': - return self._get_package_type_for_order(order, 'max_weight', 'weight') + res = self._get_package_type_for_order(order, 'max_weight', 'weight') + _logger.info(' get_package_type_for_order package by weight (%s) %s' % (res.id, res.name)) + return res elif self.package_by_field == 'volume': - return self._get_package_type_for_order(order, 'package_volume', 'volume') + res = self._get_package_type_for_order(order, 'package_volume', 'volume') + _logger.info(' get_package_type_for_order package by volume (%s) %s' % (res.id, res.name)) + return res attr = getattr(self, '%s_default_packaging_id' % (self.delivery_type, ), None) if attr: + _logger.info(' get_package_type_for_order package by default_packaging_id (%s) %s' % (attr.id, attr.name)) return attr attr = getattr(self, '%s_default_package_type_id' % (self.delivery_type, ), None) if attr: + _logger.info(' get_package_type_for_order package by default_package_type_id (%s) %s' % (attr.id, attr.name)) return attr + _logger.info(' package by NULL') return self.env['stock.package.type'] def _get_package_type_for_order(self, order, package_type_field, product_field): - order_total = sum(order.order_line.filtered(lambda ol: ol.product_id.type in ('product', 'consu')).mapped(lambda ol: ol.product_id[product_field] * ol.product_uom_qty)) + # NOTE do not optimize this into non-loop. + # this may be an orderfake + order_total = 0.0 + for ol in order.order_line.filtered(lambda ol: ol.product_id.type in ('product', 'consu')): + order_total += ol.product_id[product_field] * ol.product_uom_qty + _logger.info(' _get_package_type_for_order order_total ' + str(order_total)) if order_total: package_types = self.env['stock.package.type'].search([ ('package_carrier_type', 'in', ('none', False, self.delivery_type)), @@ -49,6 +65,7 @@ class DeliveryCarrier(models.Model): if package_type[package_type_field] >= order_total: return package_type return package_types if not package_type else package_type + return self.env['stock.package.type'] # Utility def get_to_ship_picking_packages(self, picking): @@ -268,7 +285,7 @@ class DeliveryCarrier(models.Model): else: if packages: raise UserError(_('Cannot rate package without picking.')) - self = self.with_context(date_planned=('date_planned' in order._fields and order.date_planned or fields.Datetime.now())) + self = self.with_context(date_planned=('date_planned' in self.env['sale.order']._fields and order.date_planned or fields.Datetime.now())) res = [] for carrier in self: diff --git a/delivery_hibou/views/stock_views.xml b/delivery_hibou/views/stock_views.xml index 0989f519..4205779e 100644 --- a/delivery_hibou/views/stock_views.xml +++ b/delivery_hibou/views/stock_views.xml @@ -52,4 +52,17 @@ + + hibou.stock.package.type.form + stock.package.type + + + + + + + + + + From 2d1c973034a137d1bb49780cc7b64146bbebb11c Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Tue, 20 Sep 2022 19:45:24 +0000 Subject: [PATCH 7/9] [IMP] delivery_hibou: improve dynamic calls --- delivery_hibou/models/delivery.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index 220eaae3..20f98e44 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -294,16 +294,16 @@ class DeliveryCarrier(models.Model): p.package_type_id.package_carrier_type in (False, '', 'none', carrier.delivery_type)) if packages and not carrier_packages: continue - if hasattr(carrier, '%s_rate_shipment_multi' % self.delivery_type): + attr = getattr(carrier, '%s_rate_shipment_multi' % self.delivery_type, None) + if attr: try: - res += getattr(carrier, '%s_rate_shipment_multi' % carrier.delivery_type)(order=order, - picking=picking, - packages=carrier_packages) + res += attr(order=order, picking=picking, packages=carrier_packages) except TypeError: # TODO remove catch if after Odoo 14 # This is intended to find ones that don't support packages= kwarg - res += getattr(carrier, '%s_rate_shipment_multi' % carrier.delivery_type)(order=order, - picking=picking) + res2 = attr(order=order, picking=picking) + if res2: + res += res2 return res @@ -314,11 +314,12 @@ class DeliveryCarrier(models.Model): :param packages: Optional recordset of packages (should be for this carrier) ''' self.ensure_one() - if hasattr(self, '%s_cancel_shipment' % self.delivery_type): + attr = getattr(self, '%s_cancel_shipment' % self.delivery_type, None) + if attr: # No good way to tell if this method takes the kwarg for packages if packages: try: - return getattr(self, '%s_cancel_shipment' % self.delivery_type)(pickings, packages=packages) + return attr(pickings, packages=packages) except TypeError: # we won't be able to cancel the packages properly # here we will TRY to make a good call here where we put the package references into the picking @@ -329,7 +330,7 @@ class DeliveryCarrier(models.Model): 'carrier_tracking_ref': tracking_ref, }) - return getattr(self, '%s_cancel_shipment' % self.delivery_type)(pickings) + return attr(pickings) class ChooseDeliveryPackage(models.TransientModel): From fd2edf185384f8b12f0a2fa4cfe589fe6016e471 Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 21 Sep 2022 19:22:51 +0000 Subject: [PATCH 8/9] [IMP] delivery_hibou: package count (special for package by volume) --- delivery_hibou/models/delivery.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index 20f98e44..6e92d382 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -1,4 +1,5 @@ import logging +from math import ceil from odoo import api, fields, models, _ from odoo.tools.float_utils import float_compare from odoo.addons.stock.models.stock_move import PROCUREMENT_PRIORITIES @@ -47,6 +48,14 @@ class DeliveryCarrier(models.Model): return attr _logger.info(' package by NULL') return self.env['stock.package.type'] + + def get_package_count_for_order(self, order, package_type=None): + if package_type is None: + package_type = self.get_package_type_for_order(order) + + if self.package_by_field == 'volume': + return self._get_package_count_for_order(order, package_type, 'package_volume', 'volume') + return self._get_package_count_for_order(order, package_type, 'max_weight', 'weight') def _get_package_type_for_order(self, order, package_type_field, product_field): # NOTE do not optimize this into non-loop. @@ -66,6 +75,17 @@ class DeliveryCarrier(models.Model): return package_type return package_types if not package_type else package_type return self.env['stock.package.type'] + + def _get_package_count_for_order(self, order, package_type, package_type_field, product_field): + # NOTE do not optimize this into non-loop. + # this may be an orderfake + order_total = 0.0 + for ol in order.order_line.filtered(lambda ol: ol.product_id.type in ('product', 'consu')): + order_total += ol.product_id[product_field] * ol.product_uom_qty + package_type_field_value = package_type[package_type_field] + if not package_type_field_value or package_type_field_value >= order_total: + return 1.0 + return ceil(order_total / package_type_field_value) # Utility def get_to_ship_picking_packages(self, picking): @@ -204,7 +224,7 @@ class DeliveryCarrier(models.Model): def _get_shipper_warehouse_dropship_in(self, picking): if picking.sale_id: - picking.sale_id.partner_shipping_id + return picking.sale_id.partner_shipping_id return self._get_shipper_warehouse_dropship_in_no_sale(picking) def _get_shipper_warehouse_dropship_in_no_sale(self, picking): From a33267f28a239ce6bb19f451fca867f69fa77d0e Mon Sep 17 00:00:00 2001 From: Jared Kipe Date: Wed, 21 Sep 2022 20:03:05 +0000 Subject: [PATCH 9/9] [FIX] delivery_hibou: cannot iterate on float --- delivery_hibou/models/delivery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index 6e92d382..3aeee13f 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -84,7 +84,7 @@ class DeliveryCarrier(models.Model): order_total += ol.product_id[product_field] * ol.product_uom_qty package_type_field_value = package_type[package_type_field] if not package_type_field_value or package_type_field_value >= order_total: - return 1.0 + return 1 return ceil(order_total / package_type_field_value) # Utility