From 3ed91948307260a25efae332c6dae013d276fef5 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 20 Mar 2025 15:05:01 +0700 Subject: add sale order post massage when confirm product bom --- indoteknik_custom/models/mrp_production.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 54d90256..0bf98702 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -6,5 +6,18 @@ class MrpProduction(models.Model): _inherit = 'mrp.production' desc = fields.Text(string='Description') - - \ No newline at end of file + sale_order = fields.Many2one('sale.order', string='Sale Order', required=True, copy=False) + + def action_confirm(self): + """Override action_confirm untuk mengirim pesan ke Sale Order jika state berubah menjadi 'confirmed'.""" + if self._name != 'mrp.production': + return super(MrpProduction, self).action_confirm() + + result = super(MrpProduction, self).action_confirm() + + for record in self: + if record.sale_order and record.state == 'confirmed': + message = _("Manufacturing order telah dibuat dengan nomor %s") % (record.name) + record.sale_order.message_post(body=message) + + return result \ No newline at end of file -- cgit v1.2.3 From 99626f917b032110fe12b9a0ee86c218c0367be1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 24 Mar 2025 15:34:56 +0700 Subject: push --- indoteknik_custom/models/mrp_production.py | 169 ++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 54d90256..ed05de91 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -1,4 +1,7 @@ -from odoo import fields, models, api, _ +from odoo import models, fields, api, tools, _ +from datetime import datetime, timedelta +import math +import logging from odoo.exceptions import AccessError, UserError, ValidationError @@ -6,5 +9,167 @@ class MrpProduction(models.Model): _inherit = 'mrp.production' desc = fields.Text(string='Description') + status = fields.Selection([('pending', 'Pending'), ('approved', 'Approved'), ('reject', 'Reject')], string='Status', default='pending', tracking=3) + production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) + + def action_approve(self): + if self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and self.status == 'pending': + self.status = 'approved' + + def action_reject(self): + if self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and self.status == 'pending': + self.status = 'reject' + + def create_po_from_manufacturing(self): + if not self.status == 'approved': + raise UserError('Harus Di Approve oleh Merchandiser') + + if not self.move_raw_ids: + raise UserError('Tidak ada Lines, belum bisa create PO') + # if self.is_po: + # raise UserError('Sudah pernah di create PO') + + vendor_ids = self.env['stock.move'].read_group([ + ('raw_material_production_id', '=', self.id), + ('vendor_id', '!=', False) + ], fields=['vendor_id'], groupby=['vendor_id']) + + po_ids = [] + for vendor in vendor_ids: + result_po = self.create_po_by_vendor(vendor['vendor_id'][0]) + po_ids += result_po + return { + 'name': _('Purchase Order'), + 'view_mode': 'tree,form', + 'res_model': 'purchase.order', + 'target': 'current', + 'type': 'ir.actions.act_window', + 'domain': [('id', 'in', po_ids)], + } + + + def create_po_by_vendor(self, vendor_id): + current_time = datetime.now() + + PRODUCT_PER_PO = 20 + + stock_move = self.env['stock.move'] + + param_header = { + 'partner_id': vendor_id, + # 'partner_ref': self.sale_order_id.name, + 'currency_id': 12, + 'user_id': self.env.user.id, + 'company_id': 1, # indoteknik dotcom gemilang + 'picking_type_id': 28, # indoteknik bandengan receipts + 'date_order': current_time, + # 'sale_order_id': self.sale_order_id.id, + 'note_description': 'from Manufacturing Order' + } + + domain = [ + ('raw_material_production_id', '=', self.id), + ('vendor_id', '=', vendor_id), + ('state', 'in', ['waiting','confirmed','partially_available']) + ] + + products_len = stock_move.search_count(domain) + page = math.ceil(products_len / PRODUCT_PER_PO) + po_ids = [] + # i start from zero (0) + for i in range(page): + new_po = self.env['purchase.order'].create([param_header]) + new_po.name = new_po.name + "/MO/" + str(i + 1) + po_ids.append(new_po.id) + lines = stock_move.search( + domain, + offset=i * PRODUCT_PER_PO, + limit=PRODUCT_PER_PO + ) + tax = [22] + + for line in lines: + product = line.product_id + price, taxes, vendor = self._get_purchase_price(product) + + param_line = { + 'order_id' : new_po.id, + 'product_id': product.id, + 'product_qty': line.product_uom_qty if line.state in ['confirmed', 'waiting'] else line.product_uom_qty - line.forecast_availability, + 'product_uom_qty': line.product_uom_qty if line.state in ['confirmed', 'waiting'] else line.product_uom_qty - line.forecast_availability, + 'name': product.display_name, + 'price_unit': price, + 'taxes_id': [taxes], + } + new_po_line = self.env['purchase.order.line'].create([param_line]) + + self.env['production.purchase.match'].create([{ + 'production_id': self.id, + 'order_id': new_po.id + }]) + # self.is_po = True + + return po_ids + + def _get_purchase_price(self, product_id): + override_vendor = product_id.x_manufacture.override_vendor_id + if override_vendor: + query = [('product_id', '=', product_id.id), + ('vendor_id', '=', override_vendor.id)] + purchase_price = self.env['purchase.pricelist'].search(query, limit=1) + return self._get_valid_purchase_price(purchase_price) + else: + purchase_price = self.env['purchase.pricelist'].search( + [('product_id', '=', product_id.id), + ('is_winner', '=', True)], + limit=1) + + return self._get_valid_purchase_price(purchase_price) + + def _get_valid_purchase_price(self, purchase_price): + current_time = datetime.now() + delta_time = current_time - timedelta(days=365) + # delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + + price = 0 + taxes = '' + vendor_id = '' + human_last_update = purchase_price.human_last_update or datetime.min + system_last_update = purchase_price.system_last_update or datetime.min + + if purchase_price.taxes_product_id.type_tax_use == 'purchase': + price = purchase_price.product_price + taxes = purchase_price.taxes_product_id.id + vendor_id = purchase_price.vendor_id.id + if delta_time > human_last_update: + price = 0 + taxes = '' + vendor_id = '' + + if system_last_update > human_last_update: + if purchase_price.taxes_system_id.type_tax_use == 'purchase': + price = purchase_price.system_price + taxes = purchase_price.taxes_system_id.id + vendor_id = purchase_price.vendor_id.id + if delta_time > system_last_update: + price = 0 + taxes = '' + vendor_id = '' + + return price, taxes, vendor_id - \ No newline at end of file + +class ProductionPurchaseMatch(models.Model): + _name = 'production.purchase.match' + _order = 'production_id, id' + + production_id = fields.Many2one('mrp.production', string='Ref', required=True, ondelete='cascade', index=True, copy=False) + order_id = fields.Many2one('purchase.order', string='Purchase Order') + vendor = fields.Char(string='Vendor', compute='_compute_info_po') + total = fields.Float(string='Total', compute='_compute_info_po') + + def _compute_info_po(self): + for match in self: + match.vendor = match.order_id.partner_id.name + match.total = match.order_id.amount_total + -- cgit v1.2.3 From db3ff0677f9c6ddd0f04ebcf3e9c780045259f73 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 25 Mar 2025 13:48:16 +0700 Subject: fix get purchase pricelist --- indoteknik_custom/models/mrp_production.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index ed05de91..0e17fda9 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -98,8 +98,8 @@ class MrpProduction(models.Model): 'product_qty': line.product_uom_qty if line.state in ['confirmed', 'waiting'] else line.product_uom_qty - line.forecast_availability, 'product_uom_qty': line.product_uom_qty if line.state in ['confirmed', 'waiting'] else line.product_uom_qty - line.forecast_availability, 'name': product.display_name, - 'price_unit': price, - 'taxes_id': [taxes], + 'price_unit': price if price else 0.0, + 'taxes_id': [taxes] if taxes else [], } new_po_line = self.env['purchase.order.line'].create([param_line]) @@ -113,10 +113,10 @@ class MrpProduction(models.Model): def _get_purchase_price(self, product_id): override_vendor = product_id.x_manufacture.override_vendor_id - if override_vendor: - query = [('product_id', '=', product_id.id), - ('vendor_id', '=', override_vendor.id)] - purchase_price = self.env['purchase.pricelist'].search(query, limit=1) + query = [('product_id', '=', product_id.id), + ('vendor_id', '=', override_vendor.id)] + purchase_price = self.env['purchase.pricelist'].search(query, limit=1) + if purchase_price: return self._get_valid_purchase_price(purchase_price) else: purchase_price = self.env['purchase.pricelist'].search( -- cgit v1.2.3 From e926482af5f2b95ff465445215c77161223ee671 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 27 Mar 2025 14:38:57 +0700 Subject: push --- indoteknik_custom/models/mrp_production.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 0e17fda9..561f5b3c 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -9,19 +9,11 @@ class MrpProduction(models.Model): _inherit = 'mrp.production' desc = fields.Text(string='Description') - status = fields.Selection([('pending', 'Pending'), ('approved', 'Approved'), ('reject', 'Reject')], string='Status', default='pending', tracking=3) production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) - def action_approve(self): - if self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and self.status == 'pending': - self.status = 'approved' - - def action_reject(self): - if self.env.user.has_group('indoteknik_custom.group_role_merchandiser') and self.status == 'pending': - self.status = 'reject' def create_po_from_manufacturing(self): - if not self.status == 'approved': + if not self.state == 'confirmed': raise UserError('Harus Di Approve oleh Merchandiser') if not self.move_raw_ids: @@ -63,6 +55,7 @@ class MrpProduction(models.Model): 'company_id': 1, # indoteknik dotcom gemilang 'picking_type_id': 28, # indoteknik bandengan receipts 'date_order': current_time, + 'product_bom_id': self.product_id.id, # 'sale_order_id': self.sale_order_id.id, 'note_description': 'from Manufacturing Order' } -- cgit v1.2.3 From b105f669873645f29314be55aac45d95d0556970 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 27 Mar 2025 16:20:05 +0700 Subject: fix bug --- indoteknik_custom/models/mrp_production.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 1813dbeb..d80df2ce 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -11,6 +11,7 @@ class MrpProduction(models.Model): desc = fields.Text(string='Description') sale_order = fields.Many2one('sale.order', string='Sale Order', required=True, copy=False) production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) + is_po = fields.Boolean(string='Is PO') def action_confirm(self): """Override action_confirm untuk mengirim pesan ke Sale Order jika state berubah menjadi 'confirmed'.""" @@ -31,6 +32,9 @@ class MrpProduction(models.Model): if not self.state == 'confirmed': raise UserError('Harus Di Approve oleh Merchandiser') + if self.is_po == True: + raise UserError('Sudah pernah di buat PO') + if not self.move_raw_ids: raise UserError('Tidak ada Lines, belum bisa create PO') # if self.is_po: @@ -115,7 +119,8 @@ class MrpProduction(models.Model): 'production_id': self.id, 'order_id': new_po.id }]) - # self.is_po = True + + self.is_po = True return po_ids -- cgit v1.2.3 From 783b674e04dd123a5233fd01896925c73aa8143c Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 29 Apr 2025 10:00:15 +0700 Subject: check product on bom, view stock picking po and fix bug api flashsale header --- indoteknik_custom/models/mrp_production.py | 284 +++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index d80df2ce..ebbd1c24 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -8,11 +8,34 @@ from odoo.exceptions import AccessError, UserError, ValidationError class MrpProduction(models.Model): _inherit = 'mrp.production' + check_bom_product_lines = fields.One2many('check.bom.product', 'production_id', string='Check Product', auto_join=True, copy=False) desc = fields.Text(string='Description') sale_order = fields.Many2one('sale.order', string='Sale Order', required=True, copy=False) production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) is_po = fields.Boolean(string='Is PO') + @api.constrains('check_bom_product_lines') + def constrains_check_bom_product_lines(self): + for rec in self: + if len(rec.check_bom_product_lines) > 0: + rec.qty_producing = rec.product_qty + + def button_mark_done(self): + """Override button_mark_done untuk mengirim pesan ke Sale Order jika state berubah menjadi 'confirmed'.""" + if self._name != 'mrp.production': + return super(MrpProduction, self).button_mark_done() + + result = super(MrpProduction, self).button_mark_done() + + for record in self: + if len(record.check_bom_product_lines) < 1: + raise UserError("Check Product Tidak Boleh Kosong") + if record.sale_order and record.state == 'confirmed': + message = _("Manufacturing order telah dibuat dengan nomor %s") % (record.name) + record.sale_order.message_post(body=message) + + return result + def action_confirm(self): """Override action_confirm untuk mengirim pesan ke Sale Order jika state berubah menjadi 'confirmed'.""" if self._name != 'mrp.production': @@ -21,6 +44,8 @@ class MrpProduction(models.Model): result = super(MrpProduction, self).action_confirm() for record in self: + # if len(record.check_bom_product_lines) < 1: + # raise UserError("Check Product Tidak Boleh Kosong") if record.sale_order and record.state == 'confirmed': message = _("Manufacturing order telah dibuat dengan nomor %s") % (record.name) record.sale_order.message_post(body=message) @@ -171,6 +196,265 @@ class MrpProduction(models.Model): return price, taxes, vendor_id +class CheckBomProduct(models.Model): + _name = 'check.bom.product' + _description = 'Check Product' + _order = 'production_id, id' + + production_id = fields.Many2one( + 'mrp.production', + string='Bom Reference', + required=True, + ondelete='cascade', + index=True, + copy=False, + ) + product_id = fields.Many2one('product.product', string='Product') + quantity = fields.Float(string='Quantity') + status = fields.Char(string='Status', compute='_compute_status') + code_product = fields.Char(string='Code Product') + + @api.constrains('production_id') + def _check_missing_components(self): + for mo in self: + required = mo.production_id.move_raw_ids.mapped('product_id') + entered = mo.production_id.check_bom_product_lines.mapped('product_id') + missing = required - entered + + # Jika HTML tidak bekerja sama sekali, gunakan format text biasa yang rapi + if missing: + product_list = "\n- " + "\n- ".join(p.display_name for p in missing) + raise UserError( + "⚠️ Komponen Wajib Diisi\n\n" + "Produk berikut harus ditambahkan:\n" + f"{product_list}\n\n" + "Silakan lengkapi terlebih dahulu." + ) + + @api.constrains('production_id', 'product_id') + def _check_product_bom_validation(self): + for record in self: + if not record.production_id or not record.product_id: + continue + + moves = record.production_id.move_raw_ids.filtered( + lambda move: move.product_id.id == record.product_id.id + ) + + if not moves: + raise UserError(( + "The product '%s' tidak ada di operations. " + ) % record.product_id.display_name) + + total_qty_in_moves = sum(moves.mapped('product_uom_qty')) + + # Find existing lines for the same product, excluding the current line + existing_lines = record.production_id.check_bom_product_lines.filtered( + lambda line: line.product_id == record.product_id + ) + + if existing_lines: + total_quantity = sum(existing_lines.mapped('quantity')) + + if total_quantity < total_qty_in_moves: + raise UserError(( + "Quantity Product '%s' kurang dari quantity demand." + ) % (record.product_id.display_name)) + else: + # Check if the quantity exceeds the allowed total + if record.quantity < total_qty_in_moves: + raise UserError(( + "Quantity Product '%s' kurang dari quantity demand." + ) % (record.product_id.display_name)) + + # Set the quantity to the entered value + record.quantity = record.quantity + + @api.onchange('code_product') + def _onchange_code_product(self): + if not self.code_product: + return + + # Cari product berdasarkan default_code, barcode, atau barcode_box + product = self.env['product.product'].search([ + '|', + ('default_code', '=', self.code_product), + '|', + ('barcode', '=', self.code_product), + ('barcode_box', '=', self.code_product) + ], limit=1) + + if not product: + raise UserError("Product tidak ditemukan") + + # Jika scan barcode_box, set quantity sesuai qty_pcs_box + if product.barcode_box == self.code_product: + self.product_id = product.id + self.quantity = product.qty_pcs_box + self.code_product = product.default_code or product.barcode + # return { + # 'warning': { + # 'title': 'Info',8994175025871 + + # 'message': f'Product box terdeteksi. Quantity di-set ke {product.qty_pcs_box}' + # } + # } + else: + # Jika scan biasa + self.product_id = product.id + self.code_product = product.default_code or product.barcode + self.quantity = 1 + + def unlink(self): + # Get all affected pickings before deletion + productions = self.mapped('production_id') + + # Store product_ids that will be deleted + deleted_product_ids = self.mapped('product_id') + + # Perform the deletion + result = super(CheckBomProduct, self).unlink() + + # After deletion, update moves for affected pickings + for production in productions: + # For products that were completely removed (no remaining check.bom.product lines) + remaining_product_ids = production.check_bom_product_lines.mapped('product_id') + removed_product_ids = deleted_product_ids - remaining_product_ids + + # Set quantity_done to 0 for moves of completely removed products + moves_to_reset = production.move_raw_ids.filtered( + lambda move: move.product_id in removed_product_ids + ) + for move in moves_to_reset: + move.quantity_done = 0.0 + + # Also sync remaining products in case their totals changed + self._sync_check_product_to_moves(production) + + return result + + @api.depends('quantity') + def _compute_status(self): + for record in self: + moves = record.production_id.move_raw_ids.filtered( + lambda move: move.product_id.id == record.product_id.id + ) + total_qty_in_moves = sum(moves.mapped('product_uom_qty')) + + if record.quantity < total_qty_in_moves: + record.status = 'Pending' + else: + record.status = 'Done' + + + def create(self, vals): + # Create the record + record = super(CheckBomProduct, self).create(vals) + # Ensure uniqueness after creation + if not self.env.context.get('skip_consolidate'): + record.with_context(skip_consolidate=True)._consolidate_duplicate_lines() + return record + + def write(self, vals): + # Write changes to the record + result = super(CheckBomProduct, self).write(vals) + # Ensure uniqueness after writing + if not self.env.context.get('skip_consolidate'): + self.with_context(skip_consolidate=True)._consolidate_duplicate_lines() + return result + + def _sync_check_product_to_moves(self, production): + """ + Sinkronisasi quantity_done di move_raw_ids + dengan total quantity dari check.bom.product berdasarkan product_id. + """ + for product_id in production.check_bom_product_lines.mapped('product_id'): + # Totalkan quantity dari semua baris check.bom.product untuk product_id ini + total_quantity = sum( + line.quantity for line in production.check_bom_product_lines.filtered(lambda line: line.product_id == product_id) + ) + # Update quantity_done di move yang relevan + moves = production.move_raw_ids.filtered(lambda move: move.product_id == product_id) + for move in moves: + move.quantity_done = total_quantity + + def _consolidate_duplicate_lines(self): + """ + Consolidate duplicate lines with the same product_id under the same production_id + and sync the total quantity to related moves. + """ + for production in self.mapped('production_id'): + lines_to_remove = self.env['check.bom.product'] # Recordset untuk menyimpan baris yang akan dihapus + product_lines = production.check_bom_product_lines.filtered(lambda line: line.product_id) + + # Group lines by product_id + product_groups = {} + for line in product_lines: + product_groups.setdefault(line.product_id.id, []).append(line) + + for product_id, lines in product_groups.items(): + if len(lines) > 1: + # Consolidate duplicate lines + first_line = lines[0] + total_quantity = sum(line.quantity for line in lines) + + # Update the first line's quantity + first_line.with_context(skip_consolidate=True).write({'quantity': total_quantity}) + + # Add the remaining lines to the lines_to_remove recordset + lines_to_remove |= self.env['check.bom.product'].browse([line.id for line in lines[1:]]) + + # Perform unlink after consolidation + if lines_to_remove: + lines_to_remove.unlink() + + # Sync total quantities to moves + self._sync_check_product_to_moves(production) + + @api.onchange('product_id', 'quantity') + def check_product_validity(self): + for record in self: + if not record.production_id or not record.product_id: + continue + + # Filter moves related to the selected product + moves = record.production_id.move_raw_ids.filtered( + lambda move: move.product_id.id == record.product_id.id + ) + + if not moves: + raise UserError(( + "The product '%s' tidak ada di operations. " + ) % record.product_id.display_name) + + total_qty_in_moves = sum(moves.mapped('product_uom_qty')) + + # Find existing lines for the same product, excluding the current line + existing_lines = record.production_id.check_bom_product_lines.filtered( + lambda line: line.product_id == record.product_id + ) + + if existing_lines: + # Get the first existing line + first_line = existing_lines[0] + + # Calculate the total quantity after addition + total_quantity = sum(existing_lines.mapped('quantity')) + + if total_quantity > total_qty_in_moves: + raise UserError(( + "Quantity Product '%s' sudah melebihi quantity demand." + ) % (record.product_id.display_name)) + else: + # Check if the quantity exceeds the allowed total + if record.quantity == total_qty_in_moves: + raise UserError(( + "Quantity Product '%s' sudah melebihi quantity demand." + ) % (record.product_id.display_name)) + + # Set the quantity to the entered value + record.quantity = record.quantity + class ProductionPurchaseMatch(models.Model): _name = 'production.purchase.match' -- cgit v1.2.3 From 7b5b79e03e08dff76981dd9734d20c52f90c0b36 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 30 Apr 2025 11:49:18 +0700 Subject: cr mrp production sale order required --- indoteknik_custom/models/mrp_production.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index ebbd1c24..87d75faf 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -10,7 +10,7 @@ class MrpProduction(models.Model): check_bom_product_lines = fields.One2many('check.bom.product', 'production_id', string='Check Product', auto_join=True, copy=False) desc = fields.Text(string='Description') - sale_order = fields.Many2one('sale.order', string='Sale Order', required=True, copy=False) + sale_order = fields.Many2one('sale.order', string='Sale Order', copy=False) production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) is_po = fields.Boolean(string='Is PO') @@ -30,6 +30,8 @@ class MrpProduction(models.Model): for record in self: if len(record.check_bom_product_lines) < 1: raise UserError("Check Product Tidak Boleh Kosong") + if not record.sale_order: + raise UserError("Sale Order Tidak Boleh Kosong") if record.sale_order and record.state == 'confirmed': message = _("Manufacturing order telah dibuat dengan nomor %s") % (record.name) record.sale_order.message_post(body=message) @@ -327,6 +329,8 @@ class CheckBomProduct(models.Model): ) for move in moves_to_reset: move.quantity_done = 0.0 + + production.qty_producing = 0 # Also sync remaining products in case their totals changed self._sync_check_product_to_moves(production) -- cgit v1.2.3 From 4c4414b0a4b0a51acfe7324c4c556cd0aa57c3c6 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 30 Apr 2025 15:35:02 +0700 Subject: push --- indoteknik_custom/models/mrp_production.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 87d75faf..8179fe56 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -13,6 +13,14 @@ class MrpProduction(models.Model): sale_order = fields.Many2one('sale.order', string='Sale Order', copy=False) production_purchase_match = fields.One2many('production.purchase.match', 'production_id', string='Purchase Matches', auto_join=True) is_po = fields.Boolean(string='Is PO') + state_reserve = fields.Selection([ + ('waiting', 'Waiting For Fullfilment'), + ('ready', 'Ready to Ship'), + ('done', 'Done'), + ('cancel', 'Cancelled'), + ], string='Status Reserve', tracking=True, copy=False, help="The current state of the stock picking.") + date_reserved = fields.Datetime(string="Date Reserved", help='Tanggal ter-reserved semua barang nya', copy=False) + @api.constrains('check_bom_product_lines') def constrains_check_bom_product_lines(self): -- cgit v1.2.3 From d70d65c19dccb2cc4264385c121c697ecd3fa8cd Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 14 May 2025 17:03:55 +0700 Subject: add validation state so on mrp production --- indoteknik_custom/models/mrp_production.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 8179fe56..58c2512c 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -244,6 +244,10 @@ class CheckBomProduct(models.Model): @api.constrains('production_id', 'product_id') def _check_product_bom_validation(self): for record in self: + if record.production_id.sale_order.state not in ['sale', 'done']: + raise UserError(( + "SO harus diconfirm terlebih dahulu." + )) if not record.production_id or not record.product_id: continue -- cgit v1.2.3 From 76d5328565d394c5e78c56c7c2fc37e5470022ce Mon Sep 17 00:00:00 2001 From: stephanchrst Date: Fri, 23 May 2025 15:06:29 +0700 Subject: refactor get valid purchase price cause of null in tax purchase --- indoteknik_custom/models/mrp_production.py | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'indoteknik_custom/models/mrp_production.py') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 58c2512c..14821f27 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -180,29 +180,29 @@ class MrpProduction(models.Model): # delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') price = 0 - taxes = '' + taxes = 24 vendor_id = '' human_last_update = purchase_price.human_last_update or datetime.min system_last_update = purchase_price.system_last_update or datetime.min - if purchase_price.taxes_product_id.type_tax_use == 'purchase': - price = purchase_price.product_price - taxes = purchase_price.taxes_product_id.id + #if purchase_price.taxes_product_id.type_tax_use == 'purchase': + price = purchase_price.product_price + taxes = purchase_price.taxes_product_id.id or 24 + vendor_id = purchase_price.vendor_id.id + if delta_time > human_last_update: + price = 0 + taxes = '' + vendor_id = '' + + if system_last_update > human_last_update: + #if purchase_price.taxes_system_id.type_tax_use == 'purchase': + price = purchase_price.system_price + taxes = purchase_price.taxes_system_id.id or 24 vendor_id = purchase_price.vendor_id.id - if delta_time > human_last_update: + if delta_time > system_last_update: price = 0 - taxes = '' + taxes = 24 vendor_id = '' - - if system_last_update > human_last_update: - if purchase_price.taxes_system_id.type_tax_use == 'purchase': - price = purchase_price.system_price - taxes = purchase_price.taxes_system_id.id - vendor_id = purchase_price.vendor_id.id - if delta_time > system_last_update: - price = 0 - taxes = '' - vendor_id = '' return price, taxes, vendor_id -- cgit v1.2.3