diff --git a/bemade_packing_wizard/__init__.py b/bemade_packing_wizard/__init__.py new file mode 100644 index 0000000..3616b30 --- /dev/null +++ b/bemade_packing_wizard/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import models +from . import wizard \ No newline at end of file diff --git a/bemade_packing_wizard/__manifest__.py b/bemade_packing_wizard/__manifest__.py new file mode 100644 index 0000000..41b136d --- /dev/null +++ b/bemade_packing_wizard/__manifest__.py @@ -0,0 +1,25 @@ +{ + 'name': 'Packing wizard', + 'version': '15.0.1.0.0', + 'category': 'Extra Tools', + 'summary': 'Allow automated packing type creation', + 'description': """ + This module allows users simply enter all the package dimensions on every packing and it will create the packing + type automatically if it not exists, use it the create the package with the weight and related package type. + + You need to activate the auto create package feature on the delivery carrier to use this feature. + """, + 'depends': [ + 'delivery' + ], + 'data': [ + 'views/stock_package_views.xml', + 'views/delivery_carrier_views.xml', + 'wizard/choose_delivery_package_views.xml', + ], + 'license': 'AGPL-3', + 'author': 'Bemade', + 'website': 'https://bemade.org/', + 'installable': True, + 'auto_install': False +} diff --git a/bemade_packing_wizard/models/__init__.py b/bemade_packing_wizard/models/__init__.py new file mode 100644 index 0000000..aea7c24 --- /dev/null +++ b/bemade_packing_wizard/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from . import stock_quant_package +from . import delivery_carrier + diff --git a/bemade_packing_wizard/models/delivery_carrier.py b/bemade_packing_wizard/models/delivery_carrier.py new file mode 100644 index 0000000..4f72762 --- /dev/null +++ b/bemade_packing_wizard/models/delivery_carrier.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api +from odoo.exceptions import ValidationError + +class DeliveryCarrier(models.Model): + _inherit = 'delivery.carrier' + + # this allow us to enable the auto create package feature per delivery.carrier + # default is False to avoid impacting Odoo's default behavior on Test + auto_create_package = fields.Boolean('Auto Create Package', default=False) \ No newline at end of file diff --git a/bemade_packing_wizard/models/stock_quant_package.py b/bemade_packing_wizard/models/stock_quant_package.py new file mode 100644 index 0000000..fc4ce1f --- /dev/null +++ b/bemade_packing_wizard/models/stock_quant_package.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields, api +from odoo.exceptions import ValidationError + +class StockQuantPackage(models.Model): + _inherit = 'stock.quant.package' + + length = fields.Float('Length') + width = fields.Float('Width') + height = fields.Float('Height') + + carrier_id = fields.Many2one( + comodel_name='delivery.carrier', + string='Carrier', + help="Carrier use to create package.", + compute='_compute_package_carrier' + ) + + provider = fields.Selection( + selection=lambda self: self._get_provider(), + string='Provider', + help="Provider to create package.", + compute='_compute_package_carrier' + ) + + auto_create_package = fields.Boolean( + string='Auto Create Package', + compute='_compute_auto_create_package' + ) + + + @api.depends('carrier_id') + def _compute_auto_create_package(self): + for record in self: + record.auto_create_package = record.carrier_id.auto_create_package if record.carrier_id else False + + + def _compute_package_carrier(self): + move_line = self.env['stock.move.line'].search([('result_package_id', '=', self.id)]) + self.carrier_id = move_line.carrier_id + delivery_types_available = [item[0] for item in self.env['stock.package.type']._fields['package_carrier_type'].selection] + if self.carrier_id.delivery_type not in delivery_types_available: + self.provider = False + else: + self.provider = move_line.carrier_id.delivery_type + + + def _get_package_carrier_types(self): + return self.env['stock.package.type']._fields['package_carrier_type'].selection + + + def _get_provider(self): + return self.env['stock.package.type']._fields['package_carrier_type'].selection + + + def write(self, vals): + if 'length' in vals and 'width' in vals and 'height' in vals: + # check if length, width, height are greater than 0 + if vals['length'] <= 0 or vals['width'] <= 0 or vals['height'] <= 0: + raise ValidationError('Length, width, and height must be greater than 0.') + # Make sure length is always greater than width + if vals['length'] < vals['width']: + vals['length'], vals['width'] = vals['width'], vals['length'] + # check if existing package_type exists + package_type = self.env['stock.package.type'].search([ + ('width', '=', vals['width']), + ('height', '=', vals['height']), + ('packaging_length', '=', vals['length']), + ('package_carrier_type', '=', self.provider) + ], limit=1) +# ]) + + if not package_type: + package_type = self.env['stock.package.type'].create({ + 'name': f'Box {vals["width"]}x{vals["height"]}x{vals["length"]}', + 'width': vals['width'], + 'height': vals['height'], + 'packaging_length': vals['length'], + 'package_carrier_type': self.provider + }) + + vals['package_type_id'] = package_type.id + + res = super(StockQuantPackage, self).write(vals) + + # check if length, width, height are changed + return res \ No newline at end of file diff --git a/bemade_packing_wizard/views/delivery_carrier_views.xml b/bemade_packing_wizard/views/delivery_carrier_views.xml new file mode 100644 index 0000000..ab68008 --- /dev/null +++ b/bemade_packing_wizard/views/delivery_carrier_views.xml @@ -0,0 +1,13 @@ + + + + Auto package configuration + delivery.carrier + + + + + + + + \ No newline at end of file diff --git a/bemade_packing_wizard/views/stock_package_views.xml b/bemade_packing_wizard/views/stock_package_views.xml new file mode 100644 index 0000000..8210b1d --- /dev/null +++ b/bemade_packing_wizard/views/stock_package_views.xml @@ -0,0 +1,20 @@ + + + + stock.view_quant_package_form_size + stock.quant.package + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bemade_packing_wizard/wizard/__init__.py b/bemade_packing_wizard/wizard/__init__.py new file mode 100644 index 0000000..06b962d --- /dev/null +++ b/bemade_packing_wizard/wizard/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import choose_delivery_package diff --git a/bemade_packing_wizard/wizard/choose_delivery_package.py b/bemade_packing_wizard/wizard/choose_delivery_package.py new file mode 100644 index 0000000..75d1658 --- /dev/null +++ b/bemade_packing_wizard/wizard/choose_delivery_package.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api +from math import ceil +from odoo.exceptions import ValidationError + + +class ChooseDeliveryPackage(models.TransientModel): + _inherit = 'choose.delivery.package' + + length = fields.Float('Length') + width = fields.Float('Width') + height = fields.Float('Height') + + auto_create_package = fields.Boolean( + string='Auto Create Package', + ) + + provider = fields.Selection( + selection=lambda self: self._get_provider(), + string='Provider', + help="Provider to create package.", + ) + + @api.model + def default_get(self, fields_list): + defaults = super().default_get(fields_list) + if 'provider' in fields_list: + picking = self.env['stock.picking'].browse(defaults.get('picking_id')) + + delivery_types_available = [item[0] for item in self.env['stock.package.type']._fields['package_carrier_type'].selection] + if picking.carrier_id.delivery_type not in delivery_types_available: + defaults['provider'] = False + defaults['auto_create_package'] = False + else: + defaults['provider'] = picking.carrier_id.delivery_type + defaults['auto_create_package'] = picking.carrier_id.auto_create_package + return defaults + + + def _get_provider(self): + return self.env['stock.package.type']._fields['package_carrier_type'].selection + + # def _compute_auto_create_package(self): + # for record in self: + # record.auto_create_package = record.carrier_id.auto_create_package if record.carrier_id else False + # + # def _compute_provider(self): + # move_line = self.env['stock.move.line'].search([('result_package_id', '=', self.id)]) + # delivery_types_available = [item[0] for item in self.env['stock.package.type']._fields['package_carrier_type'].selection] + # if self.picking_id.carrier_id.delivery_type not in delivery_types_available: + # self.provider = False + # else: + # self.provider = move_line.carrier_id.delivery_type + # + + + def action_put_in_pack(self): + if self.auto_create_package: + if self.width <= 0 or self.height <= 0 or self.length <= 0: + raise ValidationError('Length, width, and height must be greater than 0.') + + if self.length < self.width: + self.length, self.width = self.width, self.length + + delivery_package_type = self.env['stock.package.type'].search([ + ('width', '=', self.width), + ('height', '=', self.height), + ('packaging_length', '=', self.length), + ('package_carrier_type', '=', self.provider) + ], limit=1) + + if not delivery_package_type: + delivery_package_type = delivery_package_type.create({ + 'name': f'Box {vals["width"]}x{vals["height"]}x{vals["length"]}', + 'width': self.width, + 'height': self.height, + 'packaging_length': self.length, + 'package_carrier_type': self.provider + }) + + self.delivery_package_type_id = delivery_package_type.id + result = super().action_put_in_pack() + return result \ No newline at end of file diff --git a/bemade_packing_wizard/wizard/choose_delivery_package_views.xml b/bemade_packing_wizard/wizard/choose_delivery_package_views.xml new file mode 100644 index 0000000..ea9654b --- /dev/null +++ b/bemade_packing_wizard/wizard/choose_delivery_package_views.xml @@ -0,0 +1,23 @@ + + + + choose.delivery.package.form2 + choose.delivery.package + + + + + + + + + + + + + +