feat: implement loyalty data migration between membership levels during partner updates

This commit is contained in:
Suherdy Yacob 2026-05-22 14:14:04 +07:00
parent a2fa0304d8
commit 7985e9a32f

View File

@ -21,8 +21,8 @@ class ResPartner(models.Model):
def write(self, vals): def write(self, vals):
""" """
When a partner's membership level changes, delete their loyalty cards When a partner's membership level changes, transfer points, history,
from the OLD level's program so they don't accumulate cards across levels. and archive their loyalty cards from the OLD level's program.
""" """
if 'membership_level_id' in vals: if 'membership_level_id' in vals:
new_level_id = vals['membership_level_id'] new_level_id = vals['membership_level_id']
@ -30,12 +30,51 @@ class ResPartner(models.Model):
old_level_id = partner.membership_level_id.id if partner.membership_level_id else False old_level_id = partner.membership_level_id.id if partner.membership_level_id else False
# Only act when the level is actually changing to a different value # Only act when the level is actually changing to a different value
if old_level_id and old_level_id != new_level_id: if old_level_id and old_level_id != new_level_id:
old_cards = self.env['loyalty.card'].search([ old_cards = self.env['loyalty.card'].sudo().search([
('partner_id', '=', partner.id), ('partner_id', '=', partner.id),
('program_id', '=', old_level_id), ('program_id', '=', old_level_id),
]) ])
if old_cards and new_level_id:
new_card = self.env['loyalty.card'].sudo().search([
('partner_id', '=', partner.id),
('program_id', '=', new_level_id),
], limit=1)
if not new_card:
new_card = self.env['loyalty.card'].sudo().create({
'partner_id': partner.id,
'program_id': new_level_id,
'points': 0,
})
# 1. Transfer points
for old_card in old_cards:
pts = old_card.points
if abs(pts) > 0.0001:
new_card.points += pts
# 2. Transfer loyalty history (point transactions)
old_histories = self.env['loyalty.history'].sudo().search([
('card_id', 'in', old_cards.ids)
])
if old_histories:
old_histories.write({'card_id': new_card.id})
# 3. Transfer POS order line references
old_pos_lines = self.env['pos.order.line'].sudo().search([
('coupon_id', 'in', old_cards.ids)
])
if old_pos_lines:
old_pos_lines.write({'coupon_id': new_card.id})
# 4. Transfer Sales order line references
old_sale_lines = self.env['sale.order.line'].sudo().search([
('coupon_id', 'in', old_cards.ids)
])
if old_sale_lines:
old_sale_lines.write({'coupon_id': new_card.id})
# Archive old-level cards
if old_cards: if old_cards:
# Archive instead of delete — loyalty cards may be referenced
# by pos_order_line.coupon_id (FK), so unlink() would fail.
old_cards.write({'active': False}) old_cards.write({'active': False})
return super().write(vals) return super().write(vals)