Files
stock-logistics-warehouse/stock_cycle_count/models/stock_cycle_count.py

163 lines
5.5 KiB
Python

# Copyright 2017-18 ForgeFlow S.L.
# (http://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import logging
from odoo import _, api, fields, models
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
class StockCycleCount(models.Model):
_name = "stock.cycle.count"
_description = "Stock Cycle Counts"
_inherit = "mail.thread"
_order = "id desc"
name = fields.Char(readonly=True)
location_id = fields.Many2one(
comodel_name="stock.location",
string="Location",
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
)
responsible_id = fields.Many2one(
comodel_name="res.users",
string="Assigned to",
readonly=True,
states={"draft": [("readonly", False)], "open": [("readonly", False)]},
tracking=True,
)
date_deadline = fields.Date(
string="Required Date",
readonly=True,
states={"draft": [("readonly", False)]},
tracking=True,
compute="_compute_date_deadline",
inverse="_inverse_date_deadline",
store=True,
)
automatic_deadline_date = fields.Date(
string="Automatic Required Date",
readonly=True,
states={"draft": [("readonly", False)]},
tracking=True,
)
manual_deadline_date = fields.Date(
string="Manual Required Date",
readonly=True,
states={"draft": [("readonly", False)]},
tracking=True,
)
cycle_count_rule_id = fields.Many2one(
comodel_name="stock.cycle.count.rule",
string="Cycle count rule",
required=True,
readonly=True,
states={"draft": [("readonly", False)]},
tracking=True,
)
state = fields.Selection(
selection=[
("draft", "Planned"),
("open", "Execution"),
("cancelled", "Cancelled"),
("done", "Done"),
],
default="draft",
tracking=True,
)
stock_adjustment_ids = fields.One2many(
comodel_name="stock.inventory",
inverse_name="cycle_count_id",
string="Inventory Adjustment",
tracking=True,
)
inventory_adj_count = fields.Integer(compute="_compute_inventory_adj_count")
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self.env.company,
readonly=True,
)
def write(self, vals):
result = super().write(vals)
if "responsible_id" in vals and not self.env.context.get("no_propagate"):
stock_inventory_records = self.mapped("stock_adjustment_ids")
for record in stock_inventory_records:
if record.responsible_id.id != vals["responsible_id"]:
record.with_context(no_propagate=True).write(
{"responsible_id": vals["responsible_id"]}
)
return result
@api.depends("stock_adjustment_ids")
def _compute_inventory_adj_count(self):
for rec in self:
rec.inventory_adj_count = len(rec.stock_adjustment_ids)
def do_cancel(self):
self.write({"state": "cancelled"})
def _prepare_inventory_adjustment(self):
self.ensure_one()
return {
"name": "INV/{}".format(self.name),
"cycle_count_id": self.id,
"location_ids": [(4, self.location_id.id)],
"exclude_sublocation": True,
"responsible_id": self.responsible_id.id,
}
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
vals["name"] = (
self.env["ir.sequence"].next_by_code("stock.cycle.count") or ""
)
return super().create(vals_list)
def action_create_inventory_adjustment(self):
if any([state != "draft" for state in self.mapped("state")]):
raise UserError(_("You can only confirm cycle counts in state 'Planned'."))
for rec in self:
data = rec._prepare_inventory_adjustment()
inv = self.env["stock.inventory"].create(data)
if rec.company_id.auto_start_inventory_from_cycle_count:
try:
inv.action_state_to_in_progress()
except Exception as e:
_logger.info("Error when beginning an adjustment: %s", str(e))
self.write({"state": "open"})
return True
def action_view_inventory(self):
action = self.env["ir.actions.act_window"]._for_xml_id(
"stock_inventory.action_view_inventory_group_form"
)
action["context"] = {}
adjustment_ids = self.mapped("stock_adjustment_ids").ids
if len(adjustment_ids) > 1:
action["domain"] = [("id", "in", adjustment_ids)]
elif len(adjustment_ids) == 1:
res = self.env.ref("stock_inventory.view_inventory_group_form", False)
action["views"] = [(res and res.id or False, "form")]
action["res_id"] = adjustment_ids and adjustment_ids[0] or False
return action
@api.depends("automatic_deadline_date", "manual_deadline_date")
def _compute_date_deadline(self):
for rec in self:
if rec.manual_deadline_date:
rec.date_deadline = rec.manual_deadline_date
else:
rec.date_deadline = rec.automatic_deadline_date
def _inverse_date_deadline(self):
for rec in self:
rec.manual_deadline_date = rec.date_deadline