Initial commit: Pos packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 95dfb9edb0
1301 changed files with 264148 additions and 0 deletions

View file

@ -0,0 +1,91 @@
odoo.define('pos_discount.DiscountButton', function(require) {
'use strict';
const PosComponent = require('point_of_sale.PosComponent');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require("@web/core/utils/hooks");
const Registries = require('point_of_sale.Registries');
class DiscountButton extends PosComponent {
setup() {
super.setup();
useListener('click', this.onClick);
}
async onClick() {
var self = this;
const { confirmed, payload } = await this.showPopup('NumberPopup',{
title: this.env._t('Discount Percentage'),
startingValue: this.env.pos.config.discount_pc,
isInputSelected: true
});
if (confirmed) {
const val = Math.max(0,Math.min(100,parseFloat(payload)));
await self.apply_discount(val);
}
}
async apply_discount(pc) {
var order = this.env.pos.get_order();
var lines = order.get_orderlines();
var product = this.env.pos.db.get_product_by_id(this.env.pos.config.discount_product_id[0]);
if (product === undefined) {
await this.showPopup('ErrorPopup', {
title : this.env._t("No discount product found"),
body : this.env._t("The discount product seems misconfigured. Make sure it is flagged as 'Can be Sold' and 'Available in Point of Sale'."),
});
return;
}
// Remove existing discounts
lines.filter(line => line.get_product() === product)
.forEach(line => order.remove_orderline(line));
// Add one discount line per tax group
let linesByTax = order.get_orderlines_grouped_by_tax_ids();
for (let [tax_ids, lines] of Object.entries(linesByTax)) {
// Note that tax_ids_array is an Array of tax_ids that apply to these lines
// That is, the use case of products with more than one tax is supported.
let tax_ids_array = tax_ids.split(',').filter(id => id !== '').map(id => Number(id));
let baseToDiscount = order.calculate_base_amount(
tax_ids_array, lines.filter(ll => ll.isGlobalDiscountApplicable())
);
// We add the price as manually set to avoid recomputation when changing customer.
let discount = - pc / 100.0 * baseToDiscount;
if (discount < 0) {
order.add_product(product, {
price: discount,
lst_price: discount,
tax_ids: tax_ids_array,
merge: false,
description:
`${pc}%, ` +
(tax_ids_array.length ?
_.str.sprintf(
this.env._t('Tax: %s'),
tax_ids_array.map(taxId => this.env.pos.taxes_by_id[taxId].amount + '%').join(', ')
) :
this.env._t('No tax')),
extras: {
price_automatically_set: true,
},
});
}
}
}
}
DiscountButton.template = 'DiscountButton';
ProductScreen.addControlButton({
component: DiscountButton,
condition: function() {
return this.env.pos.config.module_pos_discount && this.env.pos.config.discount_product_id;
},
});
Registries.Component.add(DiscountButton);
return DiscountButton;
});

View file

@ -0,0 +1,18 @@
odoo.define('pos_discount.models', function (require) {
"use strict";
const { Orderline } = require('point_of_sale.models');
const Registries = require('point_of_sale.Registries');
const PosDiscountOrderline = (Orderline) => class PosDiscountOrderline extends Orderline {
/**
* Checks if the current line applies for a global discount from `pos_discount.DiscountButton`.
* @returns Boolean
*/
isGlobalDiscountApplicable() {
return !(this.pos.config.tip_product_id && this.product.id === this.pos.config.tip_product_id[0]);
}
}
Registries.Model.extend(Orderline, PosDiscountOrderline);
});

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="DiscountButton" owl="1">
<span class="control-button js_discount">
<i class="fa fa-tag"></i>
<span> </span>
<span>Discount</span>
</span>
</t>
</templates>