mirror of
https://github.com/bringout/oca-ocb-pos.git
synced 2026-04-23 16:42:00 +02:00
19.0 vanilla
This commit is contained in:
parent
6e54c1af6c
commit
3ca647e428
1087 changed files with 132065 additions and 108499 deletions
|
|
@ -0,0 +1,52 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export class LoyaltyCard extends models.ServerModel {
|
||||
_name = "loyalty.card";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return ["partner_id", "code", "points", "program_id", "expiration_date", "write_date"];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
code: "CARD001",
|
||||
points: 10,
|
||||
partner_id: 1,
|
||||
program_id: 1,
|
||||
expiration_date: DateTime.now().plus({ days: 1 }).toISODate(),
|
||||
write_date: DateTime.now().minus({ days: 1 }).toFormat("yyyy-MM-dd HH:mm:ss"),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
code: "CARD002",
|
||||
points: 25,
|
||||
partner_id: 1,
|
||||
program_id: 2,
|
||||
expiration_date: DateTime.now().minus({ days: 1 }).toISODate(),
|
||||
write_date: DateTime.now().minus({ days: 2 }).toFormat("yyyy-MM-dd HH:mm:ss"),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
code: "CARD003",
|
||||
points: 15,
|
||||
partner_id: 3,
|
||||
program_id: 3,
|
||||
write_date: DateTime.now().toFormat("yyyy-MM-dd HH:mm:ss"),
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
code: "CARD004",
|
||||
points: 3,
|
||||
partner_id: 1,
|
||||
program_id: 7,
|
||||
write_date: DateTime.now().minus({ days: 2 }).toFormat("yyyy-MM-dd HH:mm:ss"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, LoyaltyCard]);
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export class LoyaltyProgram extends models.ServerModel {
|
||||
_name = "loyalty.program";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
"name",
|
||||
"trigger",
|
||||
"applies_on",
|
||||
"program_type",
|
||||
"pricelist_ids",
|
||||
"date_from",
|
||||
"date_to",
|
||||
"limit_usage",
|
||||
"max_usage",
|
||||
"is_nominative",
|
||||
"portal_visible",
|
||||
"portal_point_name",
|
||||
"trigger_product_ids",
|
||||
"rule_ids",
|
||||
"reward_ids",
|
||||
];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Loyalty Program",
|
||||
trigger: "auto",
|
||||
applies_on: "both",
|
||||
program_type: "loyalty",
|
||||
pricelist_ids: [1],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [1],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "E-Wallet Program",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "ewallet",
|
||||
pricelist_ids: [],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "E-Wallet Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Gift Card Program",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "gift_card",
|
||||
pricelist_ids: [],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "Gift Card Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [1],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "E-Wallet Program 2",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "ewallet",
|
||||
pricelist_ids: [],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "E-Wallet Points 2",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Nominative Gift Card Program",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "gift_card",
|
||||
pricelist_ids: [],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: true,
|
||||
portal_visible: true,
|
||||
portal_point_name: "Nominative Gift Card Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [1],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "E-Wallet Program 2",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "ewallet",
|
||||
pricelist_ids: [],
|
||||
date_from: DateTime.now().minus({ days: 10 }).toISODate(),
|
||||
date_to: DateTime.now().minus({ days: 1 }).toISODate(),
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "E-Wallet Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [],
|
||||
reward_ids: [],
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "Loyalty Program Future",
|
||||
trigger: "auto",
|
||||
applies_on: "future",
|
||||
program_type: "loyalty",
|
||||
pricelist_ids: [1],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: true,
|
||||
portal_visible: true,
|
||||
portal_point_name: "Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [4],
|
||||
reward_ids: [3],
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "100% Cheapest Discount Program",
|
||||
trigger: "auto",
|
||||
applies_on: "current",
|
||||
program_type: "promotion",
|
||||
pricelist_ids: [1],
|
||||
date_from: false,
|
||||
date_to: false,
|
||||
limit_usage: false,
|
||||
max_usage: 0,
|
||||
is_nominative: false,
|
||||
portal_visible: true,
|
||||
portal_point_name: "Points",
|
||||
trigger_product_ids: [],
|
||||
rule_ids: [5],
|
||||
reward_ids: [4],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, LoyaltyProgram]);
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class LoyaltyReward extends models.ServerModel {
|
||||
_name = "loyalty.reward";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
"description",
|
||||
"program_id",
|
||||
"reward_type",
|
||||
"required_points",
|
||||
"clear_wallet",
|
||||
"currency_id",
|
||||
"discount",
|
||||
"discount_mode",
|
||||
"discount_applicability",
|
||||
"all_discount_product_ids",
|
||||
"is_global_discount",
|
||||
"discount_max_amount",
|
||||
"discount_line_product_id",
|
||||
"reward_product_id",
|
||||
"multi_product",
|
||||
"reward_product_ids",
|
||||
"reward_product_qty",
|
||||
"reward_product_uom_id",
|
||||
"reward_product_domain",
|
||||
];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
description: "10% Discount",
|
||||
program_id: 1,
|
||||
reward_type: "discount",
|
||||
required_points: 10,
|
||||
clear_wallet: false,
|
||||
currency_id: 1,
|
||||
discount: 10,
|
||||
discount_mode: "percent",
|
||||
discount_applicability: "order",
|
||||
all_discount_product_ids: [],
|
||||
is_global_discount: true,
|
||||
discount_max_amount: 0,
|
||||
discount_line_product_id: false,
|
||||
reward_product_id: false,
|
||||
multi_product: false,
|
||||
reward_product_ids: [5],
|
||||
reward_product_qty: 1,
|
||||
reward_product_uom_id: false,
|
||||
reward_product_domain: "[]",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
description: "20% Discount",
|
||||
program_id: 2,
|
||||
reward_type: "product",
|
||||
required_points: 10,
|
||||
clear_wallet: false,
|
||||
currency_id: 1,
|
||||
discount: 0,
|
||||
discount_mode: "percent",
|
||||
discount_applicability: "order",
|
||||
all_discount_product_ids: [],
|
||||
is_global_discount: true,
|
||||
discount_max_amount: 0,
|
||||
discount_line_product_id: false,
|
||||
reward_product_id: false,
|
||||
multi_product: false,
|
||||
reward_product_ids: [5],
|
||||
reward_product_qty: 1,
|
||||
reward_product_uom_id: false,
|
||||
reward_product_domain: "[]",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
description: "Free Product - Whiteboard Pen",
|
||||
program_id: 7,
|
||||
reward_type: "product",
|
||||
required_points: 1,
|
||||
clear_wallet: false,
|
||||
currency_id: 1,
|
||||
discount: 0,
|
||||
discount_mode: "percent",
|
||||
discount_applicability: "order",
|
||||
all_discount_product_ids: [],
|
||||
is_global_discount: true,
|
||||
discount_max_amount: 0,
|
||||
discount_line_product_id: 18,
|
||||
reward_product_id: 10,
|
||||
multi_product: false,
|
||||
reward_product_ids: [10],
|
||||
reward_product_qty: 1,
|
||||
reward_product_uom_id: false,
|
||||
reward_product_domain: "[]",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
description: "100% Cheapest Discount",
|
||||
program_id: 8,
|
||||
reward_type: "discount",
|
||||
required_points: 1,
|
||||
clear_wallet: false,
|
||||
currency_id: 1,
|
||||
discount: 100,
|
||||
discount_mode: "percent",
|
||||
discount_applicability: "cheapest",
|
||||
all_discount_product_ids: [],
|
||||
is_global_discount: false,
|
||||
discount_max_amount: 0,
|
||||
discount_line_product_id: 5,
|
||||
reward_product_id: false,
|
||||
multi_product: false,
|
||||
reward_product_ids: [5],
|
||||
reward_product_qty: 1,
|
||||
reward_product_uom_id: false,
|
||||
reward_product_domain: "[]",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, LoyaltyReward]);
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class LoyaltyRule extends models.ServerModel {
|
||||
_name = "loyalty.rule";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
"program_id",
|
||||
"valid_product_ids",
|
||||
"any_product",
|
||||
"currency_id",
|
||||
"reward_point_amount",
|
||||
"reward_point_split",
|
||||
"reward_point_mode",
|
||||
"minimum_qty",
|
||||
"minimum_amount",
|
||||
"minimum_amount_tax_mode",
|
||||
"mode",
|
||||
"code",
|
||||
];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
program_id: 1,
|
||||
valid_product_ids: [5],
|
||||
any_product: true,
|
||||
currency_id: 1,
|
||||
reward_point_amount: 1,
|
||||
reward_point_split: true,
|
||||
reward_point_mode: "order",
|
||||
minimum_qty: 0,
|
||||
minimum_amount: 0,
|
||||
minimum_amount_tax_mode: "incl",
|
||||
mode: "auto",
|
||||
code: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
program_id: 2,
|
||||
valid_product_ids: [5],
|
||||
any_product: true,
|
||||
currency_id: 1,
|
||||
reward_point_amount: 1,
|
||||
reward_point_split: true,
|
||||
reward_point_mode: "order",
|
||||
minimum_qty: 3,
|
||||
minimum_amount: 40,
|
||||
minimum_amount_tax_mode: "excl",
|
||||
mode: "auto",
|
||||
code: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
program_id: 6,
|
||||
valid_product_ids: [5],
|
||||
any_product: true,
|
||||
currency_id: 1,
|
||||
reward_point_amount: 1,
|
||||
reward_point_split: true,
|
||||
reward_point_mode: "order",
|
||||
minimum_qty: 3,
|
||||
minimum_amount: 40,
|
||||
minimum_amount_tax_mode: "excl",
|
||||
mode: "with_code",
|
||||
code: "EXPIRED",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
program_id: 7,
|
||||
any_product: true,
|
||||
currency_id: 1,
|
||||
reward_point_amount: 1,
|
||||
reward_point_split: false,
|
||||
reward_point_mode: "unit",
|
||||
minimum_qty: 1,
|
||||
minimum_amount: 0,
|
||||
minimum_amount_tax_mode: "incl",
|
||||
mode: "auto",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
program_id: 8,
|
||||
any_product: true,
|
||||
currency_id: 1,
|
||||
reward_point_amount: 1,
|
||||
reward_point_split: false,
|
||||
reward_point_mode: "unit",
|
||||
minimum_qty: 1,
|
||||
minimum_amount: 0,
|
||||
minimum_amount_tax_mode: "incl",
|
||||
mode: "auto",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, LoyaltyRule]);
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { PosOrder } from "@point_of_sale/../tests/unit/data/pos_order.data";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
patch(PosOrder.prototype, {
|
||||
validate_coupon_programs(self, point_changes) {
|
||||
const couponIdsFromPos = new Set(Object.keys(point_changes).map((id) => parseInt(id)));
|
||||
|
||||
const coupons = this.env["loyalty.card"]
|
||||
.browse([...couponIdsFromPos])
|
||||
.filter((c) => c && c.program_id);
|
||||
|
||||
const couponDifference = new Set(
|
||||
[...couponIdsFromPos].filter((id) => !coupons.find((c) => c.id === id))
|
||||
);
|
||||
|
||||
if (couponDifference.size > 0) {
|
||||
return {
|
||||
successful: false,
|
||||
payload: {
|
||||
message: _t(
|
||||
"Some coupons are invalid. The applied coupons have been updated. Please check the order."
|
||||
),
|
||||
removed_coupons: [...couponDifference],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
for (const coupon of coupons) {
|
||||
const needed = -point_changes[coupon.id];
|
||||
if (parseFloat(coupon.points.toFixed(2)) < parseFloat(needed.toFixed(2))) {
|
||||
return {
|
||||
successful: false,
|
||||
payload: {
|
||||
message: _t("There are not enough points for the coupon: %s.", coupon.code),
|
||||
updated_points: Object.fromEntries(coupons.map((c) => [c.id, c.points])),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
successful: true,
|
||||
payload: {},
|
||||
};
|
||||
},
|
||||
|
||||
confirm_coupon_programs(self, coupon_data) {
|
||||
const couponNewIdMap = {};
|
||||
for (const k of Object.keys(coupon_data)) {
|
||||
const id = parseInt(k);
|
||||
if (id > 0) {
|
||||
couponNewIdMap[id] = id;
|
||||
}
|
||||
}
|
||||
|
||||
const couponsToCreate = Object.fromEntries(
|
||||
Object.entries(coupon_data).filter(([k]) => parseInt(k) < 0)
|
||||
);
|
||||
|
||||
const couponCreateVals = Object.values(couponsToCreate).map((p) => ({
|
||||
program_id: p.program_id,
|
||||
partner_id: p.partner_id || false,
|
||||
code: p.code || p.barcode || `CODE${Math.floor(Math.random() * 10000)}`,
|
||||
points: p.points || 0,
|
||||
}));
|
||||
|
||||
const newCouponIds = this.env["loyalty.card"].create(couponCreateVals);
|
||||
const newCoupons = this.env["loyalty.card"].browse(newCouponIds);
|
||||
|
||||
for (let i = 0; i < Object.keys(couponsToCreate).length; i++) {
|
||||
const oldId = parseInt(Object.keys(couponsToCreate)[i], 10);
|
||||
const newCoupon = newCouponIds[i];
|
||||
couponNewIdMap[oldId] = newCoupon.id;
|
||||
}
|
||||
|
||||
const allCoupons = this.env["loyalty.card"].browse(Object.keys(couponNewIdMap).map(Number));
|
||||
for (const coupon of allCoupons) {
|
||||
const oldId = couponNewIdMap[coupon.id];
|
||||
if (oldId && coupon_data[oldId]) {
|
||||
coupon.points += coupon_data[oldId].points;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
coupon_updates: allCoupons.map((coupon) => ({
|
||||
old_id: couponNewIdMap[coupon.id],
|
||||
id: coupon.id,
|
||||
points: coupon.points,
|
||||
code: coupon.code,
|
||||
program_id: coupon.program_id,
|
||||
partner_id: coupon.partner_id,
|
||||
})),
|
||||
program_updates: [...new Set(allCoupons.map((c) => c.program_id))].map((program) => ({
|
||||
program_id: program,
|
||||
usages: this.env["loyalty.program"].browse(program)?.[0]?.total_order_count,
|
||||
})),
|
||||
new_coupon_info: newCoupons.map((c) => ({
|
||||
program_name: this.env["loyalty.program"].browse(c.program_id)?.[0]?.name || "",
|
||||
expiration_date: c.expiration_date || false,
|
||||
code: c.code,
|
||||
})),
|
||||
coupon_report: {},
|
||||
};
|
||||
},
|
||||
|
||||
add_loyalty_history_lines() {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { PosOrderLine } from "@point_of_sale/../tests/unit/data/pos_order_line.data";
|
||||
|
||||
patch(PosOrderLine.prototype, {
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
...super._load_pos_data_fields(),
|
||||
"is_reward_line",
|
||||
"reward_id",
|
||||
"coupon_id",
|
||||
"reward_identifier_code",
|
||||
"points_cost",
|
||||
];
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { PosSession } from "@point_of_sale/../tests/unit/data/pos_session.data";
|
||||
|
||||
patch(PosSession.prototype, {
|
||||
_load_pos_data_models() {
|
||||
return [
|
||||
...super._load_pos_data_models(),
|
||||
"loyalty.card",
|
||||
"loyalty.program",
|
||||
"loyalty.reward",
|
||||
"loyalty.rule",
|
||||
];
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { ProductProduct } from "@point_of_sale/../tests/unit/data/product_product.data";
|
||||
|
||||
patch(ProductProduct.prototype, {
|
||||
_load_pos_data_fields() {
|
||||
return [...super._load_pos_data_fields(), "all_product_tag_ids"];
|
||||
},
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue