Files
manufacture/repair_stock_move/models/repair_order.py
2023-02-23 10:06:06 +01:00

178 lines
6.6 KiB
Python

# Copyright (C) 2021 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools import float_compare
class RepairOrder(models.Model):
_inherit = "repair.order"
stock_move_ids = fields.One2many(
comodel_name="stock.move",
inverse_name="repair_id",
)
show_check_availability = fields.Boolean(
compute="_compute_show_check_availability",
help="Technical field used to compute whether the button "
"'Check Availability' should be displayed.",
)
ignore_availability = fields.Boolean()
# Make "Parts" editable in more states.
operations = fields.One2many(
states={
"draft": [("readonly", False)],
"confirmed": [("readonly", False)],
"under_repair": [("readonly", False)],
"ready": [("readonly", False)],
},
)
fees_lines = fields.One2many(
states={
"draft": [("readonly", False)],
"confirmed": [("readonly", False)],
"under_repair": [("readonly", False)],
"ready": [("readonly", False)],
},
)
@api.depends("state")
def _compute_show_check_availability(self):
for rec in self:
rec.show_check_availability = (
any(
move.state in ("waiting", "confirmed", "partially_available")
and float_compare(
move.product_uom_qty,
0,
precision_rounding=move.product_uom.rounding,
)
for move in rec.stock_move_ids
)
and not rec.ignore_availability
)
def _create_repair_stock_move(self):
self.ensure_one()
return self.env["stock.move"].create(
{
"name": self.name,
"product_id": self.product_id.id,
"product_uom": self.product_uom.id or self.product_id.uom_id.id,
"product_uom_qty": self.product_qty,
"partner_id": self.address_id.id,
"location_id": self.location_id.id,
"location_dest_id": self.location_id.id,
"repair_id": self.id,
"origin": self.name,
"company_id": self.company_id.id,
}
)
def action_repair_confirm(self):
res = super().action_repair_confirm()
for repair in self:
moves = self.env["stock.move"]
for operation in repair.operations:
move = operation.create_stock_move()
moves |= move
operation.write({"move_id": move.id})
move = repair._create_repair_stock_move()
repair.move_id = move
self.mapped("stock_move_ids")._action_confirm()
return res
def action_assign(self):
self.filtered(lambda r: r.state == "draft").action_repair_start()
moves = self.mapped("stock_move_ids")
moves = moves.filtered(
lambda move: move.state not in ("draft", "cancel", "done")
)
if not moves:
raise UserError(_("Nothing to check the availability for."))
moves._action_assign()
return True
def action_repair_start(self):
res = super().action_repair_start()
self.mapped("stock_move_ids")._action_assign()
return res
def action_force_availability(self):
self.write({"ignore_availability": True})
def _force_qty_done_in_repair_lines(self):
for operation in self.mapped("operations"):
for move in operation.stock_move_ids:
if move.state not in ["confirmed", "waiting", "partially_available"]:
continue
product_qty = move.product_uom._compute_quantity(
operation.product_uom_qty,
move.product_id.uom_id,
rounding_method="HALF-UP",
)
available_quantity = self.env["stock.quant"]._get_available_quantity(
move.product_id,
move.location_id,
lot_id=operation.lot_id,
strict=False,
)
move._update_reserved_quantity(
product_qty - move.reserved_availability,
available_quantity,
move.location_id,
lot_id=operation.lot_id,
strict=False,
)
move._set_quantity_done(operation.product_uom_qty)
if operation.lot_id:
move.move_line_ids.lot_id = operation.lot_id
def action_open_stock_moves(self):
self.ensure_one()
domain = [("id", "in", self.mapped("stock_move_ids").ids)]
action = {
"name": _("Stock Moves"),
"view_type": "tree",
"view_mode": "list,form",
"res_model": "stock.move",
"type": "ir.actions.act_window",
"context": self.env.context,
"domain": domain,
}
return action
def action_repair_cancel(self):
self.mapped("stock_move_ids")._action_cancel()
return super().action_repair_cancel()
def action_repair_end(self):
if any(r.show_check_availability for r in self):
raise UserError(_("Some related stock moves are not available."))
# I can not everything has been reserved.
self._force_qty_done_in_repair_lines()
for repair in self:
operation_moves = repair.mapped("operations.move_id")
if operation_moves:
consumed_lines = operation_moves.mapped("move_line_ids")
produced_lines = repair.move_id.move_line_ids
operation_moves |= repair.move_id
produced_lines.write({"consume_line_ids": [(6, 0, consumed_lines.ids)]})
self.move_id._set_quantity_done(self.move_id.product_uom_qty)
self.move_id._action_done()
for move in self.mapped("operations.move_id"):
move._set_quantity_done(move.product_uom_qty)
move._action_done()
return super().action_repair_end()
def action_repair_done(self):
self.ensure_one()
if self.stock_move_ids:
# With this module this should always be the case, so this is
# effectively overriding the method.
self.operations.write({"state": "done"})
return {self.id: self.move_id.id}
return super().action_repair_done()