diff --git a/rattail/app.py b/rattail/app.py index f168797e08a92376413e11df9b975902cce9c8af..a674bae0f138e6792bd92a9ca93b84b5f2887fab 100644 --- a/rattail/app.py +++ b/rattail/app.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -29,6 +29,7 @@ from __future__ import unicode_literals, absolute_import import os # import re import datetime +import decimal import os import shutil import socket @@ -147,6 +148,26 @@ class AppHandler(object): from rattail.time import timezone return timezone(self.config, key) + def json_friendly(self, value): + """ + Coerce a Python value to one which is JSON-serializable. + + So, this does *not* return a JSON string, but rather a Python + object which can then be safely converted via + ``json.dumps()``. + + If the value is a container, it will be crawled recursively + and all values it contains will be coerced. + """ + if isinstance(value, dict): + for key, val in six.iteritems(value): + value[key] = self.json_friendly(val) + + elif isinstance(value, decimal.Decimal): + value = float(value) + + return value + def localtime(self, *args, **kwargs): """ Produce or convert a timestamp in the default time zone. diff --git a/rattail/batch/custorder.py b/rattail/batch/custorder.py index 9b48d38cbecb29cb8bd13e1f36e19ad26c9ec595..efd076be2519fa3250d33c0acec617d1e1d0d8ed 100644 --- a/rattail/batch/custorder.py +++ b/rattail/batch/custorder.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -57,6 +57,10 @@ class CustomerOrderBatchHandler(BatchHandler): has_custom_product_autocomplete = False nondigits_pattern = re.compile(r'\D') + def __init__(self, config, **kwargs): + super(CustomerOrderBatchHandler, self).__init__(config, **kwargs) + self.custorder_handler = self.app.get_custorder_handler() + def init_batch(self, batch, progress=None, **kwargs): """ Assign the "local" store to the batch, if applicable. @@ -134,6 +138,15 @@ class CustomerOrderBatchHandler(BatchHandler): 'allow_item_discounts', default=False) + def allow_item_discounts_if_on_sale(self): + """ + Returns boolean indicating whether per-item discounts are + allowed when item is already on sale. + """ + return self.config.getbool('rattail.custorders', + 'allow_item_discounts_if_on_sale', + default=False) + def allow_past_item_reorder(self): """ Returns boolean indicating whether to expose past items for @@ -518,6 +531,7 @@ class CustomerOrderBatchHandler(BatchHandler): 'url': products.get_url(product), 'image_url': products.get_image_url(product), 'uom_choices': self.uom_choices_for_product(product), + 'default_item_discount': self.get_default_item_discount(product), } # TODO: this was somewhat copied from @@ -605,6 +619,14 @@ class CustomerOrderBatchHandler(BatchHandler): return that reason as a string; otherwise ``None``. """ + def get_default_item_discount(self, product=None, **kwargs): + """ + Returns default item discount available. If product is given, + the default may be specific to its department etc. + """ + return self.custorder_handler.get_default_item_discount( + product=product, **kwargs) + def add_product(self, batch, product, order_quantity, order_uom, **kwargs): """ diff --git a/rattail/custorders.py b/rattail/custorders.py index 5ae059bf031f0ff304d89e78f58dbe3017259a4f..5b7befb695383a1e4604782a85a37e3715b23f0d 100644 --- a/rattail/custorders.py +++ b/rattail/custorders.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2021 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -28,6 +28,8 @@ Please note this is different from the Customer Order Batch Handler. from __future__ import unicode_literals, absolute_import +import decimal + from rattail.app import GenericHandler @@ -36,6 +38,16 @@ class CustomerOrderHandler(GenericHandler): Base class and default implementation for customer order handlers. """ + def get_default_item_discount(self, product=None, **kwargs): + """ + Returns default item discount available. If product is given, + the default may be specific to its department etc. + """ + discount = self.config.get('rattail.custorders', + 'default_item_discount') + if discount: + return decimal.Decimal(discount) + def resolve_person(self, pending, person, user, **kwargs): """ Resolve a pending person for all customer orders.