diff --git a/models/pos_order.py b/models/pos_order.py index b6df420..f303a35 100644 --- a/models/pos_order.py +++ b/models/pos_order.py @@ -67,15 +67,70 @@ class PosOrder(models.Model): return res + def _check_existing_loyalty_cards(self, coupon_data): + """Extend core to also match existing subscription cards so they are + reused (point-updated) rather than triggering new-card creation.""" + # Run the standard matching first (covers 'loyalty' and 'ewallet'). + super()._check_existing_loyalty_cards(coupon_data) + + # Now handle 'subscription' type programs the same way. + coupon_key_to_modify = [] + for coupon_id, coupon_vals in coupon_data.items(): + partner_id = coupon_vals.get('partner_id', False) + if not partner_id: + continue + program = self.env['loyalty.program'].browse(coupon_vals['program_id']).exists() + if not program or program.program_type != 'subscription': + continue + existing = self.env['loyalty.card'].search([ + ('partner_id', '=', partner_id), + ('program_id', '=', coupon_vals['program_id']), + ], limit=1) + if existing: + coupon_vals['coupon_id'] = existing.id + coupon_key_to_modify.append([coupon_id, existing.id]) + + for old_key, new_key in coupon_key_to_modify: + coupon_data[new_key] = coupon_data.pop(old_key) + def confirm_coupon_programs(self, coupon_data): + """Strip any to-be-created (negative-id) coupon_data entries that + target a subscription program before handing off to core. + + Background: the POS JS adds a {points: 0} couponPointChange for every + is_nominative program (applies_on='both') whenever a partner is on the + order – including Subscription Direksi. Core would then create a fresh + loyalty.card for that partner. Subscription cards must only be created + manually, so we intercept and remove these phantom entries here. + """ + coupon_data_int = {int(k): v for k, v in coupon_data.items()} + + # Collect negative (new-card) ids that belong to subscription programs. + keys_to_remove = [] + for coupon_id, coupon_vals in coupon_data_int.items(): + if coupon_id >= 0: + # Positive id = existing card; let core handle it normally. + continue + program = self.env['loyalty.program'].browse( + coupon_vals.get('program_id') + ).exists() + if program and program.program_type == 'subscription': + keys_to_remove.append(coupon_id) + + # Remove the ghost entries (work on the original string-key dict). + for key in keys_to_remove: + coupon_data.pop(key, None) + coupon_data.pop(str(key), None) + # Run super to process normal workflow res = super().confirm_coupon_programs(coupon_data) - - # After points calculations/deductions are processed, reset the points back to 0.0 for subscription cards + + # After points calculations/deductions are processed, reset the points + # back to 0.0 for any subscription cards that were actually applied. coupon_data_int = {int(k): v for k, v in coupon_data.items()} for card_id in coupon_data_int.keys(): card = self.env['loyalty.card'].browse(card_id).exists() if card and card.program_id.program_type == 'subscription': card.points = 0.0 - + return res