mirror of
https://github.com/bringout/oca-warehouse.git
synced 2026-04-23 01:42:04 +02:00
223 lines
8.5 KiB
Python
223 lines
8.5 KiB
Python
# Copyright 2019 Sergio Teruel <sergio.teruel@tecnativa.com>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
|
|
from odoo import api, fields, models
|
|
from odoo.tools.float_utils import float_compare
|
|
|
|
|
|
class WizStockBarcodesReadTodo(models.TransientModel):
|
|
_name = "wiz.stock.barcodes.read.todo"
|
|
_description = "Wizard to read barcode todo"
|
|
|
|
# To prevent remove the record wizard until 2 days old
|
|
_transient_max_hours = 48
|
|
|
|
name = fields.Char()
|
|
wiz_barcode_id = fields.Many2one(comodel_name="wiz.stock.barcodes.read.picking")
|
|
picking_state = fields.Selection(related="wiz_barcode_id.picking_state")
|
|
partner_id = fields.Many2one(
|
|
comodel_name="res.partner",
|
|
readonly=True,
|
|
string="Partner",
|
|
)
|
|
state = fields.Selection(
|
|
[("pending", "Pending"), ("done", "Done"), ("done_forced", "Done forced")],
|
|
string="Scan State",
|
|
default="pending",
|
|
compute="_compute_state",
|
|
readonly=False,
|
|
)
|
|
|
|
product_qty_reserved = fields.Float(
|
|
"Reserved",
|
|
digits="Product Unit of Measure",
|
|
readonly=True,
|
|
)
|
|
product_uom_qty = fields.Float(
|
|
"Demand",
|
|
digits="Product Unit of Measure",
|
|
readonly=True,
|
|
)
|
|
qty_done = fields.Float(
|
|
"Done",
|
|
digits="Product Unit of Measure",
|
|
compute="_compute_qty_done",
|
|
)
|
|
qty_done_rest = fields.Float(compute="_compute_qty_done_rest", store=True)
|
|
location_id = fields.Many2one(comodel_name="stock.location")
|
|
location_name = fields.Char(related="location_id.name")
|
|
location_dest_id = fields.Many2one(comodel_name="stock.location")
|
|
location_dest_name = fields.Char(
|
|
string="Destinatino Name", related="location_dest_id.name"
|
|
)
|
|
product_id = fields.Many2one(comodel_name="product.product")
|
|
lot_id = fields.Many2one(comodel_name="stock.lot")
|
|
uom_id = fields.Many2one(comodel_name="uom.uom")
|
|
package_id = fields.Many2one(comodel_name="stock.quant.package")
|
|
result_package_id = fields.Many2one(comodel_name="stock.quant.package")
|
|
package_product_qty = fields.Float()
|
|
|
|
res_model_id = fields.Many2one(comodel_name="ir.model")
|
|
res_ids = fields.Char()
|
|
line_ids = fields.Many2many(comodel_name="stock.move.line")
|
|
stock_move_ids = fields.Many2many(comodel_name="stock.move")
|
|
position_index = fields.Integer()
|
|
picking_code = fields.Char("Type of Operation")
|
|
is_extra_line = fields.Boolean()
|
|
# Used in kanban view
|
|
is_stock_move_line_origin = fields.Boolean()
|
|
|
|
@api.depends("qty_done", "product_uom_qty")
|
|
def _compute_qty_done_rest(self):
|
|
for rec in self:
|
|
rec.qty_done_rest = rec.product_uom_qty - rec.qty_done
|
|
|
|
def action_todo_next(self):
|
|
self.state = "done_forced"
|
|
self.line_ids.barcode_scan_state = "done_forced"
|
|
for sml in self.line_ids:
|
|
if (
|
|
float_compare(
|
|
sml.reserved_uom_qty,
|
|
sml.qty_done,
|
|
precision_rounding=sml.product_uom_id.rounding,
|
|
)
|
|
== 0
|
|
):
|
|
continue
|
|
if sml.move_id.state == "confirmed" and sml.qty_done:
|
|
sml.move_id.state = "partially_available"
|
|
if sml.move_id.state in ["partially_available", "assigned"]:
|
|
sml.reserved_uom_qty = sml.qty_done
|
|
if self.is_extra_line or not self.is_stock_move_line_origin:
|
|
barcode_backorder_action = self.env.context.get(
|
|
"barcode_backorder_action", "create_backorder"
|
|
)
|
|
self.stock_move_ids.barcode_backorder_action = barcode_backorder_action
|
|
if barcode_backorder_action == "pending":
|
|
self.stock_move_ids.move_line_ids.unlink()
|
|
self.stock_move_ids._action_assign()
|
|
wiz_barcode = self.wiz_barcode_id
|
|
self.wiz_barcode_id.fill_todo_records()
|
|
self.wiz_barcode_id = wiz_barcode
|
|
self.wiz_barcode_id.determine_todo_action()
|
|
|
|
def action_reset_lines(self):
|
|
self.state = "pending"
|
|
self.line_ids.barcode_scan_state = "pending"
|
|
self.line_ids.qty_done = 0.0
|
|
self.wiz_barcode_id.action_clean_values()
|
|
self.wiz_barcode_id.fill_todo_records()
|
|
self.wiz_barcode_id.determine_todo_action()
|
|
|
|
def action_back_line(self):
|
|
if self.position_index > 0:
|
|
record = self.wiz_barcode_id.todo_line_ids[self.position_index - 1]
|
|
self.wiz_barcode_id.determine_todo_action(forced_todo_line=record)
|
|
|
|
def action_next_line(self):
|
|
if self.position_index < len(self.wiz_barcode_id.todo_line_ids) - 1:
|
|
record = self.wiz_barcode_id.todo_line_ids[self.position_index + 1]
|
|
self.wiz_barcode_id.determine_todo_action(forced_todo_line=record)
|
|
|
|
@api.depends("line_ids.qty_done")
|
|
def _compute_qty_done(self):
|
|
for rec in self:
|
|
rec.qty_done = sum(ln.qty_done for ln in rec.line_ids)
|
|
|
|
@api.depends(
|
|
"line_ids",
|
|
"line_ids.qty_done",
|
|
"line_ids.reserved_uom_qty",
|
|
"line_ids.barcode_scan_state",
|
|
"qty_done",
|
|
"product_uom_qty",
|
|
)
|
|
def _compute_state(self):
|
|
for rec in self:
|
|
if float_compare(
|
|
rec.qty_done,
|
|
rec.product_uom_qty,
|
|
precision_rounding=rec.uom_id.rounding,
|
|
) > -1 or (
|
|
rec.wiz_barcode_id.option_group_id.source_pending_moves
|
|
== "move_line_ids"
|
|
and rec.line_ids
|
|
and (
|
|
sum(rec.stock_move_ids.mapped("quantity_done"))
|
|
>= sum(rec.stock_move_ids.mapped("product_uom_qty"))
|
|
or not any(
|
|
ln.barcode_scan_state == "pending" for ln in rec.line_ids
|
|
)
|
|
)
|
|
):
|
|
rec.state = "done"
|
|
else:
|
|
rec.state = "pending"
|
|
|
|
@api.model
|
|
def fields_to_fill_from_pending_line(self):
|
|
res = [
|
|
"location_id",
|
|
"location_dest_id",
|
|
"product_id",
|
|
"lot_id",
|
|
"package_id",
|
|
]
|
|
if not self.wiz_barcode_id.keep_result_package:
|
|
res.append("result_package_id")
|
|
return res
|
|
|
|
def fill_from_pending_line(self):
|
|
self.wiz_barcode_id.selected_pending_move_id = self
|
|
self.wiz_barcode_id.determine_todo_action(forced_todo_line=self)
|
|
for field in self.fields_to_fill_from_pending_line():
|
|
self.wiz_barcode_id[field] = self[field]
|
|
# Force fill product_qty if filled_default is set
|
|
if self.wiz_barcode_id.option_group_id.get_option_value(
|
|
"product_qty", "filled_default"
|
|
):
|
|
self.wiz_barcode_id.product_qty = self.product_uom_qty - sum(
|
|
self.line_ids.mapped("qty_done")
|
|
)
|
|
self.wiz_barcode_id.product_uom_id = self.uom_id
|
|
self.wiz_barcode_id.action_show_step()
|
|
self.wiz_barcode_id._set_focus_on_qty_input()
|
|
|
|
def operation_quantities(self):
|
|
self.wiz_barcode_id.manual_entry = True
|
|
self.wiz_barcode_id.product_qty = self.product_qty_reserved
|
|
self.wiz_barcode_id.product_id = self.product_id.id
|
|
if self.wiz_barcode_id.picking_id.picking_type_id.code != "incoming":
|
|
self.wiz_barcode_id.qty_available = self.product_qty_reserved
|
|
self.wiz_barcode_id.product_id = self.product_id.id
|
|
self.wiz_barcode_id.location_id = self.location_id.id
|
|
self.wiz_barcode_id.with_context(manual_picking=True).action_confirm()
|
|
|
|
def _get_fields_to_edit(self):
|
|
return [
|
|
"location_dest_id",
|
|
"location_id",
|
|
"product_id",
|
|
"lot_id",
|
|
"package_id",
|
|
]
|
|
|
|
def action_barcode_inventory_quant_edit(self):
|
|
wiz_barcode_id = self.env.context.get("wiz_barcode_id", False)
|
|
wiz_barcode = self.env["wiz.stock.barcodes.read.picking"].browse(wiz_barcode_id)
|
|
for quant in self:
|
|
# Try to assign fields with the same name between quant and the scan wizard
|
|
for fname in self._get_fields_to_edit():
|
|
if hasattr(wiz_barcode, fname):
|
|
wiz_barcode[fname] = quant[fname]
|
|
wiz_barcode.product_qty = quant.qty_done
|
|
|
|
wiz_barcode.manual_entry = True
|
|
self.env["bus.bus"]._sendone(
|
|
"stock_barcodes_scan",
|
|
"stock_barcodes_edit_manual",
|
|
{
|
|
"manual_entry": True,
|
|
},
|
|
)
|