commit 70ae5ea8049c0d4fa04e18804ac92f09efba9c74 Author: Suherdy Yacob Date: Tue Feb 10 14:53:13 2026 +0700 first commit diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..394cd0e --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,18 @@ +{ + 'name': 'Approval Create WH to Prep Move', + 'version': '1.0', + 'category': 'Inventory/Approvals', + 'summary': 'Create Inventory Transfer from Approval Request', + 'description': """ + This module adds a new approval type "Create WH to Prep Move" to the Approvals app. + When approved, it allows users to create an inventory transfer with the operation + "Brigjend Katamso: WH to Prep (Send)" and destination "Physical Locations/Inter-warehouse transit". + """, + 'depends': ['approvals', 'stock'], + 'data': [ + 'views/approval_request_views.xml', + ], + 'installable': True, + 'application': False, + 'license': 'LGPL-3', +} diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..73a2a86 Binary files /dev/null and b/__pycache__/__init__.cpython-312.pyc differ diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..af8ab6f --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,2 @@ +from . import approval_category +from . import approval_request diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..dc18a6e Binary files /dev/null and b/models/__pycache__/__init__.cpython-312.pyc differ diff --git a/models/__pycache__/approval_category.cpython-312.pyc b/models/__pycache__/approval_category.cpython-312.pyc new file mode 100644 index 0000000..594de14 Binary files /dev/null and b/models/__pycache__/approval_category.cpython-312.pyc differ diff --git a/models/__pycache__/approval_request.cpython-312.pyc b/models/__pycache__/approval_request.cpython-312.pyc new file mode 100644 index 0000000..0273667 Binary files /dev/null and b/models/__pycache__/approval_request.cpython-312.pyc differ diff --git a/models/approval_category.py b/models/approval_category.py new file mode 100644 index 0000000..18b6816 --- /dev/null +++ b/models/approval_category.py @@ -0,0 +1,12 @@ +from odoo import api, fields, models + +class ApprovalCategory(models.Model): + _inherit = 'approval.category' + + approval_type = fields.Selection(selection_add=[('wh_prep_move', 'Create WH to Prep Move')]) + + @api.onchange('approval_type') + def _onchange_approval_type(self): + if self.approval_type == 'wh_prep_move': + self.has_product = 'required' + self.has_quantity = 'required' diff --git a/models/approval_request.py b/models/approval_request.py new file mode 100644 index 0000000..7384ae2 --- /dev/null +++ b/models/approval_request.py @@ -0,0 +1,86 @@ +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.tools.misc import clean_context +from markupsafe import Markup + +class ApprovalRequest(models.Model): + _inherit = 'approval.request' + + picking_ids = fields.Many2many('stock.picking',compute='_compute_picking_ids', string='Transfers') + picking_count = fields.Integer(compute='_compute_picking_count') + + def _compute_picking_ids(self): + for request in self: + request.picking_ids = self.env['stock.picking'].search([('origin', '=', request.name)]) if request.name else False + + @api.depends('picking_ids') + def _compute_picking_count(self): + for request in self: + request.picking_count = len(request.picking_ids) + + def action_create_wh_prep_move(self): + self.ensure_one() + if self.picking_count > 0: + return + + op_type_name = "Brigjend Katamso: WH to Prep (Send)" + dest_loc_name = "Physical Locations/Inter-warehouse transit" + + # Find Operation Type + picking_type = self.env['stock.picking.type'].search([('name', '=', op_type_name)], limit=1) + if not picking_type: + # Fallback: search by display_name if name isn't exact + picking_types = self.env['stock.picking.type'].search([]) + for pt in picking_types: + if op_type_name in pt.display_name: + picking_type = pt + break + + if not picking_type: + raise UserError(_("Operation Type '%s' not found. Please contact administrator.") % op_type_name) + + # Find Destination Location + dest_loc = self.env['stock.location'].search([('complete_name', '=', dest_loc_name)], limit=1) + if not dest_loc: + raise UserError(_("Destination Location '%s' not found. Please contact administrator.") % dest_loc_name) + + if not self.product_line_ids: + raise UserError(_("You must select products to create a transfer.")) + + picking_vals = { + 'picking_type_id': picking_type.id, + 'location_id': picking_type.default_location_src_id.id, + 'location_dest_id': dest_loc.id, + 'origin': self.name, + 'partner_id': self.partner_id.id, + 'move_ids': [], + } + + for line in self.product_line_ids: + move_vals = { + 'description_picking': line.description, + 'product_id': line.product_id.id, + 'product_uom_qty': line.quantity, + 'product_uom': line.product_uom_id.id, + 'location_id': picking_type.default_location_src_id.id, + 'location_dest_id': dest_loc.id, + } + picking_vals['move_ids'].append((0, 0, move_vals)) + + picking = self.env['stock.picking'].create(picking_vals) + picking.action_confirm() # Confirm the picking to reserve stock if possible + + msg = Markup(_("Created Inventory Transfer: %s")) % (picking.id, picking.name) + self.message_post(body=msg) + + def action_open_wh_prep_move(self): + self.ensure_one() + action = { + 'name': _('Transfers'), + 'type': 'ir.actions.act_window', + 'res_model': 'stock.picking', + 'view_mode': 'list,form', + 'domain': [('origin', '=', self.name)], + 'context': clean_context(self.env.context), + } + return action diff --git a/views/approval_request_views.xml b/views/approval_request_views.xml new file mode 100644 index 0000000..ca76e3c --- /dev/null +++ b/views/approval_request_views.xml @@ -0,0 +1,26 @@ + + + + approval.wh.prep.move.request.view.form.inherit + approval.request + + + + + + +