RemiFr82
1 year ago
13 changed files with 435 additions and 0 deletions
-
2purchase_discount_without_stock/__init__.py
-
26purchase_discount_without_stock/__manifest__.py
-
92purchase_discount_without_stock/i18n/fr.po
-
3purchase_discount_without_stock/models/__init__.py
-
38purchase_discount_without_stock/models/product_supplierinfo.py
-
118purchase_discount_without_stock/models/purchase_order.py
-
17purchase_discount_without_stock/models/res_partner.py
-
1purchase_discount_without_stock/report/__init__.py
-
34purchase_discount_without_stock/report/purchase_report.py
-
20purchase_discount_without_stock/views/product_supplierinfo_view.xml
-
42purchase_discount_without_stock/views/purchase_discount_view.xml
-
16purchase_discount_without_stock/views/report_purchaseorder.xml
-
26purchase_discount_without_stock/views/res_partner_view.xml
@ -0,0 +1,2 @@ |
|||||
|
from . import models |
||||
|
from . import report |
@ -0,0 +1,26 @@ |
|||||
|
# © 2004-2009 Tiny SPRL (<http://tiny.be>). |
||||
|
# © 2014-2017 Tecnativa - Pedro M. Baeza |
||||
|
# © 2016 ACSONE SA/NV (<http://acsone.eu>) |
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
{ |
||||
|
"name": "Purchase order lines with discounts", |
||||
|
"author": "Tiny, " |
||||
|
"Acysos S.L., " |
||||
|
"Tecnativa, " |
||||
|
"ACSONE SA/NV," |
||||
|
"GRAP," |
||||
|
"Odoo Community Association (OCA)," |
||||
|
"RemiFr82", |
||||
|
"version": "14.0.1.1.3", |
||||
|
"category": "Purchase Management", |
||||
|
"website": "https://remifr82.me", |
||||
|
"depends": ["purchase"], |
||||
|
"data": [ |
||||
|
"views/purchase_discount_view.xml", |
||||
|
"views/report_purchaseorder.xml", |
||||
|
"views/product_supplierinfo_view.xml", |
||||
|
"views/res_partner_view.xml", |
||||
|
], |
||||
|
"license": "AGPL-3", |
||||
|
"installable": True, |
||||
|
} |
@ -0,0 +1,92 @@ |
|||||
|
# Translation of Odoo Server. |
||||
|
# This file contains the translation of the following modules: |
||||
|
# * purchase_discount_whithout_stock |
||||
|
# |
||||
|
# Translators: |
||||
|
# OCA Transbot <transbot@odoo-community.org>, 2018 |
||||
|
# Quentin THEURET <odoo@kerpeo.com>, 2018 |
||||
|
msgid "" |
||||
|
msgstr "" |
||||
|
"Project-Id-Version: Odoo Server 11.0\n" |
||||
|
"Report-Msgid-Bugs-To: \n" |
||||
|
"POT-Creation-Date: 2018-02-23 17:50+0000\n" |
||||
|
"PO-Revision-Date: 2020-07-22 12:19+0000\n" |
||||
|
"Last-Translator: c2cdidier <didier.donze@camptocamp.com>\n" |
||||
|
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" |
||||
|
"Language: fr\n" |
||||
|
"MIME-Version: 1.0\n" |
||||
|
"Content-Type: text/plain; charset=UTF-8\n" |
||||
|
"Content-Transfer-Encoding: \n" |
||||
|
"Plural-Forms: nplurals=2; plural=n > 1;\n" |
||||
|
"X-Generator: Weblate 3.10\n" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model_terms:ir.ui.view,arch_db:purchase_discount_whithout_stock.report_purchaseorder_document |
||||
|
msgid "<strong>Disc. (%)</strong>" |
||||
|
msgstr "<strong>Remise (%)</strong>" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model,name:purchase_discount_whithout_stock.model_res_partner |
||||
|
msgid "Contact" |
||||
|
msgstr "Contact" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model.fields,field_description:purchase_discount_whithout_stock.field_res_partner__default_supplierinfo_discount |
||||
|
#: model:ir.model.fields,field_description:purchase_discount_whithout_stock.field_res_users__default_supplierinfo_discount |
||||
|
msgid "Default Supplier Discount (%)" |
||||
|
msgstr "Remise fournisseur par défaut (%)" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model.fields,field_description:purchase_discount_whithout_stock.field_product_supplierinfo__discount |
||||
|
#: model:ir.model.fields,field_description:purchase_discount_whithout_stock.field_purchase_order_line__discount |
||||
|
#: model:ir.model.fields,field_description:purchase_discount_whithout_stock.field_purchase_report__discount |
||||
|
msgid "Discount (%)" |
||||
|
msgstr "Remise (%)" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model.constraint,message:purchase_discount_whithout_stock.constraint_purchase_order_line_discount_limit |
||||
|
msgid "Discount must be lower than 100%." |
||||
|
msgstr "La remise doit être inférieure à 100%." |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model_terms:ir.ui.view,arch_db:purchase_discount_whithout_stock.res_partner_form_view |
||||
|
msgid "Discount-related settings are managed on" |
||||
|
msgstr "Paramètres des remises sont gérés sur" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model,name:purchase_discount_whithout_stock.model_purchase_order |
||||
|
msgid "Purchase Order" |
||||
|
msgstr "Commandes d'achat" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model,name:purchase_discount_whithout_stock.model_purchase_order_line |
||||
|
msgid "Purchase Order Line" |
||||
|
msgstr "Ligne de commande d'achat" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model,name:purchase_discount_whithout_stock.model_purchase_report |
||||
|
msgid "Purchase Report" |
||||
|
msgstr "Rapport des commandes" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model,name:purchase_discount_whithout_stock.model_product_supplierinfo |
||||
|
msgid "Supplier Pricelist" |
||||
|
msgstr "Liste de prix fournisseur" |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model:ir.model.fields,help:purchase_discount_whithout_stock.field_res_partner__default_supplierinfo_discount |
||||
|
#: model:ir.model.fields,help:purchase_discount_whithout_stock.field_res_users__default_supplierinfo_discount |
||||
|
msgid "" |
||||
|
"This value will be used as the default one, for each new supplierinfo line " |
||||
|
"depending on that supplier." |
||||
|
msgstr "" |
||||
|
"Cette valeur sera utilisée comme valeur par défaut pour chaque nouvelle " |
||||
|
"information fournisseur de ce fournisseur." |
||||
|
|
||||
|
#. module: purchase_discount_whithout_stock |
||||
|
#: model_terms:ir.ui.view,arch_db:purchase_discount_whithout_stock.res_partner_form_view |
||||
|
msgid "the parent company" |
||||
|
msgstr "Société parente" |
||||
|
|
||||
|
#~ msgid "Invoice" |
||||
|
#~ msgstr "Facture" |
@ -0,0 +1,3 @@ |
|||||
|
from . import purchase_order |
||||
|
from . import product_supplierinfo |
||||
|
from . import res_partner |
@ -0,0 +1,38 @@ |
|||||
|
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>) |
||||
|
# Copyright 2014-2019 Tecnativa - Pedro M. Baeza |
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ProductSupplierInfo(models.Model): |
||||
|
_inherit = "product.supplierinfo" |
||||
|
|
||||
|
discount = fields.Float(string="Discount (%)", digits="Discount") |
||||
|
|
||||
|
@api.onchange("name") |
||||
|
def onchange_name(self): |
||||
|
"""Apply the default supplier discount of the selected supplier""" |
||||
|
for supplierinfo in self.filtered("name"): |
||||
|
supplierinfo.discount = supplierinfo.name.default_supplierinfo_discount |
||||
|
|
||||
|
@api.model |
||||
|
def _get_po_to_supplierinfo_synced_fields(self): |
||||
|
"""Overwrite this method for adding other fields to be synchronized |
||||
|
with product.supplierinfo. |
||||
|
""" |
||||
|
return ["discount"] |
||||
|
|
||||
|
@api.model_create_multi |
||||
|
def create(self, vals_list): |
||||
|
"""Insert discount (or others) from context from purchase.order's |
||||
|
_add_supplier_to_product method""" |
||||
|
for vals in vals_list: |
||||
|
product_tmpl_id = vals.get("product_tmpl_id") |
||||
|
po_line_map = self.env.context.get("po_line_map", {}) |
||||
|
if product_tmpl_id in po_line_map: |
||||
|
po_line = po_line_map[product_tmpl_id] |
||||
|
for field in self._get_po_to_supplierinfo_synced_fields(): |
||||
|
if not vals.get(field): |
||||
|
vals[field] = po_line[field] |
||||
|
return super().create(vals_list) |
@ -0,0 +1,118 @@ |
|||||
|
# Copyright 2004-2009 Tiny SPRL (<http://tiny.be>). |
||||
|
# Copyright 2016 ACSONE SA/NV (<http://acsone.eu>) |
||||
|
# Copyright 2015-2019 Tecnativa - Pedro M. Baeza |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class PurchaseOrder(models.Model): |
||||
|
_inherit = "purchase.order" |
||||
|
|
||||
|
def _add_supplier_to_product(self): |
||||
|
"""Insert a mapping of products to PO lines to be picked up |
||||
|
in supplierinfo's create()""" |
||||
|
self.ensure_one() |
||||
|
po_line_map = { |
||||
|
line.product_id.product_tmpl_id.id: line for line in self.order_line |
||||
|
} |
||||
|
return super( |
||||
|
PurchaseOrder, self.with_context(po_line_map=po_line_map) |
||||
|
)._add_supplier_to_product() |
||||
|
|
||||
|
|
||||
|
class PurchaseOrderLine(models.Model): |
||||
|
_inherit = "purchase.order.line" |
||||
|
|
||||
|
# adding discount to depends |
||||
|
@api.depends("discount") |
||||
|
def _compute_amount(self): |
||||
|
return super()._compute_amount() |
||||
|
|
||||
|
def _prepare_compute_all_values(self): |
||||
|
vals = super()._prepare_compute_all_values() |
||||
|
vals.update({"price_unit": self._get_discounted_price_unit()}) |
||||
|
return vals |
||||
|
|
||||
|
discount = fields.Float(string="Discount (%)", digits="Discount") |
||||
|
|
||||
|
_sql_constraints = [ |
||||
|
( |
||||
|
"discount_limit", |
||||
|
"CHECK (discount <= 100.0)", |
||||
|
"Discount must be lower than 100%.", |
||||
|
) |
||||
|
] |
||||
|
|
||||
|
def _get_discounted_price_unit(self): |
||||
|
"""Inheritable method for getting the unit price after applying |
||||
|
discount(s). |
||||
|
|
||||
|
:rtype: float |
||||
|
:return: Unit price after discount(s). |
||||
|
""" |
||||
|
self.ensure_one() |
||||
|
if self.discount: |
||||
|
return self.price_unit * (1 - self.discount / 100) |
||||
|
return self.price_unit |
||||
|
|
||||
|
@api.onchange("product_qty", "product_uom") |
||||
|
def _onchange_quantity(self): |
||||
|
""" |
||||
|
Check if a discount is defined into the supplier info and if so then |
||||
|
apply it to the current purchase order line |
||||
|
""" |
||||
|
res = super()._onchange_quantity() |
||||
|
if self.product_id: |
||||
|
date = None |
||||
|
if self.order_id.date_order: |
||||
|
date = self.order_id.date_order.date() |
||||
|
seller = self.product_id._select_seller( |
||||
|
partner_id=self.partner_id, |
||||
|
quantity=self.product_qty, |
||||
|
date=date, |
||||
|
uom_id=self.product_uom, |
||||
|
) |
||||
|
self._apply_value_from_seller(seller) |
||||
|
return res |
||||
|
|
||||
|
@api.model |
||||
|
def _apply_value_from_seller(self, seller): |
||||
|
"""Overload this function to prepare other data from seller, |
||||
|
like in purchase_triple_discount module""" |
||||
|
if not seller: |
||||
|
return |
||||
|
self.discount = seller.discount |
||||
|
|
||||
|
def _prepare_account_move_line(self, move=False): |
||||
|
vals = super(PurchaseOrderLine, self)._prepare_account_move_line(move) |
||||
|
vals["discount"] = self.discount |
||||
|
return vals |
||||
|
|
||||
|
@api.model |
||||
|
def _prepare_purchase_order_line( |
||||
|
self, product_id, product_qty, product_uom, company_id, supplier, po |
||||
|
): |
||||
|
"""Apply the discount to the created purchase order""" |
||||
|
res = super()._prepare_purchase_order_line( |
||||
|
product_id, product_qty, product_uom, company_id, supplier, po |
||||
|
) |
||||
|
partner = supplier.name |
||||
|
uom_po_qty = product_uom._compute_quantity(product_qty, product_id.uom_po_id) |
||||
|
seller = product_id.with_company(company_id)._select_seller( |
||||
|
partner_id=partner, |
||||
|
quantity=uom_po_qty, |
||||
|
date=po.date_order and po.date_order.date(), |
||||
|
uom_id=product_id.uom_po_id, |
||||
|
) |
||||
|
res.update(self._prepare_purchase_order_line_from_seller(seller)) |
||||
|
return res |
||||
|
|
||||
|
@api.model |
||||
|
def _prepare_purchase_order_line_from_seller(self, seller): |
||||
|
"""Overload this function to prepare other data from seller, |
||||
|
like in purchase_triple_discount module""" |
||||
|
if not seller: |
||||
|
return {} |
||||
|
return {"discount": seller.discount} |
@ -0,0 +1,17 @@ |
|||||
|
# Copyright 2016 GRAP (http://www.grap.coop) |
||||
|
# Sylvain LE GAL (https://twitter.com/legalsylvain) |
||||
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html |
||||
|
|
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ResPartner(models.Model): |
||||
|
_inherit = "res.partner" |
||||
|
|
||||
|
default_supplierinfo_discount = fields.Float( |
||||
|
string="Default Supplier Discount (%)", |
||||
|
digits="Discount", |
||||
|
help="This value will be used as the default one, for each new" |
||||
|
" supplierinfo line depending on that supplier.", |
||||
|
tracking=True, |
||||
|
) |
@ -0,0 +1 @@ |
|||||
|
from . import purchase_report |
@ -0,0 +1,34 @@ |
|||||
|
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>) |
||||
|
# Copyright 2017-2019 Tecnativa - Pedro M. Baeza |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class PurchaseReport(models.Model): |
||||
|
_inherit = "purchase.report" |
||||
|
|
||||
|
discount = fields.Float( |
||||
|
string="Discount (%)", digits="Discount", group_operator="avg" |
||||
|
) |
||||
|
|
||||
|
def _select(self): |
||||
|
res = super()._select() |
||||
|
# There are 3 matches |
||||
|
res = res.replace("l.price_unit", self._get_discounted_price_unit_exp()) |
||||
|
res += ", l.discount AS discount" |
||||
|
return res |
||||
|
|
||||
|
def _group_by(self): |
||||
|
res = super()._group_by() |
||||
|
res += ", l.discount" |
||||
|
return res |
||||
|
|
||||
|
def _get_discounted_price_unit_exp(self): |
||||
|
"""Inheritable method for getting the SQL expression used for |
||||
|
calculating the unit price with discount(s). |
||||
|
|
||||
|
:rtype: str |
||||
|
:return: SQL expression for discounted unit price. |
||||
|
""" |
||||
|
return "(1.0 - COALESCE(l.discount, 0.0) / 100.0) * l.price_unit" |
@ -0,0 +1,20 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="product_supplierinfo_form_view"> |
||||
|
<field name="model">product.supplierinfo</field> |
||||
|
<field name="inherit_id" ref="product.product_supplierinfo_form_view" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//div[field[@name='price']]" position="after"> |
||||
|
<field name="discount" /> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record model="ir.ui.view" id="product_supplierinfo_tree_view"> |
||||
|
<field name="model">product.supplierinfo</field> |
||||
|
<field name="inherit_id" ref="product.product_supplierinfo_tree_view" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="price" position="after"> |
||||
|
<field name="discount" /> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,42 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="purchase_order_line_form2"> |
||||
|
<field name="name">purchase_discount.order.line.form2</field> |
||||
|
<field name="model">purchase.order.line</field> |
||||
|
<field name="inherit_id" ref="purchase.purchase_order_line_form2" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="price_unit" position="after"> |
||||
|
<field name="discount" /> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record model="ir.ui.view" id="purchase_order_line_tree"> |
||||
|
<field name="name">purchase_discount.order.line.tree</field> |
||||
|
<field name="model">purchase.order.line</field> |
||||
|
<field name="inherit_id" ref="purchase.purchase_order_line_tree" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="price_unit" position="after"> |
||||
|
<field name="discount" /> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record model="ir.ui.view" id="purchase_order_form"> |
||||
|
<field name="name">purchase_discount.purchase.order.form</field> |
||||
|
<field name="model">purchase.order</field> |
||||
|
<field name="inherit_id" ref="purchase.purchase_order_form" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath |
||||
|
expr="//field[@name='order_line']/tree/field[@name='price_unit']" |
||||
|
position="after" |
||||
|
> |
||||
|
<field name="discount" /> |
||||
|
</xpath> |
||||
|
<xpath |
||||
|
expr="//field[@name='order_line']/form//field[@name='price_unit']" |
||||
|
position="after" |
||||
|
> |
||||
|
<field name="discount" /> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,16 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template |
||||
|
id="report_purchaseorder_document" |
||||
|
inherit_id="purchase.report_purchaseorder_document" |
||||
|
> |
||||
|
<xpath expr="//table[1]/thead/tr//th[last()]" position="before"> |
||||
|
<th name="th_discount" class="text-right"><strong>Disc. (%)</strong></th> |
||||
|
</xpath> |
||||
|
<xpath expr="//td[span[@t-field='line.price_subtotal']]" position="before"> |
||||
|
<td name="td_discount" class="text-right"> |
||||
|
<span t-field="line.discount" /> |
||||
|
</td> |
||||
|
</xpath> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,26 @@ |
|||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="res_partner_form_view"> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="inherit_id" ref="base.view_partner_form" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//group[@name='purchase']" position="inside"> |
||||
|
<field |
||||
|
name="default_supplierinfo_discount" |
||||
|
attrs="{'invisible': [('is_company', '=', False), ('parent_id', '!=', False)]}" |
||||
|
/> |
||||
|
<div |
||||
|
name="supplierinfo_discount_disabled" |
||||
|
colspan="2" |
||||
|
attrs="{'invisible': ['|',('is_company', '=', True), ('parent_id', '=', False)]}" |
||||
|
> |
||||
|
<p>Discount-related settings are managed on <button |
||||
|
name="open_commercial_entity" |
||||
|
type="object" |
||||
|
string="the parent company" |
||||
|
class="oe_link" |
||||
|
/></p> |
||||
|
</div> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue