Skip to content

Commit

Permalink
[FIX] pos_loyalty,pos_sale_loyalty: avoid creating 2 loyalty cards
Browse files Browse the repository at this point in the history
Current behavior:
When you create an order for partner A but do not confirm it, then
settle the order in the PoS and add some product. You will have 2
loyalty cards created for partner A. This is happening because when you
confirm the order in the PoS it will confirm the sale order and create
a first loyalty card, but the PoS will not be aware of this and when it
will try to apply the point for the product added through the PoS it
will create a new loyalty card.

Steps to reproduce:
- Activate a loyalty program
- Create a partner A
- Create a sale order for partner A but do not confirm it
- Go to the PoS and settle the order
- Add some product to the order
- Pay the order
- Go to the backend and check the loyalty cards for partner A
- You will have 2 loyalty cards created

To avoid this we will check if the partner has a loyalty card before
creating a new one.

opw-3582174

closes odoo#149621

X-original-commit: ecd62dc
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
Signed-off-by: Robin Engels (roen) <roen@odoo.com>
  • Loading branch information
robinengels committed Jan 17, 2024
1 parent 4d997bc commit e1ed785
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 0 deletions.
21 changes: 21 additions & 0 deletions addons/pos_loyalty/models/pos_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def confirm_coupon_programs(self, coupon_data):
get_partner_id = lambda partner_id: partner_id and self.env['res.partner'].browse(partner_id).exists() and partner_id or False
# Keys are stringified when using rpc
coupon_data = {int(k): v for k, v in coupon_data.items()}

self._check_existing_loyalty_cards(coupon_data)
# Map negative id to newly created ids.
coupon_new_id_map = {k: k for k in coupon_data.keys() if k > 0}

Expand Down Expand Up @@ -145,6 +147,25 @@ def confirm_coupon_programs(self, coupon_data):
'coupon_report': coupon_per_report,
}

def _check_existing_loyalty_cards(self, coupon_data):
coupon_key_to_modify = []
for coupon_id, coupon_vals in coupon_data.items():
partner_id = coupon_vals.get('partner_id', False)
if partner_id:
partner_coupons = self.env['loyalty.card'].search(
[('partner_id', '=', partner_id), ('program_type', '=', 'loyalty')])
existing_coupon_for_program = partner_coupons.filtered(lambda c: c.program_id.id == coupon_vals['program_id'])
if existing_coupon_for_program:
coupon_vals['coupon_id'] = existing_coupon_for_program[0].id
coupon_key_to_modify.append([coupon_id, existing_coupon_for_program[0].id])
for old_key, new_key in coupon_key_to_modify:
coupon_data[new_key] = coupon_data.pop(old_key)

def _get_fields_for_order_line(self):
fields = super(PosOrder, self)._get_fields_for_order_line()
fields.extend(['is_reward_line', 'reward_id', 'coupon_id', 'reward_identifier_code', 'points_cost'])
return fields

def _add_mail_attachment(self, name, ticket):
attachment = super()._add_mail_attachment(name, ticket)
gift_card_programs = self.config_id._get_program_ids().filtered(lambda p: p.program_type == 'gift_card' and
Expand Down
3 changes: 3 additions & 0 deletions addons/pos_sale_loyalty/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
'point_of_sale._assets_pos': [
'pos_sale_loyalty/static/src/**/*',
],
'web.assets_tests': [
'pos_sale_loyalty/static/tests/tours/**/*',
],
},
'license': 'LGPL-3',
}
25 changes: 25 additions & 0 deletions addons/pos_sale_loyalty/static/tests/tours/PosSaleLoyaltyTour.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** @odoo-module **/

import * as PaymentScreen from "@point_of_sale/../tests/tours/helpers/PaymentScreenTourMethods";
import * as ReceiptScreen from "@point_of_sale/../tests/tours/helpers/ReceiptScreenTourMethods";
import * as ProductScreenPos from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods";
import * as ProductScreenSale from "@pos_sale/../tests/helpers/ProductScreenTourMethods";
const ProductScreen = { ...ProductScreenPos, ...ProductScreenSale };
import { registry } from "@web/core/registry";

registry
.category("web_tour.tours")
.add('PosSaleLoyaltyTour1', {
test: true,
url: '/pos/ui',
steps: () => [
ProductScreen.confirmOpeningPopup(),
ProductScreen.clickQuotationButton(),
ProductScreen.selectFirstOrder(),
ProductScreen.clickDisplayedProduct('Desk Pad'),
ProductScreen.clickPayButton(),
PaymentScreen.clickPaymentMethod('Bank'),
PaymentScreen.clickValidate(),
ReceiptScreen.isShown(),
].flat(),
});
4 changes: 4 additions & 0 deletions addons/pos_sale_loyalty/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from . import test_pos_sale_loyalty
45 changes: 45 additions & 0 deletions addons/pos_sale_loyalty/tests/test_pos_sale_loyalty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.addons.point_of_sale.tests.test_frontend import TestPointOfSaleHttpCommon
from odoo.tests import tagged


@tagged("post_install", "-at_install")
class TestPoSSaleLoyalty(TestPointOfSaleHttpCommon):
def test_pos_sale_loyalty_1(self):
"""Test that only one loyalty card is created when settling an unconfirmed order."""
self.env['loyalty.program'].search([]).write({'active': False})
self.env['loyalty.program'].create({
'name': 'Test Loyalty Program',
'program_type': 'loyalty',
'trigger': 'auto',
'applies_on': 'both',
'rule_ids': [
(0, 0, {
'reward_point_mode': 'money',
'minimum_amount': 1,
'reward_point_amount': 1,
}),
],
'reward_ids': [
(0, 0, {
'reward_type': 'discount',
'discount': 1,
'required_points': 1000,
'discount_mode': 'percent',
'discount_applicability': 'order',
}),
],
})
self.env['sale.order'].create({
'partner_id': self.partner_a.id,
'order_line': [(0, 0, {
'product_id': self.desk_organizer.id,
'product_uom_qty': 1,
'price_unit': 100,
})]
})

self.main_pos_config.open_ui()
self.start_tour("/pos/web?config_id=%d" % self.main_pos_config.id, "PosSaleLoyaltyTour1", login="accountman")
self.assertEqual(self.env['loyalty.card'].search_count([('partner_id', '=', self.partner_a.id)]), 1)

0 comments on commit e1ed785

Please sign in to comment.