[imp] add nfu_ecommerce module, add balance to cart

This commit is contained in:
Niels Göttsch 2024-07-27 00:36:18 +02:00
parent 65544c0c44
commit 9d9d7643d7
47 changed files with 246 additions and 455 deletions

4
.vscode/launch.json vendored
View file

@ -9,12 +9,12 @@
"program": "${config:odoo.path}/odoo-bin", "program": "${config:odoo.path}/odoo-bin",
"console": "integratedTerminal", "console": "integratedTerminal",
"args": [ "args": [
"--database=nfu_", "--database=nfu_ecommerce",
"--addons-path=${config:odoo.addons_path},${workspaceFolder}", "--addons-path=${config:odoo.addons_path},${workspaceFolder}",
"--limit-time-real=0", "--limit-time-real=0",
"--limit-time-cpu=0", "--limit-time-cpu=0",
// "--init=", // "--init=",
// "--update=", "--update=nfu_ecommerce",
"--dev=xml" "--dev=xml"
] ]
}, },

View file

@ -1,6 +1,6 @@
========================== =============
NFU Sale Min Max Quantitiy NFU eCommerce
========================== =============
.. ..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@ -17,12 +17,13 @@ NFU Sale Min Max Quantitiy
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3 :alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github
:target: https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_product_min_max_qty :target: https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_ecommerce
:alt: bruecksen/ife_nfu :alt: bruecksen/ife_nfu
|badge1| |badge2| |badge3| |badge1| |badge2| |badge3|
This module adds a minium and a maximum order quantity field to Sale Orders and adds it to checkout of the website shop. This module adds a minium and a maximum order quantity field to Website Sale Orders
and adds it the customer balance to checkout of the website shop.
**Table of contents** **Table of contents**
@ -32,7 +33,7 @@ This module adds a minium and a maximum order quantity field to Sale Orders and
Changelog Changelog
========= =========
:1.0.0: Initial module. :0.0.1: Initial module.
Bug Tracker Bug Tracker
=========== ===========
@ -40,7 +41,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/bruecksen/ife_nfu/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/bruecksen/ife_nfu/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_product_min_max_qty%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. `feedback <https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_ecommerce%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@ -61,6 +62,6 @@ Contributors
Maintainers Maintainers
~~~~~~~~~~~ ~~~~~~~~~~~
This module is part of the `bruecksen/ife_nfu <https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_product_min_max_qty>`_ project on GitHub. This module is part of the `bruecksen/ife_nfu <https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_ecommerce>`_ project on GitHub.
You are welcome to contribute. You are welcome to contribute.

View file

@ -1,3 +1,2 @@
from . import models from . import models
from . import controllers from . import controllers
from . import wizard

View file

@ -0,0 +1,12 @@
{
"name": "NFU eCommerce",
"summary": "Qty ranges, packagings and credit in webshop",
"author": "BAKEUP",
"website": "https://www.bakeup.org",
"category": "website",
"version": "16.0.0.0.1",
"depends": ["sale_management", "website_sale", "nfu_sale_order_batch_packaging"],
"data": ["views/templates.xml"],
"assets": {"web.assets_frontend": ["nfu_sale_product_min_max_qty/static/src/js/website_sale.js"]},
"license": "LGPL-3",
}

View file

@ -0,0 +1 @@
from . import main

View file

@ -0,0 +1,12 @@
from odoo import fields, http
from odoo.addons.website_sale.controllers.main import WebsiteSale
class WebsiteSaleMinMax(WebsiteSale):
@http.route()
def cart_update(self, *args, ordered_qty=None, max_qty=None, **kw):
"""Override to get ordered_qty and max_qty from the product."""
product_uom_ordered_qty = fields.Float(ordered_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)

View file

@ -0,0 +1 @@
from . import sale_order

View file

@ -0,0 +1,49 @@
from odoo import api, fields, models
class SaleOrder(models.Model):
_inherit = "sale.order"
balance = fields.Monetary(compute="_compute_balance")
updated_balance = fields.Monetary(compute="_compute_updated_balance")
def _compute_balance(self):
for order in self:
order.balance = -order.partner_id.commercial_partner_id.credit
@api.depends("amount_total")
def _compute_updated_balance(self):
for order in self:
order.updated_balance = order.balance - (order.amount_total / order.currency_rate)
def _prepare_order_line_values(
self,
product_id,
quantity,
linked_line_id=False,
no_variant_attribute_values=None,
product_custom_attribute_values=None,
**kwargs
):
values = super()._prepare_order_line_values(
product_id,
quantity,
linked_line_id=linked_line_id,
no_variant_attribute_values=no_variant_attribute_values,
product_custom_attribute_values=product_custom_attribute_values,
**kwargs
)
values.update({"product_uom_ordered_qty": quantity, "product_uom_max_qty": kwargs.get("max_qty", quantity)})
return values
def _prepare_order_line_update_values(self, order_line, quantity, linked_line_id=False, **kwargs):
values = super()._prepare_order_line_update_values(
order_line, quantity, linked_line_id=linked_line_id, **kwargs
)
max_qty = kwargs.get("max_qty", quantity)
if quantity != order_line.product_uom_ordered_qty:
values["product_uom_ordered_qty"] = quantity
if max_qty and max_qty != order_line.product_uom_max_qty:
values["product_uom_max_qty"] = max_qty
return values

View file

@ -0,0 +1,2 @@
This module adds a minium and a maximum order quantity field to Website Sale Orders
and adds it the customer balance to checkout of the website shop.

View file

@ -0,0 +1 @@
:0.0.1: Initial module.

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" /> <meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>NFU Sale Min Max Quantitiy</title> <title>NFU eCommerce</title>
<style type="text/css"> <style type="text/css">
/* /*
@ -360,8 +360,8 @@ ul.auto-toc {
</style> </style>
</head> </head>
<body> <body>
<div class="document" id="nfu-sale-min-max-quantitiy"> <div class="document" id="nfu-ecommerce">
<h1 class="title">NFU Sale Min Max Quantitiy</h1> <h1 class="title">NFU eCommerce</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
@ -369,8 +369,9 @@ ul.auto-toc {
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4dfaea54e4d01502b433eb5c0dcca409a5fbe2c3f175e29382a19230343183c9 !! source digest: sha256:4dfaea54e4d01502b433eb5c0dcca409a5fbe2c3f175e29382a19230343183c9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_product_min_max_qty"><img alt="bruecksen/ife_nfu" src="https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github" /></a></p> <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_ecommerce"><img alt="bruecksen/ife_nfu" src="https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github" /></a></p>
<p>This module adds a minium and a maximum order quantity field to Sale Orders and adds it to checkout of the website shop.</p> <p>This module adds a minium and a maximum order quantity field to Website Sale Orders
and adds it the customer balance to checkout of the website shop.</p>
<p><strong>Table of contents</strong></p> <p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents"> <div class="contents local topic" id="contents">
<ul class="simple"> <ul class="simple">
@ -390,7 +391,7 @@ ul.auto-toc {
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
<tbody valign="top"> <tbody valign="top">
<tr class="field"><th class="field-name">1.0.0:</th><td class="field-body">Initial module.</td> <tr class="field"><th class="field-name">0.0.1:</th><td class="field-body">Initial module.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -400,7 +401,7 @@ ul.auto-toc {
<p>Bugs are tracked on <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_product_min_max_qty%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_ecommerce%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@ -420,7 +421,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2> <h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_product_min_max_qty">bruecksen/ife_nfu</a> project on GitHub.</p> <p>This module is part of the <a class="reference external" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_ecommerce">bruecksen/ife_nfu</a> project on GitHub.</p>
<p>You are welcome to contribute.</p> <p>You are welcome to contribute.</p>
</div> </div>
</div> </div>

View file

@ -1,4 +1,4 @@
odoo.define("nfu_sale_product_min_max_qty.website_min_max_qty", function (require) { odoo.define("nfu_ecommerce.website_min_max_qty", function (require) {
"use strict"; "use strict";
var core = require("web.core"); var core = require("web.core");
var _t = core._t; var _t = core._t;

View file

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="cart_lines_min_max_qty" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="text-center td-qty">
<t t-if="show_qty">
<span>Max qty.</span>
</t>
</th>
</xpath>
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class="text-center td-qty">
<div class="css_quantity input-group mx-auto justify-content-center">
<t t-if="not line._is_not_sellable_line()">
<t t-if="show_qty">
<a
t-attf-href="#"
class="btn btn-link js_add_cart_json d-none d-md-inline-block"
aria-label="Remove one"
title="Remove one"
>
<i class="fa fa-minus"/>
</a>
<input
type="text"
name="max-qty"
class="js_quantity form-control quantity"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="line.product_uom_max_qty and int(line.product_uom_max_qty) or int(line.product_uom_qty)"
t-att-data-min="int(line.product_uom_qty)"
/>
<t t-if="line._get_shop_warning(clear=False)">
<a t-attf-href="#" class="btn btn-link">
<i
class='fa fa-warning text-warning'
t-att-title="line._get_shop_warning()"
role="img"
aria-label="Warning"
/>
</a>
</t>
<a
t-else=''
t-attf-href="#"
class="btn btn-link float_left js_add_cart_json d-none d-md-inline-block"
aria-label="Add one"
title="Add one"
>
<i class="fa fa-plus"/>
</a>
</t>
<t t-else="">
<input
type="hidden"
class="js_quantity form-control quantity"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="int(line.product_uom_qty) == line.product_uom_qty and int(line.product_uom_qty) or line.product_uom_qty"
/>
</t>
</t>
<t t-else="">
<span class="text-muted w-100" t-esc="int(line.product_uom_qty)"/>
<input
type="hidden"
class="js_quantity form-control quantity"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="line.product_uom_qty"
/>
</t>
</div>
</td>
</xpath>
</template>
<template id="cart_summary_min_max_qty" inherit_id="website_sale.cart_summary" name="Cart right column">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="border-top-0 td-qty">Max qty.</th>
</xpath>
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class='td-qty'>
<div t-esc="line.product_uom_max_qty"/>
</td>
</xpath>
</template>
<template id="total" inherit_id="website_sale.total">
<xpath expr="//tr[@id='empty']" position="after">
<tr id="balance">
<td class="text-end border-0">Balance:</td>
<td class="text-xl-end border-0">
<span
t-field="website_sale_order.balance"
class="monetary_field"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"
/>
</td>
</tr>
</xpath>
<xpath expr="//tr[@id='order_total']" position="after">
<tr id="updated_balance">
<td class="text-end border-0">New balance:</td>
<td class="text-xl-end border-0">
<t t-if="website_sale_order.updated_balance &lt; 0">
<span
t-field="website_sale_order.updated_balance"
class="monetary_field text-danger"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"
/>
</t>
<t t-else="">
<span
t-field="website_sale_order.updated_balance"
t-att-class="monetary_field"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"
/>
</t>
</td>
</tr>
</xpath>
</template>
</odoo>

View file

@ -1,6 +1,6 @@
======================== ==============================
NFU Sale Order Packaging NFU Sale Order Batch Packaging
======================== ==============================
.. ..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@ -17,7 +17,7 @@ NFU Sale Order Packaging
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3 :alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github
:target: https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_packaging :target: https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_batch_packaging
:alt: bruecksen/ife_nfu :alt: bruecksen/ife_nfu
|badge1| |badge2| |badge3| |badge1| |badge2| |badge3|
@ -33,7 +33,8 @@ and adds a packaging default to sale order batch.
Changelog Changelog
========= =========
:1.0.0: Initial module. :0.0.1: Initial module.
:1.0.0: rename to nfu_sale_order_batch_packaging
Bug Tracker Bug Tracker
=========== ===========
@ -41,7 +42,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/bruecksen/ife_nfu/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/bruecksen/ife_nfu/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_order_packaging%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. `feedback <https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_order_batch_packaging%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@ -62,6 +63,6 @@ Contributors
Maintainers Maintainers
~~~~~~~~~~~ ~~~~~~~~~~~
This module is part of the `bruecksen/ife_nfu <https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_packaging>`_ project on GitHub. This module is part of the `bruecksen/ife_nfu <https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_batch_packaging>`_ project on GitHub.
You are welcome to contribute. You are welcome to contribute.

