Files
odoo_source/addons/pos_loyalty/models/pos_order.py
T
William Braeckman 26e79061f5 [ADD] pos_loyalty: manage loyalty in PoS
This module was moved from enterprise to community and now includes
pos_coupon and pos_gift_card aswell.

TaskId-2675382
2022-04-08 11:04:44 +02:00

127 lines
5.7 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
from odoo import _, models
class PosOrder(models.Model):
_inherit = 'pos.order'
def validate_coupon_programs(self, point_changes, new_codes):
"""
This is called upon validating the order in the pos.
This will check the balance for any pre-existing coupon to make sure that the rewards are in fact all claimable.
This will also check that any set code for coupons do not exist in the database.
"""
point_changes = {int(k): v for k, v in point_changes.items()}
coupon_ids_from_pos = set(point_changes.keys())
coupons = self.env['loyalty.card'].browse(coupon_ids_from_pos).exists().filtered('program_id.active')
coupon_difference = set(coupons.ids) ^ coupon_ids_from_pos
if coupon_difference:
return {
'successful': False,
'payload': {
'message': _('Some coupons are invalid. The applied coupons have been updated. Please check the order.'),
'removed_coupons': list(coupon_difference),
}
}
for coupon in coupons:
if (coupon.points + point_changes[coupon.id]) < 0:
return {
'successful': False,
'payload': {
'message': _('There are not enough points for the coupon: %s.', coupon.code),
'updated_points': {c.id: c.points for c in coupons}
}
}
# Check existing coupons
coupons = self.env['loyalty.card'].search([('code', 'in', new_codes)])
if coupons:
return {
'successful': False,
'payload': {
'message': _('The following codes already exist in the database, perhaps they were already sold?\n%s',
', '.join(coupons.mapped('code'))),
}
}
return {
'successful': True,
'payload': {},
}
def confirm_coupon_programs(self, coupon_data):
"""
This is called after the order is created.
This will create all necessary coupons and link them to their line orders etc..
It will also return the points of all concerned coupons to be updated in the cache.
"""
# Keys are stringified when using rpc
coupon_data = {int(k): v for k, v in coupon_data.items()}
# Map negative id to newly created ids.
coupon_new_id_map = {k: k for k in coupon_data.keys() if k > 0}
# Create the coupons that were awarded by the order.
coupons_to_create = {k: v for k, v in coupon_data.items() if k < 0}
coupon_create_vals = [{
'program_id': p['program_id'],
'partner_id': p.get('partner_id', False),
'code': p.get('barcode') or self.env['loyalty.card']._generate_code(),
'points': 0,
'source_pos_order_id': self.id,
} for p in coupons_to_create.values()]
# Pos users don't have the create permission
new_coupons = self.env['loyalty.card'].sudo().create(coupon_create_vals)
# Map the newly created coupons
for old_id, new_id in zip(coupons_to_create.keys(), new_coupons):
coupon_new_id_map[new_id.id] = old_id
all_coupons = self.env['loyalty.card'].browse(coupon_new_id_map.keys()).exists()
lines_per_reward_code = defaultdict(lambda: self.env['pos.order.line'])
for line in self.lines:
if not line.reward_identifier_code:
continue
lines_per_reward_code[line.reward_identifier_code] |= line
for coupon in all_coupons:
if coupon.id in coupon_new_id_map:
# Coupon existed previously, update amount of points.
coupon.points += coupon_data[coupon_new_id_map[coupon.id]]['points']
for reward_code in coupon_data[coupon_new_id_map[coupon.id]].get('line_codes', []):
lines_per_reward_code[reward_code].coupon_id = coupon
# Reports per program
report_per_program = {}
coupon_per_report = defaultdict(list)
for coupon in new_coupons:
if coupon.program_id not in report_per_program:
report_per_program[coupon.program_id] = coupon.program_id.communication_plan_ids.\
filtered(lambda c: c.trigger == 'create').pos_report_print_id
for report in report_per_program[coupon.program_id]:
coupon_per_report[report.id].append(coupon.id)
return {
'coupon_updates': [{
'old_id': coupon_new_id_map[coupon.id],
'id': coupon.id,
'points': coupon.points,
'code': coupon.code,
'program_id': coupon.program_id.id,
'partner_id': coupon.partner_id.id,
} for coupon in all_coupons if coupon.program_id.is_nominative],
'program_updates': [{
'program_id': program.id,
'usages': program.total_order_count,
} for program in all_coupons.program_id],
'new_coupon_info': [{
'program_name': coupon.program_id.name,
'expiration_date': coupon.expiration_date,
'code': coupon.code,
} for coupon in new_coupons if coupon.program_id.applies_on == 'future'],
'coupon_report': coupon_per_report,
}
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