This module was moved from enterprise to community and now includes pos_coupon and pos_gift_card aswell. TaskId-2675382
127 lines
5.7 KiB
Python
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
|