111 lines
4.9 KiB
Python
111 lines
4.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
|
|
class C2CRepackOrder(models.Model):
|
|
_name = 'c2c.repack.order'
|
|
_description = 'C2C Repacking Order'
|
|
_order = 'create_date desc'
|
|
|
|
name = fields.Char('Reference', default='New', readonly=True)
|
|
state = fields.Selection([('draft', 'Draft'), ('done', 'Done')], default='draft', readonly=True)
|
|
|
|
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company)
|
|
location_id = fields.Many2one('stock.location', string='Location', domain="[('usage', '=', 'internal')]", required=True)
|
|
|
|
# Source (Bulk)
|
|
source_product_id = fields.Many2one('product.product', string='Bulk Product', required=True)
|
|
source_qty = fields.Float('Bulk Qty to Repack', required=True, default=1.0)
|
|
source_uom_id = fields.Many2one('uom.uom', string='Bulk UoM', related='source_product_id.uom_id')
|
|
source_lot_id = fields.Many2one('stock.lot', string='Bulk Lot', domain="[('product_id', '=', source_product_id)]")
|
|
|
|
# Destination (Retail)
|
|
dest_product_id = fields.Many2one('product.product', string='Retail Pack Product', required=True)
|
|
dest_qty = fields.Float('Number of Retail Packs', required=True)
|
|
dest_uom_id = fields.Many2one('uom.uom', string='Retail UoM', related='dest_product_id.uom_id')
|
|
dest_lot_id = fields.Many2one('stock.lot', string='New Retail Lot', domain="[('product_id', '=', dest_product_id)]")
|
|
|
|
move_ids = fields.One2many('stock.move', 'repack_id', string='Stock Moves')
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if vals.get('name', 'New') == 'New':
|
|
vals['name'] = self.env['ir.sequence'].next_by_code('c2c.repack.order') or 'REPACK'
|
|
return super().create(vals_list)
|
|
|
|
def action_confirm_repack(self):
|
|
"""Consume bulk and create retail packs."""
|
|
self.ensure_one()
|
|
if self.state == 'done':
|
|
return
|
|
|
|
if self.source_qty <= 0 or self.dest_qty <= 0:
|
|
raise UserError('Quantities must be strictly positive.')
|
|
|
|
prod_location = self.location_id
|
|
scrap_location = self.env['stock.location'].search([('scrap_location', '=', True), ('company_id', '=', self.company_id.id)], limit=1)
|
|
if not scrap_location:
|
|
# Fallback to standard production loction usually handled via standard routes, but we can do a simple virtual production loc
|
|
scrap_location = self.env.ref('stock.location_production')
|
|
|
|
# 1. Consume Bulk (Move from Internal to Production)
|
|
consume_move = self.env['stock.move'].create({
|
|
'name': 'Repack Consume %s' % self.name,
|
|
'product_id': self.source_product_id.id,
|
|
'product_uom_qty': self.source_qty,
|
|
'product_uom': self.source_uom_id.id,
|
|
'location_id': prod_location.id,
|
|
'location_dest_id': scrap_location.id,
|
|
'repack_id': self.id,
|
|
'state': 'draft',
|
|
'company_id': self.company_id.id,
|
|
})
|
|
consume_move._action_confirm()
|
|
if self.source_lot_id:
|
|
self.env['stock.move.line'].create({
|
|
'move_id': consume_move.id,
|
|
'product_id': self.source_product_id.id,
|
|
'product_uom_id': self.source_uom_id.id,
|
|
'quantity': self.source_qty,
|
|
'lot_id': self.source_lot_id.id,
|
|
'location_id': prod_location.id,
|
|
'location_dest_id': scrap_location.id,
|
|
})
|
|
else:
|
|
consume_move.quantity = self.source_qty
|
|
consume_move._action_done()
|
|
|
|
# 2. Produce Retail Packs (Move from Production to Internal)
|
|
produce_move = self.env['stock.move'].create({
|
|
'name': 'Repack Produce %s' % self.name,
|
|
'product_id': self.dest_product_id.id,
|
|
'product_uom_qty': self.dest_qty,
|
|
'product_uom': self.dest_uom_id.id,
|
|
'location_id': scrap_location.id,
|
|
'location_dest_id': prod_location.id,
|
|
'repack_id': self.id,
|
|
'state': 'draft',
|
|
'company_id': self.company_id.id,
|
|
})
|
|
produce_move._action_confirm()
|
|
if self.dest_lot_id:
|
|
self.env['stock.move.line'].create({
|
|
'move_id': produce_move.id,
|
|
'product_id': self.dest_product_id.id,
|
|
'product_uom_id': self.dest_uom_id.id,
|
|
'quantity': self.dest_qty,
|
|
'lot_id': self.dest_lot_id.id,
|
|
'location_id': scrap_location.id,
|
|
'location_dest_id': prod_location.id,
|
|
})
|
|
else:
|
|
produce_move.quantity = self.dest_qty
|
|
produce_move._action_done()
|
|
|
|
self.write({'state': 'done'})
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = 'stock.move'
|
|
repack_id = fields.Many2one('c2c.repack.order', string='Repack Order', copy=False)
|