View file

@ -1,10 +1,10 @@
{ {
"name": "NFU Sale Order Packaging", "name": "NFU Sale Order Batch Packaging",
"summary": "Add minimum and maximum order quantities to sale orders and use default packaging", "summary": "Add minimum and maximum order quantities to sale orders and batches and use default packaging",
"author": "BAKEUP", "author": "BAKEUP",
"website": "https://www.bakeup.org", "website": "https://www.bakeup.org",
"category": "Sale", "category": "Sale",
"version": "16.0.0.0.1", "version": "16.0.1.0.0",
"depends": ["sale", "sale_order_batch"], "depends": ["sale", "sale_order_batch"],
"data": [ "data": [
"views/sale_order_views.xml", "views/sale_order_views.xml",

View file

@ -0,0 +1,2 @@
:0.0.1: Initial module.
:1.0.0: rename to nfu_sale_order_batch_packaging

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" /> <meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>NFU Sale Order Packaging</title> <title>NFU Sale Order Batch Packaging</title>
<style type="text/css"> <style type="text/css">
/* /*
@ -360,8 +360,8 @@ ul.auto-toc {
</style> </style>
</head> </head>
<body> <body>
<div class="document" id="nfu-sale-order-packaging"> <div class="document" id="nfu-sale-order-batch-packaging">
<h1 class="title">NFU Sale Order Packaging</h1> <h1 class="title">NFU Sale Order Batch Packaging</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! <!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
@ -369,7 +369,7 @@ ul.auto-toc {
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:cf35c3a80aa0718148099036cd6a3dd60afb61acdb420573b1bd129be3ea2cf1 !! source digest: sha256:cf35c3a80aa0718148099036cd6a3dd60afb61acdb420573b1bd129be3ea2cf1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_packaging"><img alt="bruecksen/ife_nfu" src="https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github" /></a></p> <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_batch_packaging"><img alt="bruecksen/ife_nfu" src="https://img.shields.io/badge/github-bruecksen%2Fife_nfu-lightgray.png?logo=github" /></a></p>
<p>This module adds a minium and a maximum order quantity field to Sale Orders <p>This module adds a minium and a maximum order quantity field to Sale Orders
and adds a packaging default to sale order batch.</p> and adds a packaging default to sale order batch.</p>
<p><strong>Table of contents</strong></p> <p><strong>Table of contents</strong></p>
@ -391,7 +391,9 @@ and adds a packaging default to sale order batch.</p>
<col class="field-name" /> <col class="field-name" />
<col class="field-body" /> <col class="field-body" />
<tbody valign="top"> <tbody valign="top">
<tr class="field"><th class="field-name">1.0.0:</th><td class="field-body">Initial module.</td> <tr class="field"><th class="field-name">0.0.1:</th><td class="field-body">Initial module.</td>
</tr>
<tr class="field"><th class="field-name">1.0.0:</th><td class="field-body">rename to nfu_sale_order_batch_packaging</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -401,7 +403,7 @@ and adds a packaging default to sale order batch.</p>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_order_packaging%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <a class="reference external" href="https://github.com/bruecksen/ife_nfu/issues/new?body=module:%20nfu_sale_order_batch_packaging%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@ -421,7 +423,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2> <h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_packaging">bruecksen/ife_nfu</a> project on GitHub.</p> <p>This module is part of the <a class="reference external" href="https://github.com/bruecksen/ife_nfu/tree/16.0/nfu_sale_order_batch_packaging">bruecksen/ife_nfu</a> project on GitHub.</p>
<p>You are welcome to contribute.</p> <p>You are welcome to contribute.</p>
</div> </div>
</div> </div>

View file

@ -1 +0,0 @@
:1.0.0: Initial module.

View file

@ -1,19 +0,0 @@
{
"name": "NFU Sale Min Max Quantitiy",
"summary": "Add minimum and maximum order quantities to sale orders",
"author": "BAKEUP",
"website": "https://www.bakeup.org",
"category": "Stock",
"version": "16.0.0.0.1",
"depends": ["sale_management", "website_sale"],
"data": [
"views/sale_order_views.xml",
"views/sale_order_line_views.xml",
"wizard/sale_max_qty_line_views.xml",
"wizard/sale_max_qty_chooser_views.xml",
"views/templates.xml",
"security/ir.model.access.csv",
],
"assets": {"web.assets_frontend": ["nfu_sale_product_min_max_qty/static/src/js/website_sale.js"]},
"license": "LGPL-3",
}

View file

@ -1 +0,0 @@
from . import main

View file

@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
from odoo.http import request
from odoo import fields, http
from odoo.addons.website_sale.controllers.main import WebsiteSale
class WebsiteSaleMinMax(WebsiteSale):
@http.route()
def cart_update(self, *args, min_qty=None, max_qty=None, **kw):
""" Override to get min_qty and max_qty from the product.
"""
product_uom_min_qty = fields.Float(min_qty)
product_uom_max_qty = fields.Float(max_qty)
return super().cart_update(*args, min_qty=product_uom_min_qty, max_qty=product_uom_max_qty, **kw)

View file

@ -1,2 +0,0 @@
from . import sale_order_line
from . import sale_order

View file

@ -1,80 +0,0 @@
from odoo import _, models
class SaleOrder(models.Model):
_inherit = "sale.order"
def action_min_max_qty_wizard(self):
"""
Here you need to create the wizzard objects first and then call the wizzard with the newly created id
"""
sale_max_qty_chooser = self.env["sale.max.qty.chooser"].create({})
draft_sale_orders = self.filtered(lambda x: x.state == "draft")
for sale_order in draft_sale_orders:
sale_max_qty_chooser.sale_order_ids += sale_order
for line in sale_order.order_line.filtered(lambda x: not x.display_type):
self.env["sale.max.qty.line"].create(
{
"sale_line_id": line.id,
"sale_max_qty_chooser": sale_max_qty_chooser.id,
"qty": line.product_uom_qty,
}
)
action = {
"name": _("Min max qty wizard"),
"type": "ir.actions.act_window",
"res_model": "sale.max.qty.line",
"view_mode": "tree",
"target": "current",
"editable": True,
"context": {"search_default_group_by_product": 1},
"domain": [("id", "in", sale_max_qty_chooser.sale_max_qty_ids.ids)],
}
return action
def action_sale_order_lines(self):
"""
Here you need to create the wizzard objects first and then call the wizzard with the newly created id
"""
return {
"name": _("Min max qty wizard"),
"type": "ir.actions.act_window",
"res_model": "sale.order.line",
"view_mode": "tree,form",
"target": "current",
"context": {"group_by": "product_id"},
"domain": [("id", "in", self.order_line.ids)],
}
def _prepare_order_line_values(
self,
product_id,
quantity,
linked_line_id=False,
no_variant_attribute_values=None,
product_custom_attribute_values=None,
**kwargs
):
values = super()._prepare_order_line_values(
product_id,
quantity,
linked_line_id=linked_line_id,
no_variant_attribute_values=no_variant_attribute_values,
product_custom_attribute_values=product_custom_attribute_values,
**kwargs
)
values.update({"product_uom_min_qty": quantity, "product_uom_max_qty": kwargs.get("max_qty", quantity)})
return values
def _prepare_order_line_update_values(self, order_line, quantity, linked_line_id=False, **kwargs):
values = super()._prepare_order_line_update_values(
order_line, quantity, linked_line_id=linked_line_id, **kwargs
)
max_qty = kwargs.get("max_qty", quantity)
if quantity != order_line.product_uom_min_qty:
values["product_uom_min_qty"] = quantity
if max_qty and max_qty != order_line.product_uom_max_qty:
values["product_uom_max_qty"] = max_qty
return values

View file

@ -1,15 +0,0 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
product_uom_min_qty = fields.Float(string="Min qty.", digits="Product Unit of Measure")
product_uom_max_qty = fields.Float(string="Max qty.", digits="Product Unit of Measure")
@api.constrains("product_uom_qty", "product_uom_max_qty")
def _check_product_uom_qty(self):
for record in self:
if record.product_uom_max_qty != 0 and record.product_uom_qty > record.product_uom_max_qty:
raise UserError(_("The quantity must be less than or equal to the maximum quantity."))

View file

@ -1 +0,0 @@
This module adds a minium and a maximum order quantity field to Sale Orders and adds it to checkout of the website shop.

View file

@ -1 +0,0 @@
:1.0.0: Initial module.

View file

@ -1,3 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_max_qty_chooser,sale.max.qty.chooser,model_sale_max_qty_chooser,sales_team.group_sale_salesman,1,1,1,1
access_sale_max_qty_line,sale.max.qty.line,model_sale_max_qty_line,sales_team.group_sale_salesman,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sale_max_qty_chooser sale.max.qty.chooser model_sale_max_qty_chooser sales_team.group_sale_salesman 1 1 1 1
3 access_sale_max_qty_line sale.max.qty.line model_sale_max_qty_line sales_team.group_sale_salesman 1 1 1 1

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_order_line_tree" model="ir.ui.view">
<field name="name">sale.order.line.tree</field>
<field name="model">sale.order.line</field>
<field name="arch" type="xml">
<tree create="false" expand="1">
<field name="order_id"/>
<field name="order_partner_id"/>
<field name="name"/>
<field name="salesman_id"/>
<field name="product_uom_qty" string="Qty"/>
<field name="product_uom_min_qty" optional="hide"/>
<field name="product_uom_max_qty"/>
<field name="qty_delivered"/>
<field name="qty_invoiced"/>
<field name="qty_to_invoice"/>
<field name="product_uom" string="Unit of Measure" groups="uom.group_uom"/>
<field name="price_subtotal" sum="Total" widget="monetary"/>
<field name="currency_id" invisible="1"/>
</tree>
</field>
</record>
</odoo>

View file

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_order_form_inherit_product_min_max_qty" model="ir.ui.view">
<field name="name">sale.order.form.product.min_max_qty</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="after">
<field name="product_uom_min_qty" optional="hide"/>
<field name="product_uom_max_qty"/>
</xpath>
</field>
</record>
<record id="view_order_list_inherit_product_min_max_qty" model="ir.ui.view">
<field name="name">sale.order.list.view.inherited</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_quotation_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<button type="object" name="action_min_max_qty_wizard" string="Min/Max Wizard"/>
<button type="object" name="action_sale_order_lines" string="Sale order lines"/>
</header>
</xpath>
</field>
</record>
</odoo>

View file

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="cart_lines_min_max_qty" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="text-center td-qty">
<t t-if="show_qty">
<span>Max qty.</span>
</t>
</th>
</xpath>
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class="text-center td-qty">
<div class="css_quantity input-group mx-auto justify-content-center">
<t t-if="not line._is_not_sellable_line()">
<t t-if="show_qty">
<a t-attf-href="#" class="btn btn-link js_add_cart_json d-none d-md-inline-block" aria-label="Remove one" title="Remove one">
<i class="fa fa-minus"></i>
</a>
<input type="text" name="max-qty" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="line.product_uom_max_qty and int(line.product_uom_max_qty) or int(line.product_uom_qty)" t-att-data-min="int(line.product_uom_qty)" />
<t t-if="line._get_shop_warning(clear=False)">
<a t-attf-href="#" class="btn btn-link">
<i class='fa fa-warning text-warning' t-att-title="line._get_shop_warning()" role="img" aria-label="Warning"/>
</a>
</t>
<a t-else='' t-attf-href="#" class="btn btn-link float_left js_add_cart_json d-none d-md-inline-block" aria-label="Add one" title="Add one">
<i class="fa fa-plus"></i>
</a>
</t>
<t t-else="">
<input type="hidden" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="int(line.product_uom_qty) == line.product_uom_qty and int(line.product_uom_qty) or line.product_uom_qty" />
</t>
</t>
<t t-else="">
<span class="text-muted w-100" t-esc="int(line.product_uom_qty)"/>
<input type="hidden" class="js_quantity form-control quantity" t-att-data-line-id="line.id" t-att-data-product-id="line.product_id.id" t-att-value="line.product_uom_qty" />
</t>
</div>
</td>
</xpath>
</template>
<template id="cart_summary_min_max_qty" inherit_id="website_sale.cart_summary" name="Cart right column">
<xpath expr="//th[hasclass('td-qty')]" position="after">
<th class="border-top-0 td-qty">Max qty.</th>
</xpath>
<xpath expr="//td[hasclass('td-qty')]" position="after">
<td class='td-qty'>
<div t-esc="line.product_uom_max_qty" />
</td>
</xpath>
</template>
</odoo>

View file

@ -1,2 +0,0 @@
from . import sale_max_qty_chooser
from . import sale_max_qty_line

View file

@ -1,54 +0,0 @@
from odoo import fields, models
class SaleMaxQtyChooser(models.TransientModel):
"""Wizard to Allow user to adjust the sale order amout to fit to a packaging size"""
_name = "sale.max.qty.chooser"
_description = "Sale Max Quantity Chhooser"
# fill from init or compute from given sale order lines
sale_order_ids = fields.Many2many("sale.order")
sale_max_qty_ids = fields.One2many("sale.max.qty.line", "sale_max_qty_chooser")
def update_and_confirm_sale_order(self):
"""
Confirm sale orders where the quantity is fine. Create new Sale Orders for SO Lines with reset to draft
Through user error when total order amount of a product is not equal to packaging size (first package in the
list or smalles package sale_order_line.product_id.product.packaging_ids.qty)
we can use write({'key':'value'}) to update all sale order lines and action_confirm() to validate all sale
orders
Also see this methode on how to create new records. It creates a invoice with invoice lines. we need to do the
same for sale orders
def action_sold(self):
res = super().action_sold()
self.env["account.move"].create(
{
"property_id": self.id,
"partner_id": self.buyer_id.id,
"move_type": "out_invoice",
"line_ids": [
fields.Command.create(
{
"name": f"Property {self.name} - 10% Tax",
"quantity": 1,
"price_unit": self.selling_price * 1.1,
}
),
fields.Command.create({"name": "Administration Fees", "quantity": 1, "price_unit": 1000}),
],
}
)
return res
"""
for sale_order in self.sale_order_ids:
can_confirm = True
for line in self.sale_max_qty_ids.filtered(lambda line: line.sale_line_id.order_id == sale_order):
line.sale_line_id.write({"product_uom_qty": line.qty})
if not line.quantity_fits_packaging:
can_confirm = False
if can_confirm:
sale_order.action_confirm()

View file

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_sale_max_qty_chooser_form" model="ir.ui.view">
<field name="name">Sale Max Quantity Chhooser</field>
<field name="model">sale.max.qty.chooser</field>
<field name="arch" type="xml">
<form>
<div class="oe_grey">
<p>Sale Orders</p>
<field name="sale_order_ids" widget="many2many_tags"/>
</div>
<field name="sale_max_qty_ids" context="{'search_default_group_by_qty': 1}">
<!-- <tree create="0" editable="1" default_order="product_id">
<field name="product_id" context="{'group_by': 'product_id'}" />
<field name="qty"/>
<field name="max_qty"/>
<field name="packaging_size"/>
<field name="quantity_fits_packaging" widget="boolean"/>
<field name="reset_to_draft"/>
</tree> -->
</field>
<footer>
<button
name="update_and_confirm_sale_order"
string="Confirm Sale Orders"
type="object"
class="btn-primary"
data-hotkey="q"
/>
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</form>
</field>
</record>
<record id="action_sale_max_qty" model="ir.actions.act_window">
<field name="name">Set Quantities</field>
<field name="res_model">sale.max.qty.chooser</field>
<field name="view_mode">form</field>
<field name="target">current</field>
<field name="context">
{
'search_default_group_by_product': 1,
}
</field>
</record>
</odoo>

View file

@ -1,46 +0,0 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError
class SaleMaxQtyLine(models.TransientModel):
"""
Lines to shown in Wizard
"""
_name = "sale.max.qty.line"
_description = "Max qty Sale Order Lines"
name = fields.Char()
sale_max_qty_chooser = fields.Many2one("sale.max.qty.chooser")
qty = fields.Float()
max_qty = fields.Float(related="sale_line_id.product_uom_max_qty")
packaging_size = fields.Float(compute="_compute_packaging_size")
quantity_fits_packaging = fields.Boolean(compute="_compute_quantity_fits_packaging")
total_quantity = fields.Float(compute="_compute_quantity_fits_packaging")
sale_line_id = fields.Many2one("sale.order.line")
product_id = fields.Many2one(related="sale_line_id.product_id", store=True)
reset_to_draft = fields.Boolean()
def _compute_packaging_size(self):
for max_qty_line in self:
max_qty_line.packaging_size = min(
max_qty_line.sale_line_id.product_id.packaging_ids.mapped("qty"), default=1.0
)
@api.onchange("qty")
def _compute_quantity_fits_packaging(self):
for max_qty_line in self:
order_lines = max_qty_line.sale_max_qty_chooser.sale_max_qty_ids.filtered(
lambda line: line.sale_line_id.product_id == max_qty_line.product_id
)
max_qty_line.total_quantity = sum(order_lines.mapped("qty"))
max_qty_line.quantity_fits_packaging = max_qty_line.total_quantity % max_qty_line.packaging_size == 0
# for order_line in order_lines:
# order_line.quantity_fits_packaging = max_qty_line.quantity_fits_packaging
@api.constrains("qty")
def _check_product_uom_qty(self):
for max_qty_line in self:
if max_qty_line.max_qty != 0 and max_qty_line.qty > max_qty_line.max_qty:
raise UserError(_("The quantity must be less than or equal to the maximum quantity."))

View file

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_sale_max_qty_line_search" model="ir.ui.view">
<field name="name">sale.max.qty.line.search</field>
<field name="model">sale.max.qty.line</field>
<field name="arch" type="xml">
<search>
<filter string="Product" name="group_by_product" context="{'group_by':'product_id'}"/>
</search>
</field>
</record>
<record id="viw_sale_max_qty_line_tree" model="ir.ui.view">
<field name="name">sale.max.qty.line.tree</field>
<field name="model">sale.max.qty.line</field>
<field name="arch" type="xml">
<tree editable="bottom" create="0" expand="1">
<field name="product_id"/>
<field name="qty"/>
<field name="max_qty"/>
<field name="packaging_size"/>
<field name="quantity_fits_packaging" widget="boolean"/>
<field name="reset_to_draft"/>
</tree>
</field>
</record>
</odoo>