mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-24 20:12:05 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,7 @@
|
|||
# Copyright 2014 Numérigraphe
|
||||
# Copyright 2016 Sodexis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import product_product
|
||||
from . import product_template
|
||||
from . import res_config_settings
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright 2014 Numérigraphe
|
||||
# Copyright 2016 Sodexis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
from odoo.addons.stock.models.product import OPERATORS
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
|
||||
"""Add a field for the stock available to promise.
|
||||
Useful implementations need to be installed through the Settings menu or by
|
||||
installing one of the modules stock_available_*
|
||||
"""
|
||||
|
||||
_inherit = "product.product"
|
||||
|
||||
def _compute_available_quantities_dict(self):
|
||||
stock_dict = self._compute_quantities_dict(
|
||||
self._context.get("lot_id"),
|
||||
self._context.get("owner_id"),
|
||||
self._context.get("package_id"),
|
||||
self._context.get("from_date"),
|
||||
self._context.get("to_date"),
|
||||
)
|
||||
res = {}
|
||||
for product in self:
|
||||
res[product.id] = {
|
||||
"immediately_usable_qty": stock_dict[product.id]["virtual_available"],
|
||||
"potential_qty": 0.0,
|
||||
}
|
||||
return res, stock_dict
|
||||
|
||||
@api.depends("virtual_available")
|
||||
@api.depends_context(
|
||||
"lot_id",
|
||||
"owner_id",
|
||||
"package_id",
|
||||
"from_date",
|
||||
"to_date",
|
||||
"location",
|
||||
"warehouse",
|
||||
)
|
||||
def _compute_available_quantities(self):
|
||||
res, _ = self._compute_available_quantities_dict()
|
||||
for product in self:
|
||||
for key, value in res[product.id].items():
|
||||
if hasattr(product, key):
|
||||
product[key] = value
|
||||
|
||||
immediately_usable_qty = fields.Float(
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_available_quantities",
|
||||
search="_search_immediately_usable_qty",
|
||||
string="Available to promise",
|
||||
help="Stock for this Product that can be safely proposed "
|
||||
"for sale to Customers.\n"
|
||||
"The definition of this value can be configured to suit "
|
||||
"your needs.",
|
||||
)
|
||||
potential_qty = fields.Float(
|
||||
compute="_compute_available_quantities",
|
||||
digits="Product Unit of Measure",
|
||||
string="Potential",
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand.",
|
||||
)
|
||||
|
||||
def _get_search_immediately_usable_qty_domain(self):
|
||||
return [("type", "=", "product")]
|
||||
|
||||
@api.model
|
||||
def _search_immediately_usable_qty(self, operator, value):
|
||||
"""Search function for the immediately_usable_qty field.
|
||||
The search is quite similar to the Odoo search about quantity available
|
||||
(addons/stock/models/product.py,253; _search_product_quantity function)
|
||||
:param operator: str
|
||||
:param value: str
|
||||
:return: list of tuple (domain)
|
||||
"""
|
||||
product_domain = self._get_search_immediately_usable_qty_domain()
|
||||
products = self.with_context(prefetch_fields=False).search(
|
||||
product_domain, order="id"
|
||||
)
|
||||
product_ids = []
|
||||
for product in products:
|
||||
if OPERATORS[operator](product.immediately_usable_qty, value):
|
||||
product_ids.append(product.id)
|
||||
return [("id", "in", product_ids)]
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
# Copyright 2014 Numérigraphe
|
||||
# Copyright 2016 Sodexis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
from odoo.addons.stock.models.product import OPERATORS
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = "product.template"
|
||||
|
||||
@api.depends(
|
||||
"product_variant_ids.immediately_usable_qty",
|
||||
"product_variant_ids.potential_qty",
|
||||
)
|
||||
def _compute_available_quantities(self):
|
||||
res = self._compute_available_quantities_dict()
|
||||
for product in self:
|
||||
for key, value in res[product.id].items():
|
||||
if key in product._fields:
|
||||
product[key] = value
|
||||
|
||||
def _compute_available_quantities_dict(self):
|
||||
variants_dict, _ = self.mapped(
|
||||
"product_variant_ids"
|
||||
)._compute_available_quantities_dict()
|
||||
res = {}
|
||||
for template in self:
|
||||
immediately_usable_qty = sum(
|
||||
variants_dict[p.id]["immediately_usable_qty"]
|
||||
- variants_dict[p.id]["potential_qty"]
|
||||
for p in template.product_variant_ids
|
||||
)
|
||||
potential_qty = max(
|
||||
[
|
||||
variants_dict[p.id]["potential_qty"]
|
||||
for p in template.product_variant_ids
|
||||
]
|
||||
or [0.0]
|
||||
)
|
||||
res[template.id] = {
|
||||
"immediately_usable_qty": immediately_usable_qty + potential_qty,
|
||||
"potential_qty": potential_qty,
|
||||
}
|
||||
return res
|
||||
|
||||
immediately_usable_qty = fields.Float(
|
||||
digits="Product Unit of Measure",
|
||||
compute="_compute_available_quantities",
|
||||
search="_search_immediately_usable_qty",
|
||||
string="Available to promise",
|
||||
help="Stock for this Product that can be safely proposed "
|
||||
"for sale to Customers.\n"
|
||||
"The definition of this value can be configured to suit "
|
||||
"your needs",
|
||||
)
|
||||
potential_qty = fields.Float(
|
||||
compute="_compute_available_quantities",
|
||||
digits="Product Unit of Measure",
|
||||
string="Potential",
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand. "
|
||||
"If the product has several variants, this will be the biggest "
|
||||
"quantity that can be made for a any single variant.",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _search_immediately_usable_qty(self, operator, value):
|
||||
"""Search function for the immediately_usable_qty field.
|
||||
The search is quite similar to the Odoo search about quantity available
|
||||
(addons/stock/models/product.py,341; _search_product_quantity function)
|
||||
:param operator: str
|
||||
:param value: str
|
||||
:return: list of tuple (domain)
|
||||
"""
|
||||
products = self.search([])
|
||||
# Force prefetch
|
||||
products.mapped("immediately_usable_qty")
|
||||
product_ids = []
|
||||
for product in products:
|
||||
if OPERATORS[operator](product.immediately_usable_qty, value):
|
||||
product_ids.append(product.id)
|
||||
return [("id", "in", product_ids)]
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# Copyright 2014 Numérigraphe
|
||||
# Copyright 2016 Sodexis
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
"""Add options to easily install the submodules"""
|
||||
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
@api.model
|
||||
def _get_stock_available_mrp_based_on(self):
|
||||
"""Gets the available languages for the selection."""
|
||||
pdct_fields = self.env["ir.model.fields"].search(
|
||||
[("model", "=", "product.product"), ("ttype", "=", "float")]
|
||||
)
|
||||
return [
|
||||
(field.name, field.field_description)
|
||||
for field in sorted(pdct_fields, key=lambda f: f.field_description)
|
||||
]
|
||||
|
||||
module_stock_available_immediately = fields.Boolean(
|
||||
string="Exclude incoming goods",
|
||||
help="This will subtract incoming quantities from the quantities "
|
||||
"available to promise.\n"
|
||||
"This installs the module stock_available_immediately.",
|
||||
)
|
||||
|
||||
module_stock_available_mrp = fields.Boolean(
|
||||
string="Include the production potential",
|
||||
help="This will add the quantities of goods that can be "
|
||||
"immediately manufactured, to the quantities available to "
|
||||
"promise.\n"
|
||||
"This installs the module stock_available_mrp.\n"
|
||||
"If the module mrp is not installed, this will install it "
|
||||
"too",
|
||||
)
|
||||
|
||||
stock_available_mrp_based_on = fields.Selection(
|
||||
_get_stock_available_mrp_based_on,
|
||||
string="based on",
|
||||
help="Choose the field of the product which will be used to compute "
|
||||
"potential.\nIf empty, Quantity On Hand is used.\n"
|
||||
"Only the quantity fields have meaning for computing stock",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def get_values(self):
|
||||
res = super(ResConfigSettings, self).get_values()
|
||||
res.update(
|
||||
stock_available_mrp_based_on=self.env["ir.config_parameter"]
|
||||
.sudo()
|
||||
.get_param("stock_available_mrp_based_on", "qty_available")
|
||||
)
|
||||
return res
|
||||
|
||||
def set_values(self):
|
||||
res = super(ResConfigSettings, self).set_values()
|
||||
self.env["ir.config_parameter"].sudo().set_param(
|
||||
"stock_available_mrp_based_on", self.stock_available_mrp_based_on
|
||||
)
|
||||
return res
|
||||
Loading…
Add table
Add a link
Reference in a new issue