Browse Source

[ADD] purchase_discount_without_stock

16.0
RemiFr82 1 year ago
parent
commit
3aabeca09a
  1. 2
      purchase_discount_without_stock/__init__.py
  2. 26
      purchase_discount_without_stock/__manifest__.py
  3. 92
      purchase_discount_without_stock/i18n/fr.po
  4. 3
      purchase_discount_without_stock/models/__init__.py
  5. 38
      purchase_discount_without_stock/models/product_supplierinfo.py
  6. 118
      purchase_discount_without_stock/models/purchase_order.py
  7. 17
      purchase_discount_without_stock/models/res_partner.py
  8. 1
      purchase_discount_without_stock/report/__init__.py
  9. 34
      purchase_discount_without_stock/report/purchase_report.py
  10. 20
      purchase_discount_without_stock/views/product_supplierinfo_view.xml
  11. 42
      purchase_discount_without_stock/views/purchase_discount_view.xml
  12. 16
      purchase_discount_without_stock/views/report_purchaseorder.xml
  13. 26
      purchase_discount_without_stock/views/res_partner_view.xml

2
purchase_discount_without_stock/__init__.py

@ -0,0 +1,2 @@
from . import models
from . import report

26
purchase_discount_without_stock/__manifest__.py

@ -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,
}

92
purchase_discount_without_stock/i18n/fr.po

@ -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"

3
purchase_discount_without_stock/models/__init__.py

@ -0,0 +1,3 @@
from . import purchase_order
from . import product_supplierinfo
from . import res_partner

38
purchase_discount_without_stock/models/product_supplierinfo.py

@ -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)

118
purchase_discount_without_stock/models/purchase_order.py

@ -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}

17
purchase_discount_without_stock/models/res_partner.py

@ -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,
)

1
purchase_discount_without_stock/report/__init__.py

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

34
purchase_discount_without_stock/report/purchase_report.py

@ -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"

20
purchase_discount_without_stock/views/product_supplierinfo_view.xml

@ -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>

42
purchase_discount_without_stock/views/purchase_discount_view.xml

@ -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>

16
purchase_discount_without_stock/views/report_purchaseorder.xml

@ -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>

26
purchase_discount_without_stock/views/res_partner_view.xml

@ -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>
Loading…
Cancel
Save