[IMP] point_of_sale: allow hiding images

In this commit we add the ability to toggle between showing and not
showing product and category images in the pos ui.

Because this change is done in stable, we store the user's selection in
`ir.config.parameter`.

In the forward port, this will be removed and the settings will be
stored in `pos.config`

Task 3704416

closes odoo/odoo#151823

Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
This commit is contained in:
vlst-odoo
2024-02-01 07:06:48 +00:00
parent 42a72f6a20
commit cb0efa815d
8 changed files with 81 additions and 27 deletions
@@ -814,6 +814,10 @@ class PosConfig(models.Model):
except (TypeError, ValueError, OverflowError):
return default_limit
def toggle_images(self, for_products, for_categories):
self.env['ir.config_parameter'].sudo().set_param('point_of_sale.show_product_images', for_products)
self.env['ir.config_parameter'].sudo().set_param('point_of_sale.show_category_images', for_categories)
def get_limited_partners_loading(self):
self.env.cr.execute("""
WITH pm AS
@@ -1687,6 +1687,8 @@ class PosSession(models.Model):
loaded_data['pos_special_products_ids'] = self.env['pos.config']._get_special_products().ids
loaded_data['open_orders'] = self.env['pos.order'].search([('session_id', '=', self.id), ('state', '=', 'draft')]).export_for_ui()
loaded_data['partner_commercial_fields'] = self.env['res.partner']._commercial_fields()
loaded_data['show_product_images'] = self.env['ir.config_parameter'].sudo().get_param('point_of_sale.show_product_images', 'yes')
loaded_data['show_category_images'] = self.env['ir.config_parameter'].sudo().get_param('point_of_sale.show_category_images', 'yes')
@api.model
def _pos_ui_models_to_load(self):
@@ -22,7 +22,7 @@ export class CategorySelector extends Component {
icon: { type: String, optional: true },
separator: { type: String, optional: true },
showSeparator: { type: Boolean, optional: true },
imageUrl: { type: String, optional: true },
imageUrl: { type: [String, Boolean], optional: true },
},
},
class: { type: String, optional: true },
@@ -9,7 +9,7 @@ export class ProductCard extends Component {
name: String,
productId: Number,
price: String,
imageUrl: String,
imageUrl: [String, Boolean],
productInfo: { Boolean, optional: true },
onClick: { type: Function, optional: true },
onProductInfoClick: { type: Function, optional: true },
@@ -23,7 +23,7 @@
<ul>
<li class="menu-item position-relative d-flex">
<i class="fa fa-bars" aria-hidden="true"></i>
<ul class="dropdown-menu sub-menu position-absolute d-flex flex-column align-items-stretch w-100 bg-white shadow-lg z-index-1">
<ul class="dropdown-menu sub-menu position-absolute d-flex flex-column align-items-stretch bg-white shadow-lg z-index-1">
<li class="ticket-button" t-on-click="onTicketButtonClick">
<a class="dropdown-item with-badge py-2">
Orders
@@ -51,6 +51,18 @@
Switch Product View
</a>
</li>
<li class="menu-item navbar-button close-button" t-on-click="() => pos.toggleImages('product')">
<a class="dropdown-item py-2">
<t t-if="pos.show_product_images">Hide Product Images</t>
<t t-else="">Show Product Images</t>
</a>
</li>
<li class="menu-item navbar-button close-button" t-on-click="() => pos.toggleImages('category')">
<a class="dropdown-item py-2">
<t t-if="pos.show_category_images">Hide Category Images</t>
<t t-else="">Show Category Images</t>
</a>
</li>
<li t-if="this.env.debug" class="menu-item navbar-button" t-on-click="() => debug.toggleWidget()">
<a class="dropdown-item py-2">
Debug Window
@@ -48,6 +48,7 @@ export class ProductsWidget extends Component {
getShowCategoryImages() {
return (
this.pos.show_category_images &&
Object.values(this.pos.db.category_by_id).some((category) => category.has_image) &&
!this.ui.isSmall &&
this.state.height >= 720
@@ -26,7 +26,7 @@
name="product.display_name"
productId="product.id"
price="product.getFormattedUnitPrice()"
imageUrl="product.getImageUrl()"
imageUrl="pos.show_product_images and product.getImageUrl()"
onClick="() =>this.pos.addProductToCurrentOrder(product)"
productInfo="true"
onProductInfoClick="() => this.onProductInfoClick(product)"
@@ -180,6 +180,19 @@ export class PosStore extends Reactive {
this.preloadImages();
this.showScreen("ProductScreen");
}
toggleImages(imageType = "product") {
if (imageType === "product") {
this.show_product_images = !this.show_product_images;
}
if (imageType === "category") {
this.show_category_images = !this.show_category_images;
}
this.orm.silent.call("pos.config", "toggle_images", [
[this.config.id],
this.show_product_images ? "yes" : "no",
this.show_category_images ? "yes" : "no",
]);
}
get productListViewMode() {
const viewMode = this.productListView && this.ui.isSmall ? this.productListView : "grid";
if (viewMode === "grid") {
@@ -280,6 +293,8 @@ export class PosStore extends Reactive {
this.pos_has_valid_product = loadedData["pos_has_valid_product"];
this.db.addProductIdsToNotDisplay(loadedData["pos_special_products_ids"]);
this.partner_commercial_fields = loadedData["partner_commercial_fields"];
this.show_product_images = loadedData["show_product_images"] === "yes";
this.show_category_images = loadedData["show_category_images"] === "yes";
await this._loadPosPrinters(loadedData["pos.printer"]);
this.open_orders_json = loadedData["open_orders"];
}
@@ -1237,12 +1252,14 @@ export class PosStore extends Reactive {
try {
// FIXME POSREF timeout
// const timeout = typeof options.timeout === "number" ? options.timeout : 30000 * orders.length;
const serverIds = await orm.call("pos.order", "create_from_ui", [
orders,
options.draft || false,
], {
context: this._getCreateOrderContext(orders, options),
});
const serverIds = await orm.call(
"pos.order",
"create_from_ui",
[orders, options.draft || false],
{
context: this._getCreateOrderContext(orders, options),
}
);
for (const serverId of serverIds) {
const order = this.env.services.pos.orders.find(
@@ -1475,7 +1492,7 @@ export class PosStore extends Reactive {
// 2) Deal with the rounding methods
const company = this.company;
var round_tax = company.tax_calculation_rounding_method != 'round_globally';
var round_tax = company.tax_calculation_rounding_method != "round_globally";
var initial_currency_rounding = currency_rounding;
if (!round_tax) {
@@ -1483,20 +1500,23 @@ export class PosStore extends Reactive {
}
// 3) Iterate the taxes in the reversed sequence order to retrieve the initial base of the computation.
var recompute_base = function(base_amount, incl_tax_amounts){
var recompute_base = function (base_amount, incl_tax_amounts) {
let fixed_amount = incl_tax_amounts.fixed_amount;
let division_amount = 0.0;
for(const [, tax_factor] of incl_tax_amounts.division_taxes){
for (const [, tax_factor] of incl_tax_amounts.division_taxes) {
division_amount += tax_factor;
}
let percent_amount = 0.0;
for(const [, tax_factor] of incl_tax_amounts.percent_taxes){
for (const [, tax_factor] of incl_tax_amounts.percent_taxes) {
percent_amount += tax_factor;
}
if(company.country && company.country.code === "IN"){
for(const [i, tax_factor] of incl_tax_amounts.percent_taxes){
const tax_amount = round_pr(base_amount * tax_factor / (100 + percent_amount), currency_rounding);
if (company.country && company.country.code === "IN") {
for (const [i, tax_factor] of incl_tax_amounts.percent_taxes) {
const tax_amount = round_pr(
(base_amount * tax_factor) / (100 + percent_amount),
currency_rounding
);
cached_tax_amounts[i] = tax_amount;
fixed_amount += tax_amount;
}
@@ -1509,8 +1529,12 @@ export class PosStore extends Reactive {
fixed_amount: 0.0,
});
return (base_amount - fixed_amount) / (1.0 + percent_amount / 100.0) * (100 - division_amount) / 100;
}
return (
(((base_amount - fixed_amount) / (1.0 + percent_amount / 100.0)) *
(100 - division_amount)) /
100
);
};
var base = round_pr(price_unit * quantity, initial_currency_rounding);
@@ -1528,7 +1552,7 @@ export class PosStore extends Reactive {
percent_taxes: [],
division_taxes: [],
fixed_amount: 0.0,
}
};
var cached_tax_amounts = {};
if (handle_price_include) {
@@ -1539,11 +1563,18 @@ export class PosStore extends Reactive {
}
if (tax.price_include) {
if (tax.amount_type === "percent") {
incl_tax_amounts.percent_taxes.push([i, tax.amount * tax.sum_repartition_factor]);
incl_tax_amounts.percent_taxes.push([
i,
tax.amount * tax.sum_repartition_factor,
]);
} else if (tax.amount_type === "division") {
incl_tax_amounts.division_taxes.push([i, tax.amount * tax.sum_repartition_factor]);
incl_tax_amounts.division_taxes.push([
i,
tax.amount * tax.sum_repartition_factor,
]);
} else if (tax.amount_type === "fixed") {
incl_tax_amounts.fixed_amount += Math.abs(quantity) * tax.amount * tax.sum_repartition_factor;
incl_tax_amounts.fixed_amount +=
Math.abs(quantity) * tax.amount * tax.sum_repartition_factor;
} else {
var tax_amount = self._compute_all(tax, base, quantity);
incl_tax_amounts.fixed_amount += tax_amount;
@@ -1558,7 +1589,10 @@ export class PosStore extends Reactive {
});
}
var total_excluded = round_pr(recompute_base(base, incl_tax_amounts), initial_currency_rounding);
var total_excluded = round_pr(
recompute_base(base, incl_tax_amounts),
initial_currency_rounding
);
var total_included = total_excluded;
// 4) Iterate the taxes in the sequence order to fill missing base/amount values.
@@ -1583,11 +1617,12 @@ export class PosStore extends Reactive {
total_included_checkpoints[i] !== undefined &&
tax.sum_repartition_factor != 0
) {
var tax_amount = total_included_checkpoints[i] - (base + cumulated_tax_included_amount);
var tax_amount =
total_included_checkpoints[i] - (base + cumulated_tax_included_amount);
cumulated_tax_included_amount = 0;
}else if(tax.price_include && cached_tax_amounts.hasOwnProperty(i)){
} else if (tax.price_include && cached_tax_amounts.hasOwnProperty(i)) {
var tax_amount = cached_tax_amounts[i];
}else{
} else {
var tax_amount = self._compute_all(tax, tax_base_amount, quantity, true);
}