Odoo brinda soporte para manejar paquetes en el stock. A nivel desarrollo funciona bien y con un colector de código de barras que conozco trabaja perfecto. Pero a nivel formulario de transferencias es limitado, engorroso para el usuario. Muchas veces el usuario cuando hace una transferencia necesita primero crear el paquete, y luego agregar los contenidos de la transferencia al paquete. Esa funcionalidad la implementamos en un módulo llamado stock_add_packages.
Este módulo agrega un botón a las transferencias llamado "Agregar paquetes" el cual pregunta el nombre del paquete a crear, y luego permite agregar los contenidos de la transferencia al paquete
En las líneas uno puede indicar por operación que cantidad de unidades desea agregar al paquete. Luego al confirmar, se actualizan las líneas de las operaciones con el paquete indicado.
Notas tecnicas
Este módulo implementa un wizard el cual es llamado desde una transferencia. Como todo wizard, se lo llama desde un método en un objeto y dicho método debe devolver un diccionario con la llamada a una acción de ventana.
def btn_add_packages(self):
self.ensure_one()
vals = {
'picking_id': self.id,
}
wizard_id = self.env['add.packages.wizard'].create(vals)
domain = [('picking_id','=',self.id),('result_package_id','=',False)]
move_lines = self.env['stock.move.line'].search(domain)
if not move_lines:
raise ValidationError('No hay operaciones sin paquete asignado')
for move_line in move_lines:
vals_line = {
'wizard_id': wizard_id.id,
'move_line_id': move_line.id,
'original_quantity': move_line.quantity,
'final_quantity': move_line.quantity,
}
line_id = self.env['add.packages.line.wizard'].create(vals_line)
return {
'name': _('Add Packages'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'add.packages.wizard',
'res_id': wizard_id.id,
'target': 'new',
'type': 'ir.actions.act_window',
}
En este metodo tambien se implementa la logica para mostrar solo las operaciones que no tienen asignadas paquetes.
Como implementa Odoo su lógica de paquetes? Primero tiene el objeto paquete, llamado stock.quant.package. El cual basicamente solo tiene un nombre. Y cuales son sus contenidos? Los quants referenciados por la columna package_id. Como se referencian los paquetes en las operaciones? Por medio de las columnas package_id y result_package_id.
Bien, en el wizard lo primero que hacemos es pedir el nombre del nuevo paquete, y lo creamos. Una vez creado, lo que hacemos es actualizar las operaciones sin paquetes con la referencia del paquete creado.
if not pack_name:
raise ValidationError('Ingrese nombre del paquete')
pack_id = self.env['stock.quant.package'].search([('name','=',pack_name)])
if pack_id:
raise ValidationError('Paquete existente')
pack_id = self.env['stock.quant.package'].create({'name': pack_name})
for line in self.line_ids:
if line.original_quantity == line.final_quantity:
move_line = line.move_line_id
move_line.result_package_id = pack_id.id
else:
move_line = line.move_line_id
original_quantity = line.original_quantity
new_line = move_line.copy({'quantity': original_quantity - line.final_quantity})
move_line.quantity = line.final_quantity
move_line.result_package_id = pack_id.id
Ahora, si la cantidad de unidades en la operacion es menor a la cantidad de la demanda, se crea una nueva operacion con la cantidad resstante. Para ello utilizamos el comando copy
new_line = move_line.copy({'quantity': original_quantity - line.final_quantity})