# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ from odoo.exceptions import UserError from odoo.tools import float_compare from datetime import datetime, time import pytz class PosOrder(models.Model): _inherit = 'pos.order' def validate_coupon_programs(self, point_changes, new_codes): point_changes_int = {int(k): v for k, v in point_changes.items()} subscription_cards = self.env['loyalty.card'].browse(point_changes_int.keys()).exists().filtered( lambda c: c.program_id.program_type == 'subscription' ) # Validate dates and limits for subscription cards for card in subscription_cards: today = fields.Date.today() if card.subscription_start_date and today < card.subscription_start_date: return { 'successful': False, 'payload': { 'message': _('The subscription for %s is not active yet (Starts on %s).', card.partner_id.name, card.subscription_start_date), } } if card.subscription_end_date and today > card.subscription_end_date: return { 'successful': False, 'payload': { 'message': _('The subscription for %s has expired (Expired on %s).', card.partner_id.name, card.subscription_end_date), } } # Check usage limit today in user local timezone user_tz = pytz.timezone(self.env.user.tz or 'UTC') now_utc = fields.Datetime.now() now_local = pytz.utc.localize(now_utc).astimezone(user_tz) midnight_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0) start_date = midnight_local.astimezone(pytz.utc).replace(tzinfo=None) history_count = self.env['loyalty.history'].sudo().search_count([ ('card_id', '=', card.id), ('create_date', '>=', start_date), ('used', '>', 0), ]) if history_count >= 1: return { 'successful': False, 'payload': { 'message': _('Customer %s has already claimed their subscription free product today.', card.partner_id.name), } } # Bypass the points validation by temporarily mocking subscription cards points to a high value. original_points = {card: card.points for card in subscription_cards} for card in subscription_cards: card.points = 9999.0 try: res = super().validate_coupon_programs(point_changes, new_codes) finally: for card, points in original_points.items(): card.points = points return res def confirm_coupon_programs(self, coupon_data): # 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 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