Merge pull request #20 from bakeupboys/53-16.0-add_open_packages_list_to_webshop
[IMP] Add Open Packagings Filter to Webshop
This commit is contained in:
commit
329a52e680
11 changed files with 234 additions and 12 deletions
|
|
@ -37,6 +37,7 @@ Changelog
|
||||||
|
|
||||||
:0.0.1: Initial module.
|
:0.0.1: Initial module.
|
||||||
:1.0.0: Live
|
:1.0.0: Live
|
||||||
|
:1.1.0: Add Open Packagings Filter and fix rounding issue
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"author": "BAKEUP",
|
"author": "BAKEUP",
|
||||||
"website": "https://www.bakeup.org",
|
"website": "https://www.bakeup.org",
|
||||||
"category": "website",
|
"category": "website",
|
||||||
"version": "16.0.1.0.0",
|
"version": "16.0.1.1.0",
|
||||||
"depends": ["website_sale", "nfu_sale_order_batch_packaging", "website_decimal_quantity"],
|
"depends": ["website_sale", "nfu_sale_order_batch_packaging", "website_decimal_quantity"],
|
||||||
"data": ["views/product_template_views.xml", "views/templates.xml"],
|
"data": ["views/product_template_views.xml", "views/templates.xml"],
|
||||||
"assets": {"web.assets_frontend": ["nfu_ecommerce/static/src/js/website_sale.js"]},
|
"assets": {"web.assets_frontend": ["nfu_ecommerce/static/src/js/website_sale.js"]},
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from odoo import fields, http
|
from odoo import fields, http
|
||||||
|
from odoo.http import request
|
||||||
|
|
||||||
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
from odoo.addons.website_sale.controllers.main import WebsiteSale
|
||||||
|
|
||||||
|
|
@ -10,3 +11,49 @@ class WebsiteSaleMinMax(WebsiteSale):
|
||||||
product_uom_ordered_qty = fields.Float(ordered_qty)
|
product_uom_ordered_qty = fields.Float(ordered_qty)
|
||||||
product_uom_max_qty = fields.Float(max_qty)
|
product_uom_max_qty = fields.Float(max_qty)
|
||||||
return super().cart_update(*args, ordered_qty=product_uom_ordered_qty, max_qty=product_uom_max_qty, **kw)
|
return super().cart_update(*args, ordered_qty=product_uom_ordered_qty, max_qty=product_uom_max_qty, **kw)
|
||||||
|
|
||||||
|
|
||||||
|
class WebsiteSale(WebsiteSale):
|
||||||
|
def _get_additional_shop_values(self, values):
|
||||||
|
new_values = super()._get_additional_shop_values(values)
|
||||||
|
new_values["open_packagings"] = True if request.httprequest.args.get("open_packagings") else False
|
||||||
|
return new_values
|
||||||
|
|
||||||
|
def _get_search_options(
|
||||||
|
self, category=None, attrib_values=None, pricelist=None, min_price=0.0, max_price=0.0, conversion_rate=1, **post
|
||||||
|
):
|
||||||
|
res = super()._get_search_options(
|
||||||
|
category=category,
|
||||||
|
attrib_values=attrib_values,
|
||||||
|
pricelist=pricelist,
|
||||||
|
min_price=min_price,
|
||||||
|
max_price=max_price,
|
||||||
|
conversion_rate=conversion_rate,
|
||||||
|
**post
|
||||||
|
)
|
||||||
|
res["open_product_ids"] = post.get("open_product_ids")
|
||||||
|
return res
|
||||||
|
|
||||||
|
@http.route(
|
||||||
|
[
|
||||||
|
"/shop",
|
||||||
|
"/shop/page/<int:page>",
|
||||||
|
'/shop/category/<model("product.public.category"):category>',
|
||||||
|
'/shop/category/<model("product.public.category"):category>/page/<int:page>',
|
||||||
|
],
|
||||||
|
type="http",
|
||||||
|
auth="public",
|
||||||
|
website=True,
|
||||||
|
)
|
||||||
|
def shop(self, page=0, category=None, search="", min_price=0.0, max_price=0.0, ppg=False, **post):
|
||||||
|
open_packages = bool(post.get("open_packagings"))
|
||||||
|
if open_packages:
|
||||||
|
batch = request.website.sale_get_order(force_create=True).batch_id
|
||||||
|
open_product_ids = (
|
||||||
|
batch.product_ids.filtered(lambda p: p.open_packaging_qty > 0).mapped("product_template_id").ids
|
||||||
|
)
|
||||||
|
post["open_product_ids"] = open_product_ids
|
||||||
|
else:
|
||||||
|
post["open_product_ids"] = None
|
||||||
|
res = super().shop(page=0, category=None, search="", min_price=0.0, max_price=0.0, ppg=False, **post)
|
||||||
|
return res
|
||||||
|
|
|
||||||
120
nfu_ecommerce/i18n/de.po
Normal file
120
nfu_ecommerce/i18n/de.po
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * nfu_ecommerce
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Odoo Server 16.0\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2024-10-04 19:54+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-10-04 19:54+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
msgid "<span>Max Qty</span>"
|
||||||
|
msgstr "<span>Max Menge</span>"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
msgid "Add one"
|
||||||
|
msgstr "Einen hinzufügen"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.o_wsale_offcanvas
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.products_open_packaging
|
||||||
|
msgid "All Products"
|
||||||
|
msgstr "Alle Produkte"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model.fields,field_description:nfu_ecommerce.field_sale_order__balance
|
||||||
|
msgid "Balance"
|
||||||
|
msgstr "Guthaben"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.total
|
||||||
|
msgid "Balance:"
|
||||||
|
msgstr "Aktuelles Guthaben:"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_summary_packaging
|
||||||
|
msgid "Max Ordered Quantity:"
|
||||||
|
msgstr "Max Menge"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_summary_packaging
|
||||||
|
msgid "Max Qty"
|
||||||
|
msgstr "Max Menge:"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.total
|
||||||
|
msgid "New balance:"
|
||||||
|
msgstr "Neues Guthaben:"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
msgid "No open package available"
|
||||||
|
msgstr "Keine offenen Gebinde"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_summary_packaging
|
||||||
|
msgid "Open Package:"
|
||||||
|
msgstr "Offenes Gebinde:"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.o_wsale_offcanvas
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.products_open_packaging
|
||||||
|
msgid "Open Packagings"
|
||||||
|
msgstr "Offene Gebinde"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model.fields,field_description:nfu_ecommerce.field_sale_order_line__open_qty
|
||||||
|
msgid "Open Qty"
|
||||||
|
msgstr "Offene Menge"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model,name:nfu_ecommerce.model_product_template
|
||||||
|
msgid "Product"
|
||||||
|
msgstr "Produkt"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.product_template_tree_view
|
||||||
|
msgid "Publish on Website"
|
||||||
|
msgstr "Veröffentlichen"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
msgid "Remove one"
|
||||||
|
msgstr "Eins entfernen"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model,name:nfu_ecommerce.model_sale_order
|
||||||
|
msgid "Sales Order"
|
||||||
|
msgstr "Verkaufsauftrag"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model,name:nfu_ecommerce.model_sale_order_line
|
||||||
|
msgid "Sales Order Line"
|
||||||
|
msgstr "Verkaufsauftragszeile"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.product_template_tree_view
|
||||||
|
msgid "Unpublish on Website"
|
||||||
|
msgstr "Von Website entfernen"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model:ir.model.fields,field_description:nfu_ecommerce.field_sale_order__updated_balance
|
||||||
|
msgid "Updated Balance"
|
||||||
|
msgstr "Zukünftiges Guthaben"
|
||||||
|
|
||||||
|
#. module: nfu_ecommerce
|
||||||
|
#: model_terms:ir.ui.view,arch_db:nfu_ecommerce.cart_lines_packaging
|
||||||
|
msgid "Warning"
|
||||||
|
msgstr "Warnung"
|
||||||
|
|
@ -11,3 +11,11 @@ class ProductTemplate(models.Model):
|
||||||
def action_unpublish_on_website(self):
|
def action_unpublish_on_website(self):
|
||||||
for product in self:
|
for product in self:
|
||||||
product.is_published = False
|
product.is_published = False
|
||||||
|
|
||||||
|
def _search_get_detail(self, website, order, options):
|
||||||
|
search_details = super()._search_get_detail(website, order, options)
|
||||||
|
open_product_ids = options.get("open_product_ids")
|
||||||
|
domain = search_details["base_domain"]
|
||||||
|
if open_product_ids is not None:
|
||||||
|
domain.append([("id", "in", tuple(open_product_ids))])
|
||||||
|
return search_details
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
from odoo import models
|
from odoo import fields, models
|
||||||
|
from odoo.tools import float_is_zero, float_round
|
||||||
|
|
||||||
|
|
||||||
class SaleOrderLine(models.Model):
|
class SaleOrderLine(models.Model):
|
||||||
_inherit = "sale.order.line"
|
_inherit = "sale.order.line"
|
||||||
|
|
||||||
def compute_open_packages(self):
|
open_qty = fields.Float(compute="_compute_open_qty")
|
||||||
self.ensure_one()
|
|
||||||
qty_of_last_pack = self.batch_uom_qty % self.product_packaging_id.qty
|
def _compute_open_qty(self):
|
||||||
open_qty = self.product_packaging_id.qty - qty_of_last_pack
|
for line in self:
|
||||||
return open_qty
|
if line.product_packaging_id:
|
||||||
|
precision_rounding = line.product_id.uom_id.rounding
|
||||||
|
precision_digits = len(str(precision_rounding).split(".")[1])
|
||||||
|
qty_of_last_pack = float_round(
|
||||||
|
line.batch_uom_qty % line.product_packaging_id.qty, precision_rounding=precision_rounding
|
||||||
|
)
|
||||||
|
if not float_is_zero(qty_of_last_pack, precision_rounding=precision_rounding):
|
||||||
|
line.open_qty = round(line.product_packaging_id.qty - qty_of_last_pack, precision_digits)
|
||||||
|
else:
|
||||||
|
line.open_qty = 0.0
|
||||||
|
else:
|
||||||
|
line.open_qty = 0.0
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
:0.0.1: Initial module.
|
:0.0.1: Initial module.
|
||||||
:1.0.0: Live
|
:1.0.0: Live
|
||||||
|
:1.1.0: Add Open Packagings Filter and fix rounding issue
|
||||||
|
|
@ -397,6 +397,8 @@ and after the current order.</p>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="field"><th class="field-name">1.0.0:</th><td class="field-body">Live</td>
|
<tr class="field"><th class="field-name">1.0.0:</th><td class="field-body">Live</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr class="field"><th class="field-name">1.1.0:</th><td class="field-body">Add Open Packagings Filter and fix rounding issue</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,39 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
|
<template id="products_open_packaging" inherit_id="website_sale.products">
|
||||||
|
<xpath expr="//aside[@id='products_grid_before']/div[1]/div[1]" position="before">
|
||||||
|
<a t-att-href="keep('/shop',open_packagings = False if open_packagings else True)">
|
||||||
|
<h6 t-attf-class="o_packaging_collapse_title mb-3 {{_titleClasses}}"><b>
|
||||||
|
<span t-if="open_packagings">All Products</span>
|
||||||
|
<span t-else="">Open Packagings</span>
|
||||||
|
</b></h6>
|
||||||
|
</a>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="o_wsale_offcanvas" name="Open Packagings" inherit_id="website_sale.o_wsale_offcanvas">
|
||||||
|
<xpath expr="//div[@id='o_wsale_offcanvas_content']/div[1]" position="before">
|
||||||
|
<div class="position-relative o_wsale_offcanvas_title px-4 border-top">
|
||||||
|
<a t-att-href="keep('/shop',open_packagings = False if open_packagings else True)">
|
||||||
|
<h6 t-attf-class="o_packaging_collapse_title mb-3 pt-3 {{_titleClasses}}"><b>
|
||||||
|
<span t-if="open_packagings">All Products</span>
|
||||||
|
<span t-else="">Open Packagings</span>
|
||||||
|
</b></h6>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="cart_lines_packaging" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
|
<template id="cart_lines_packaging" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
|
||||||
<xpath expr="//td[hasclass('td-product_name')]" position="inside">
|
<xpath expr="//td[hasclass('td-product_name')]" position="inside">
|
||||||
<div t-if="line.product_packaging_id and (line.product_packaging_id.qty != 1)">
|
<div t-if="line.product_packaging_id and (line.product_packaging_id.qty != 1)">
|
||||||
<span>Open Package: <t t-esc="line.compute_open_packages()"/>/<t t-esc="line.product_packaging_id.qty"/>
|
<span t-if="line.open_qty > 0">Open Package: <t t-esc="line.open_qty"/>/<t
|
||||||
</span><br/>
|
t-esc="line.product_packaging_id.qty"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span t-else="">No open package available</span>
|
||||||
|
<br/>
|
||||||
<span>Max Ordered Quantity: <span
|
<span>Max Ordered Quantity: <span
|
||||||
t-esc="line.batch_uom_max_qty"
|
t-esc="line.batch_uom_max_qty"
|
||||||
t-attf-class="#{'text-danger' if line.batch_uom_max_qty < line.product_packaging_id.qty else ''}"
|
t-attf-class="#{'text-danger' if line.batch_uom_max_qty < line.product_packaging_id.qty else ''}"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from odoo import api, fields, models
|
||||||
class SaleOrderBatchProduct(models.Model):
|
class SaleOrderBatchProduct(models.Model):
|
||||||
_inherit = "sale.order.batch.product"
|
_inherit = "sale.order.batch.product"
|
||||||
|
|
||||||
open_packaging_qty = fields.Float(compute="_compute_open_packagin_qty")
|
open_packaging_qty = fields.Float(compute="_compute_open_packagin_qty", store=True)
|
||||||
|
|
||||||
@api.depends("sale_order_line_ids.product_uom_qty")
|
@api.depends("sale_order_line_ids.product_uom_qty")
|
||||||
def _compute_open_packagin_qty(self):
|
def _compute_open_packagin_qty(self):
|
||||||
|
|
|
||||||
|
|
@ -28,13 +28,15 @@ class SaleOrderLine(models.Model):
|
||||||
if line.order_id.batch_id:
|
if line.order_id.batch_id:
|
||||||
batch_id = line.batch_id
|
batch_id = line.batch_id
|
||||||
product_id = line.product_id
|
product_id = line.product_id
|
||||||
|
precision_rounding = line.product_id.uom_id.rounding
|
||||||
|
precision_digits = len(str(precision_rounding).split(".")[1])
|
||||||
batch_lines = (
|
batch_lines = (
|
||||||
self.env["sale.order.line"]
|
self.env["sale.order.line"]
|
||||||
.sudo()
|
.sudo()
|
||||||
.search([("batch_id", "=", batch_id.id), ("product_id", "=", product_id.id)])
|
.search([("batch_id", "=", batch_id.id), ("product_id", "=", product_id.id)])
|
||||||
)
|
)
|
||||||
line.batch_uom_qty = sum(batch_lines.mapped("product_uom_qty"))
|
line.batch_uom_qty = sum(batch_lines.mapped("product_uom_qty"))
|
||||||
line.batch_uom_max_qty = sum(batch_lines.mapped("product_uom_max_qty"))
|
line.batch_uom_max_qty = round(sum(batch_lines.mapped("product_uom_max_qty")), precision_digits)
|
||||||
else:
|
else:
|
||||||
line.batch_uom_max_qty = line.batch_uom_qty = 0
|
line.batch_uom_max_qty = line.batch_uom_qty = 0
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue