From 166291c29e9bd7fd2be024ddd8b89d59565825b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 19 Aug 2025 13:33:55 +0200 Subject: [PATCH] Set sale attribute only if changed This avoid to clear the sale if there are no actual change on the sale order. Closes #14171 (grafted from 51e9c921e4e44a90472eebcfa137170e2ee28ec0) --HG-- branch : 7.0 --- modules/web_shop_shopify/common.py | 1 + modules/web_shop_shopify/sale.py | 101 +++++++++++++++++------------ 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/modules/web_shop_shopify/common.py b/modules/web_shop_shopify/common.py index c493496f7b..265b92d88f 100644 --- a/modules/web_shop_shopify/common.py +++ b/modules/web_shop_shopify/common.py @@ -162,3 +162,4 @@ class IdentifiersMixin(IdentifiersUpdateMixin): def setattr_changed(record, name, value): if getattr(record, name, None) != value: setattr(record, name, value) + return True diff --git a/modules/web_shop_shopify/sale.py b/modules/web_shop_shopify/sale.py index 38870c9723..c70d9b1ad2 100644 --- a/modules/web_shop_shopify/sale.py +++ b/modules/web_shop_shopify/sale.py @@ -16,7 +16,7 @@ from trytond.pool import Pool, PoolMeta from trytond.pyson import Eval from trytond.transaction import Transaction -from .common import IdentifierMixin +from .common import IdentifierMixin, setattr_changed from .exceptions import ShopifyError @@ -63,8 +63,7 @@ class Sale(IdentifierMixin, metaclass=PoolMeta): if not sale: sale = shop.get_sale(party=party) sale.shopify_identifier = order.id - elif sale.party != party: - sale.party = party + setattr_changed(sale, 'party', party) assert sale.shopify_identifier == order.id if order.location_id: @@ -79,13 +78,21 @@ class Sale(IdentifierMixin, metaclass=PoolMeta): if sale.party != shop.guest_party: if getattr(order, 'shipping_address', None): - sale.shipment_address = party.get_address_from_shopify( + shipment_address = party.get_address_from_shopify( order.shipping_address) + else: + shipment_address = None + if shipment_address: + setattr_changed(sale, 'shipment_address', shipment_address) if getattr(order, 'billing_address', None): - sale.invoice_address = party.get_address_from_shopify( + invoice_address = party.get_address_from_shopify( order.billing_address) else: - sale.invoice_address = getattr(sale, 'shipment_address', None) + invoice_address = None + if invoice_address or shipment_address: + setattr_changed( + sale, 'invoice_address', + invoice_address or shipment_address) if not party.addresses: address = Address(party=party) @@ -95,10 +102,10 @@ class Sale(IdentifierMixin, metaclass=PoolMeta): if not sale.invoice_address: sale.invoice_address = address - sale.reference = order.name - sale.comment = order.note - sale.sale_date = dateutil.parser.isoparse( - order.processed_at or order.created_at).date() + setattr_changed(sale, 'reference', order.name) + setattr_changed(sale, 'comment', order.note) + setattr_changed(sale, 'sale_date', dateutil.parser.isoparse( + order.processed_at or order.created_at).date()) if order.phone: for contact_mechanism in party.contact_mechanisms: @@ -108,7 +115,7 @@ class Sale(IdentifierMixin, metaclass=PoolMeta): else: contact_mechanism = ContactMechanism( party=party, type='phone', value=order.phone) - sale.contact = contact_mechanism + setattr_changed(sale, 'contact', contact_mechanism) refund_line_items = defaultdict(list) for refund in order.refunds: @@ -307,24 +314,30 @@ class Sale_ShipmentCost(metaclass=PoolMeta): sale = super().get_from_shopify(shop, order, sale=sale) - sale.shipment_cost_method = None + shipment_cost_method = None if order.shipping_lines: available_carriers = sale.on_change_with_available_carriers() + carrier = None if available_carriers: - sale.carrier = available_carriers[0] + carrier = available_carriers[0] + setattr_changed(sale, 'carrier', carrier) if sale.carrier: - sale.shipment_cost_method = 'order' + shipment_cost_method = 'order' for line in sale.lines: if getattr(line, 'shipment_cost', None) is not None: unit_price = line.unit_price base_price = getattr(line, 'base_price', None) - line.product = sale.carrier.carrier_product - line.on_change_product() - line.unit_price = round_price(Tax.reverse_compute( + if setattr_changed( + line, 'product', sale.carrier.carrier_product): + line.on_change_product() + unit_price = round_price(Tax.reverse_compute( unit_price, line.taxes, sale.sale_date)) + setattr_changed(line, 'unit_price', unit_price) if base_price is not None: - line.base_price = round_price(Tax.reverse_compute( + base_price = round_price(Tax.reverse_compute( base_price, line.taxes, sale.sale_date)) + setattr_changed(line, 'base_price', base_price) + setattr_changed(sale, 'shipment_cost_method', shipment_cost_method) return sale @@ -354,14 +367,15 @@ class Line(IdentifierMixin, metaclass=PoolMeta): if getattr(line_item, 'variant_id', None): if product := Product.search_shopify_identifier( sale.web_shop, line_item.variant_id): - line.product = product + setattr_changed(line, 'product', product) if line.product: line._set_shopify_quantity(line.product, quantity) - line.on_change_product() + if line._changed_values(): + line.on_change_product() else: - line.quantity = quantity - line.description = line_item.title - line.taxes = [] + setattr_changed(line, 'quantity', quantity) + setattr_changed(line, 'description', line_item.title) + setattr_changed(line, 'taxes', ()) total_discount = sum( Decimal(d.amount) for d in line_item.discount_allocations) unit_price = (( @@ -373,26 +387,28 @@ class Line(IdentifierMixin, metaclass=PoolMeta): if line.product: line._set_shopify_unit_price(line.product, unit_price) else: - line.unit_price = unit_price + setattr_changed(line, 'unit_price', unit_price) return line def _set_shopify_quantity(self, product, quantity): if product.shopify_uom.category == product.sale_uom.category: - self.unit = self.product.shopify_uom - self.quantity = quantity + setattr_changed(self, 'unit', self.product.shopify_uom) + setattr_changed(self, 'quantity', quantity) def _set_shopify_unit_price(self, product, unit_price): if product.shopify_uom.category == product.sale_uom.category: - self.unit_price = unit_price + setattr_changed(self, 'unit_price', unit_price) @classmethod def get_from_shopify_shipping(cls, sale, shipping_line, line=None): if not line: line = cls(type='line') line.sale = sale - line.quantity = 1 - line.unit_price = round_price(Decimal(shipping_line.discounted_price)) - line.description = shipping_line.title + setattr_changed(line, 'quantity', 1) + setattr_changed( + line, 'unit_price', + round_price(Decimal(shipping_line.discounted_price))) + setattr_changed(line, 'description', shipping_line.title) return line def _get_invoice_line_quantity(self): @@ -413,15 +429,16 @@ class Line_Discount(metaclass=PoolMeta): pool = Pool() Tax = pool.get('account.tax') line = super().get_from_shopify(sale, line_item, quantity, line=line) - line.base_price = round_price(Tax.reverse_compute( - Decimal(line_item.price), line.taxes, sale.sale_date)) + setattr_changed(line, 'base_price', round_price( + Tax.reverse_compute( + Decimal(line_item.price), line.taxes, sale.sale_date))) return line @classmethod def get_from_shopify_shipping(cls, sale, shipping_line, line=None): line = super().get_from_shopify_shipping( sale, shipping_line, line=line) - line.base_price = Decimal(shipping_line.price) + setattr_changed(line, 'base_price', Decimal(shipping_line.price)) return line @@ -433,19 +450,21 @@ class Line_SaleSecondaryUnit(metaclass=PoolMeta): if (product.sale_secondary_uom and product.shopify_uom.category == product.sale_secondary_uom.category): - self.unit = product.sale_uom - self.secondary_unit = product.shopify_uom - self.on_change_product() - self.secondary_quantity = quantity - self.on_change_secondary_quantity() + changed = setattr_changed(self, 'unit', product.sale_uom) + changed |= setattr_changed( + self, 'secondary_unit', product.shopify_uom) + if changed: + self.on_change_product() + if setattr_changed(self, 'secondary_quantity', quantity): + self.on_change_secondary_quantity() def _set_shopify_unit_price(self, product, unit_price): super()._set_shopify_unit_price(product, unit_price) if (product.sale_secondary_uom and product.shopify_uom.category == product.sale_secondary_uom.category): - self.secondary_unit_price = unit_price - self.on_change_secondary_unit_price() + if setattr_changed(self, 'secondary_unit_price', unit_price): + self.on_change_secondary_unit_price() class Line_ShipmentCost(metaclass=PoolMeta): @@ -455,7 +474,7 @@ class Line_ShipmentCost(metaclass=PoolMeta): def get_from_shopify_shipping(cls, sale, shipping_line, line=None): line = super().get_from_shopify_shipping( sale, shipping_line, line=line) - line.shipment_cost = Decimal(shipping_line.price) + setattr_changed(line, 'shipment_cost', Decimal(shipping_line.price)) return line # TODO: refund as return sale