# POS Loyalty Expiration Custom ## Overview This module enhances the Odoo 19 Point of Sale (POS) loyalty capabilities by introducing a strict expiration control mechanism. It provides an isolated, custom expiration date field (`custom_end_date`) that overrides default point earning and reward claiming logic in the Point of Sale UI and backend. When a Loyalty Card passes this `custom_end_date`, the system securely locks the card out of POS transactions, preventing both the accumulation of new reward points and the claiming of previously earned rewards. ## Key Features * **Dedicated Custom End Date:** Formally declares and injects the `custom_end_date` directly into the `loyalty.card` model and UI (no Odoo Studio required). * **Earn Point Blocking:** Halts any calculation or recording of points for an order when an expired loyalty card is used. * **Reward Claim Blocking:** Filters and completely hides any claimable rewards associated with an expired loyalty card from the POS frontend interface. * **Strict Backend Validation:** Expands on Odoo's internal coupon code checks to raise descriptive validation errors if an expired code is manually inputted. ## Installation 1. Place the `pos_loyalty_expiration_custom` directory inside your Odoo `addons` or `custom` folder. 2. Restart the Odoo service. 3. Log in as an Administrator, activate Developer Mode, and click **Update Apps List**. 4. Search for `POS Loyalty Expiration Custom` and click **Install**. ## Usage 1. Navigate to **Point of Sale > Products > Loyalty Programs**. 2. Select a program and view its related **Loyalty Cards** (or go directly to **Loyalty Cards**). 3. On the card form, locate the **End Date** field (placed next to the standard `expiration_date`). 4. Set an expiration date. 5. In an active POS Session: * Selecting a customer or scanning a code linked to an expired card will yield no points for their purchase. * Selecting the "Rewards" button will not present any options related to the expired card. ## Technical Notes * Extending Python model `loyalty.card` to inject `custom_end_date` into `_load_pos_data_fields`. * Patching `LoyaltyCard.prototype.isExpired()` in `pos_order.js` to parse and check the custom date constraint. * Patching `Order.prototype.getClaimableRewards` to proactively filter out expired cards. * Patching `PosStore.prototype._updatePrograms` to gracefully ignore and purge any points calculated against expired cards.