build: configurar herramientas de verificación OCA
- Instalar pre-commit con 25 hooks configurados - Configurar black 26.1.0 para formateo de código Python - Configurar isort 7.0.0 para ordenación de imports - Configurar flake8 7.3.0 con flake8-bugbear - Configurar pylint 3.1.1 con pylint-odoo 9.1.2 - Añadir autoflake y pyupgrade para mejoras automáticas - Configurar prettier para formateo de XML/JSON/YAML - Crear .editorconfig para consistencia de editor - Crear Makefile con comandos útiles - Crear check_addon.sh para verificación rápida de addons - Actualizar configuración de VS Code con extensiones recomendadas - Añadir documentación completa de uso - Aplicar formateo automático a archivos existentes - Deshabilitar setuptools-odoo (no soporta Odoo 18.0 aún) - Deshabilitar fix-encoding-pragma (obsoleto, usar pyupgrade)
This commit is contained in:
parent
5b9c6e3211
commit
fe137dc265
224 changed files with 18376 additions and 0 deletions
5
purchase_triple_discount/models/__init__.py
Normal file
5
purchase_triple_discount/models/__init__.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
from . import purchase_triple_discount_mixin
|
||||
from . import product_supplierinfo
|
||||
from . import purchase_order_line
|
||||
from . import purchase_order
|
||||
from . import res_partner
|
||||
35
purchase_triple_discount/models/product_supplierinfo.py
Normal file
35
purchase_triple_discount/models/product_supplierinfo.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Copyright 2019 Tecnativa - David Vidal
|
||||
# Copyright 2019 Tecnativa - Pedro M. Baeza
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import api
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ProductSupplierInfo(models.Model):
|
||||
_name = "product.supplierinfo"
|
||||
_inherit = ["purchase.triple.discount.mixin", "product.supplierinfo"]
|
||||
|
||||
@api.onchange("partner_id")
|
||||
def _onchange_partner_id(self):
|
||||
self.update(
|
||||
{
|
||||
field: self.partner_id[f"default_supplierinfo_{field}"]
|
||||
for field in self._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
res.update(
|
||||
{
|
||||
field: self.partner_id[f"default_supplierinfo_{field}"]
|
||||
for field in self._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _get_po_to_supplierinfo_synced_fields(self):
|
||||
res = super()._get_po_to_supplierinfo_synced_fields()
|
||||
res += self._get_multiple_discount_field_names()
|
||||
return res
|
||||
18
purchase_triple_discount/models/purchase_order.py
Normal file
18
purchase_triple_discount/models/purchase_order.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright 2017-19 Tecnativa - David Vidal
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = "purchase.order"
|
||||
|
||||
def _prepare_supplier_info(self, partner, line, price, currency):
|
||||
res = super()._prepare_supplier_info(partner, line, price, currency)
|
||||
res.update(
|
||||
{
|
||||
fname: line[fname]
|
||||
for fname in line._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
return res
|
||||
77
purchase_triple_discount/models/purchase_order_line.py
Normal file
77
purchase_triple_discount/models/purchase_order_line.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# Copyright 2017-19 Tecnativa - David Vidal
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api
|
||||
from odoo import fields
|
||||
from odoo import models
|
||||
|
||||
|
||||
class PurchaseOrderLine(models.Model):
|
||||
_name = "purchase.order.line"
|
||||
_inherit = ["purchase.triple.discount.mixin", "purchase.order.line"]
|
||||
|
||||
@api.depends("product_qty", "product_uom", "company_id")
|
||||
def _compute_price_unit_and_date_planned_and_name(self):
|
||||
res = super()._compute_price_unit_and_date_planned_and_name()
|
||||
self._compute_discounts()
|
||||
return res
|
||||
|
||||
def _compute_discounts(self):
|
||||
for line in self:
|
||||
if not line.company_id or not line.product_id or line.invoice_lines:
|
||||
continue
|
||||
params = {"order_id": line.order_id}
|
||||
seller = line.product_id._select_seller(
|
||||
partner_id=line.partner_id,
|
||||
quantity=line.product_qty,
|
||||
date=line.order_id.date_order
|
||||
and line.order_id.date_order.date()
|
||||
or fields.Date.context_today(line),
|
||||
uom_id=line.product_uom,
|
||||
params=params,
|
||||
)
|
||||
if not seller:
|
||||
continue
|
||||
line.update(
|
||||
{
|
||||
fname: seller[fname] or 0.0
|
||||
for fname in self._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
|
||||
def _prepare_account_move_line(self, move=False):
|
||||
self.ensure_one()
|
||||
res = super()._prepare_account_move_line(move)
|
||||
res.update(
|
||||
{
|
||||
fname: self[fname]
|
||||
for fname in self._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _prepare_purchase_order_line(
|
||||
self, product_id, product_qty, product_uom, company_id, supplier, po
|
||||
):
|
||||
res = super()._prepare_purchase_order_line(
|
||||
product_id, product_qty, product_uom, company_id, supplier, po
|
||||
)
|
||||
today = fields.Date.today()
|
||||
partner = supplier.partner_id
|
||||
uom_po_qty = product_uom._compute_quantity(
|
||||
product_qty, product_id.uom_po_id, rounding_method="HALF-UP"
|
||||
)
|
||||
seller = product_id.with_company(company_id)._select_seller(
|
||||
partner_id=partner,
|
||||
quantity=uom_po_qty,
|
||||
date=po.date_order and max(po.date_order.date(), today) or today,
|
||||
uom_id=product_id.uom_po_id,
|
||||
)
|
||||
res.update(
|
||||
{
|
||||
fname: seller[fname] or 0.0
|
||||
for fname in self._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright 2017-19 Tecnativa - David Vidal
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
import functools
|
||||
|
||||
from odoo import api
|
||||
from odoo import fields
|
||||
from odoo import models
|
||||
|
||||
|
||||
class TripleDiscountMixin(models.AbstractModel):
|
||||
_name = "purchase.triple.discount.mixin"
|
||||
_description = "Purchase Triple Discount Mixin"
|
||||
|
||||
discount = fields.Float(
|
||||
compute="_compute_discount",
|
||||
store=True,
|
||||
)
|
||||
discount1 = fields.Float(
|
||||
string="Disc. 1 (%)",
|
||||
digits="Discount",
|
||||
readonly=False,
|
||||
)
|
||||
|
||||
discount2 = fields.Float(
|
||||
string="Disc. 2 (%)",
|
||||
digits="Discount",
|
||||
readonly=False,
|
||||
)
|
||||
discount3 = fields.Float(
|
||||
string="Disc. 3 (%)",
|
||||
digits="Discount",
|
||||
readonly=False,
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
(
|
||||
"discount1_limit",
|
||||
"CHECK (discount1 <= 100.0)",
|
||||
"Discount 1 must be lower than 100%.",
|
||||
),
|
||||
(
|
||||
"discount2_limit",
|
||||
"CHECK (discount2 <= 100.0)",
|
||||
"Discount 2 must be lower than 100%.",
|
||||
),
|
||||
(
|
||||
"discount3_limit",
|
||||
"CHECK (discount3 <= 100.0)",
|
||||
"Discount 3 must be lower than 100%.",
|
||||
),
|
||||
]
|
||||
|
||||
@api.depends(lambda self: self._get_multiple_discount_field_names())
|
||||
def _compute_discount(self):
|
||||
for record in self:
|
||||
record.discount = record._get_aggregated_discount_from_values(
|
||||
{
|
||||
fname: record[fname]
|
||||
for fname in record._get_multiple_discount_field_names()
|
||||
}
|
||||
)
|
||||
|
||||
def _get_aggregated_discount_from_values(self, values):
|
||||
discount_fnames = self._get_multiple_discount_field_names()
|
||||
discounts = []
|
||||
for discount_fname in discount_fnames:
|
||||
discounts.append(values.get(discount_fname) or 0.0)
|
||||
return self._get_aggregated_multiple_discounts(discounts)
|
||||
|
||||
@staticmethod
|
||||
def _get_multiple_discount_field_names():
|
||||
return ["discount1", "discount2", "discount3"]
|
||||
|
||||
@staticmethod
|
||||
def _get_aggregated_multiple_discounts(discounts):
|
||||
discount_values = []
|
||||
for discount in discounts:
|
||||
discount_values.append(1 - (discount or 0.0) / 100.0)
|
||||
aggregated_discount = (
|
||||
1 - functools.reduce((lambda x, y: x * y), discount_values)
|
||||
) * 100
|
||||
return aggregated_discount
|
||||
28
purchase_triple_discount/models/res_partner.py
Normal file
28
purchase_triple_discount/models/res_partner.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Copyright 2019 Tecnativa - David Vidal
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from odoo import fields
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
default_supplierinfo_discount1 = fields.Float(
|
||||
string="Default Supplier Discount 1 (%)",
|
||||
digits="Discount",
|
||||
help="This value will be used as the default one, for each new "
|
||||
"supplierinfo line depending on that supplier.",
|
||||
)
|
||||
|
||||
default_supplierinfo_discount2 = fields.Float(
|
||||
string="Default Supplier Discount 2 (%)",
|
||||
digits="Discount",
|
||||
help="This value will be used as the default one, for each new "
|
||||
"supplierinfo line depending on that supplier.",
|
||||
)
|
||||
default_supplierinfo_discount3 = fields.Float(
|
||||
string="Default Supplier Discount 3 (%)",
|
||||
digits="Discount",
|
||||
help="This value will be used as the default one, for each new "
|
||||
"supplierinfo line depending on that supplier.",
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue