From 6c43ee02300fbeee3a838a1d2d4b145096fa7df8 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 27 Nov 2025 16:36:21 +0700 Subject: push --- indoteknik_custom/models/stock_picking.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index e7686b75..1a5239d7 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1453,10 +1453,10 @@ class StockPicking(models.Model): if not self.linked_manual_bu_out and 'BU/PICK/' in self.name: raise UserError(_("Isi BU Out terlebih dahulu!")) - if len(self.check_product_lines) == 0 and 'BU/PICK/' in self.name: + if len(self.check_product_lines) == 0 and 'BU/PICK/' in self.name and not self.env.user.has_group('indoteknik_custom.group_role_it'): raise UserError(_("Tidak ada Check Product! Harap periksa kembali.")) - if len(self.check_product_lines) == 0 and 'BU/INPUT/' in self.name: + if len(self.check_product_lines) == 0 and 'BU/INPUT/' in self.name and not self.env.user.has_group('indoteknik_custom.group_role_it'): raise UserError(_("Tidak ada Check Product! Harap periksa kembali.")) if self.total_koli > self.total_so_koli: -- cgit v1.2.3 From 6439ce89ae7c89663d61aed0abb5affc7fb75d23 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Thu, 27 Nov 2025 17:11:37 +0700 Subject: urutan validate picking vcm --- indoteknik_custom/models/stock_picking.py | 33 ++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 1a5239d7..fbcddc5a 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1416,6 +1416,37 @@ class StockPicking(models.Model): group_id = self.env.ref('indoteknik_custom.group_role_merchandiser').id users_in_group = self.env['res.users'].search([('groups_id', 'in', [group_id])]) active_model = self.env.context.get('active_model') + if self.tukar_guling_po_id: + for po in self.tukar_guling_po_id: + pickings = po.picking_ids.filtered(lambda p: p.return_type == 'tukar_guling') + + # Buat mapping picking berdasarkan prefix + picking_map = { + 'BU/VRT': None, + 'BU/PRT': None, + 'BU/INPUT': None, + 'BU/PUT': None, + } + + for picking in pickings: + for prefix in picking_map: + if picking.name.startswith(prefix): + picking_map[prefix] = picking + + # Cek apakah keempat jenis picking tersedia + missing = [key for key, val in picking_map.items() if val is None] + if missing: + raise UserError(f"Picking untuk tukar guling tidak lengkap: {', '.join(missing)}") + + # Cek urutan sesuai aturan: VRT -> PRT -> INPUT -> PUT + ordered_pickings = [picking_map['BU/VRT'], picking_map['BU/PRT'], picking_map['BU/INPUT'], picking_map['BU/PUT']] + done_pickings = [p for p in ordered_pickings if p.state == 'done'] + + for i, picking in enumerate(done_pickings): + expected = ordered_pickings[i] + if picking != expected: + raise UserError("Urutan validasi picking tukar guling tidak sesuai. Harus mengikuti urutan: BU/VRT → BU/PRT → BU/INPUT → BU/PUT") + if self.is_so_fiktif == True: raise UserError("SO Fiktif tidak bisa di validate") if self.location_id.id == 47 and self.env.user.id not in users_in_group.mapped( @@ -2821,4 +2852,4 @@ class StockPickingSjDocument(models.Model): picking_id = fields.Many2one('stock.picking', required=True, ondelete='cascade') image = fields.Binary('Gambar', required=True, attachment=True) - sequence = fields.Integer('Urutan', default=10) \ No newline at end of file + sequence = fields.Integer('Urutan', default=10) -- cgit v1.2.3 From 15717173d3774635bdb3838fb0b37cee91e0dcd5 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Fri, 28 Nov 2025 09:47:44 +0700 Subject: VCM validate sequence --- indoteknik_custom/models/stock_picking.py | 73 ++++++++++++++++++------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index fbcddc5a..900529b9 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1406,6 +1406,47 @@ class StockPicking(models.Model): else: raise UserError('Hanya MD yang bisa Approve') + def validate_seq_vcm(self): + for picking in self: + tg_po = picking.tukar_guling_po_id + if not tg_po: + continue + + return_type = tg_po.return_type + if return_type not in ['retur_po', 'tukar_guling']: + continue + + picking_order = [] + if return_type == 'retur_po': + picking_order = ['BU/INPUT', 'BU/PUT'] + elif return_type == 'tukar_guling': + picking_order = ['BU/VRT', 'BU/PRT', 'BU/INPUT', 'BU/PUT'] + + related_pickings = self.env['stock.picking'].search([ + ('tukar_guling_po_id', '=', tg_po.id) + ]) + + ordered_pickings = [] + for prefix in picking_order: + match = next((p for p in related_pickings if p.name.startswith(prefix)), None) + if not match: + raise UserError(f"Picking dengan prefix {prefix} belum ada.") + ordered_pickings.append(match) + + current_index = -1 + for idx, p in enumerate(ordered_pickings): + if p.id == picking.id: + current_index = idx + break + + if current_index == -1: + raise UserError("Picking ini tidak ditemukan dalam urutan picking yang sesuai.") + + for prev_picking in ordered_pickings[:current_index]: + if prev_picking.state != 'done': + raise UserError( + f"Tidak bisa validasi {picking.name} sebelum {prev_picking.name} divalidasi." + ) def button_validate(self): self.check_invoice_date() _logger.info("Kode Picking: %s", self.picking_type_id.code) @@ -1416,37 +1457,7 @@ class StockPicking(models.Model): group_id = self.env.ref('indoteknik_custom.group_role_merchandiser').id users_in_group = self.env['res.users'].search([('groups_id', 'in', [group_id])]) active_model = self.env.context.get('active_model') - if self.tukar_guling_po_id: - for po in self.tukar_guling_po_id: - pickings = po.picking_ids.filtered(lambda p: p.return_type == 'tukar_guling') - - # Buat mapping picking berdasarkan prefix - picking_map = { - 'BU/VRT': None, - 'BU/PRT': None, - 'BU/INPUT': None, - 'BU/PUT': None, - } - - for picking in pickings: - for prefix in picking_map: - if picking.name.startswith(prefix): - picking_map[prefix] = picking - - # Cek apakah keempat jenis picking tersedia - missing = [key for key, val in picking_map.items() if val is None] - if missing: - raise UserError(f"Picking untuk tukar guling tidak lengkap: {', '.join(missing)}") - - # Cek urutan sesuai aturan: VRT -> PRT -> INPUT -> PUT - ordered_pickings = [picking_map['BU/VRT'], picking_map['BU/PRT'], picking_map['BU/INPUT'], picking_map['BU/PUT']] - done_pickings = [p for p in ordered_pickings if p.state == 'done'] - - for i, picking in enumerate(done_pickings): - expected = ordered_pickings[i] - if picking != expected: - raise UserError("Urutan validasi picking tukar guling tidak sesuai. Harus mengikuti urutan: BU/VRT → BU/PRT → BU/INPUT → BU/PUT") - + self.validate_seq_vcm() if self.is_so_fiktif == True: raise UserError("SO Fiktif tidak bisa di validate") if self.location_id.id == 47 and self.env.user.id not in users_in_group.mapped( -- cgit v1.2.3 From 781b4a10102836443357a941e68a333edefbdf76 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Fri, 28 Nov 2025 16:06:39 +0700 Subject: hide refrenece and info line dunning run --- indoteknik_custom/views/dunning_run.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/indoteknik_custom/views/dunning_run.xml b/indoteknik_custom/views/dunning_run.xml index 911a372d..52a0c6ae 100644 --- a/indoteknik_custom/views/dunning_run.xml +++ b/indoteknik_custom/views/dunning_run.xml @@ -25,8 +25,8 @@ - - + + @@ -125,4 +125,4 @@ action="dunning_run_action" parent="account.menu_finance_reports" sequence="200"/> - \ No newline at end of file + -- cgit v1.2.3 From 73296b2a5e1baaa29770d4d91482c95d93740572 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Mon, 1 Dec 2025 09:31:53 +0700 Subject: uom bquick in invoice always unit in coretax xml --- indoteknik_custom/models/coretax_fatur.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index 755c5cc3..d93ca7b7 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -117,7 +117,7 @@ class CoretaxFaktur(models.Model): ) # Calculate totals - total_product_amount = sum(line.get('price_subtotal', 0) if isinstance(line, dict) + total_product_amount = sum(line.get('price_subtotal', 0) if isinstance(line, dict) else line.price_subtotal for line in product_lines) if total_product_amount == 0: total_product_amount = 1 # Avoid division by zero @@ -153,7 +153,10 @@ class CoretaxFaktur(models.Model): else: uom = line.product_uom_id - coretax_id = uom.coretax_id if uom else '' + coretax_id = uom.coretax_id if uom else 'UM.0018' + bquick_id = 80007 + if invoice.partner_id.id == bquick_id: + coretax_id = 'UM.0018' # coretax_id = line.product_uom_id.coretax_id # Calculate other tax values -- cgit v1.2.3 From 42cb9eef299048dcca942fee3c02c845e44893fd Mon Sep 17 00:00:00 2001 From: Mqdd Date: Mon, 1 Dec 2025 09:51:58 +0700 Subject: Coretax xml bquik always unit --- indoteknik_custom/models/coretax_fatur.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/indoteknik_custom/models/coretax_fatur.py b/indoteknik_custom/models/coretax_fatur.py index d93ca7b7..c098fd01 100644 --- a/indoteknik_custom/models/coretax_fatur.py +++ b/indoteknik_custom/models/coretax_fatur.py @@ -154,9 +154,6 @@ class CoretaxFaktur(models.Model): uom = line.product_uom_id coretax_id = uom.coretax_id if uom else 'UM.0018' - bquick_id = 80007 - if invoice.partner_id.id == bquick_id: - coretax_id = 'UM.0018' # coretax_id = line.product_uom_id.coretax_id # Calculate other tax values @@ -170,7 +167,7 @@ class CoretaxFaktur(models.Model): ET.SubElement(good_service, 'Opt').text = 'A' ET.SubElement(good_service, 'Code').text = '000000' ET.SubElement(good_service, 'Name').text = line_name - ET.SubElement(good_service, 'Unit').text = coretax_id + ET.SubElement(good_service, 'Unit').text = coretax_id if invoice.partner_id.id != 80007 else 'UM.0018' # ET.SubElement(good_service, 'Price').text = str(round(line_price_unit, 2)) if line_price_unit else '0' ET.SubElement(good_service, 'Price').text = str(price_per_unit) ET.SubElement(good_service, 'Qty').text = str(quantity) -- cgit v1.2.3 From a6def05e8e94db52af007bfc42fde9d1b753f000 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Mon, 1 Dec 2025 10:08:00 +0700 Subject: only bg rafly H. can start inventory adjustment --- indoteknik_custom/models/stock_inventory.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py index 69cca5bc..e34d9a8e 100644 --- a/indoteknik_custom/models/stock_inventory.py +++ b/indoteknik_custom/models/stock_inventory.py @@ -52,6 +52,10 @@ class StockInventory(models.Model): return "00001" # Jika format tidak valid, mulai dari 00001 return "00001" # Jika belum ada data, mulai dari 00001 + def action_start(self): + if self.env.user.id != 21: + raise UserError("Hanya Rafly H. yang bisa start inventory") + @api.model def create(self, vals): """Pastikan nomor hanya dibuat saat penyimpanan.""" -- cgit v1.2.3 From d36a64b9cfcc00c55a03bc0d7a090c8142355172 Mon Sep 17 00:00:00 2001 From: HafidBuroiroh Date: Mon, 1 Dec 2025 13:13:34 +0700 Subject: overlap journal --- indoteknik_custom/models/refund_sale_order.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 38ab69fa..5338c9c0 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -335,6 +335,7 @@ class RefundSaleOrder(models.Model): ('state', '=', 'posted'), ('ref', 'ilike', 'uang muka penjualan'), ('ref', 'not ilike', 'reklas'), + ('ref', 'not ilike', 'dp'), ] if so_names: domain += ['|'] * (len(so_names) - 1) @@ -694,6 +695,7 @@ class RefundSaleOrder(models.Model): ('state', '=', 'posted'), ('ref', 'ilike', 'uang muka penjualan'), ('ref', 'not ilike', 'reklas'), + ('ref', 'not ilike', 'dp'), ] domain += ['|'] * (len(so_names) - 1) for n in so_names: -- cgit v1.2.3 From 173ea861bec5f5118efa714a12facf31f0147639 Mon Sep 17 00:00:00 2001 From: HafidBuroiroh Date: Mon, 1 Dec 2025 13:37:07 +0700 Subject: overlap journal --- indoteknik_custom/models/refund_sale_order.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 5338c9c0..fe0002bd 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -292,6 +292,7 @@ class RefundSaleOrder(models.Model): ('sale_id', 'in', so_ids), ('journal_id', '=', 11), ('state', '=', 'posted'), + ('ref', 'not ilike', 'dp'), ]) piutangbca = self.env['account.move'].search([ ('ref', 'in', invoices.mapped('name')), @@ -648,6 +649,7 @@ class RefundSaleOrder(models.Model): ('sale_id', 'in', so_ids), ('journal_id', '=', 11), ('state', '=', 'posted'), + ('ref', 'not ilike', 'dp'), ]) piutangbca = self.env['account.move'].search([ ('ref', 'in', all_invoices.mapped('name')), -- cgit v1.2.3 From 5f28a7a38385ccf529c85ea78138867e04ed6cba Mon Sep 17 00:00:00 2001 From: Mqdd Date: Tue, 2 Dec 2025 09:11:48 +0700 Subject: stock inven add more user --- indoteknik_custom/models/stock_inventory.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py index e34d9a8e..e41854ef 100644 --- a/indoteknik_custom/models/stock_inventory.py +++ b/indoteknik_custom/models/stock_inventory.py @@ -53,8 +53,8 @@ class StockInventory(models.Model): return "00001" # Jika belum ada data, mulai dari 00001 def action_start(self): - if self.env.user.id != 21: - raise UserError("Hanya Rafly H. yang bisa start inventory") + if self.env.user.id not in [21, 17, 6277]: + raise UserError("Hanya Rafly, denise, dan faisal yang bisa start inventory") @api.model def create(self, vals): -- cgit v1.2.3 From b49fc1dcecd3543917c46f6c0a1505b271da5c51 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Tue, 2 Dec 2025 10:03:46 +0700 Subject: fix stock inven action start --- indoteknik_custom/models/stock_inventory.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py index e41854ef..432d9225 100644 --- a/indoteknik_custom/models/stock_inventory.py +++ b/indoteknik_custom/models/stock_inventory.py @@ -55,6 +55,7 @@ class StockInventory(models.Model): def action_start(self): if self.env.user.id not in [21, 17, 6277]: raise UserError("Hanya Rafly, denise, dan faisal yang bisa start inventory") + return super(StockInventory, self).action_start() @api.model def create(self, vals): -- cgit v1.2.3 From 6a8b6d97e2f7814843935b179bfe5390861d8e6c Mon Sep 17 00:00:00 2001 From: Mqdd Date: Wed, 3 Dec 2025 09:17:06 +0700 Subject: cannot approve requisition when has same product in so --- indoteknik_custom/models/requisition.py | 39 +++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/indoteknik_custom/models/requisition.py b/indoteknik_custom/models/requisition.py index bcdafb12..39251a45 100644 --- a/indoteknik_custom/models/requisition.py +++ b/indoteknik_custom/models/requisition.py @@ -77,9 +77,20 @@ class Requisition(models.Model): vals['number'] = self.env['ir.sequence'].next_by_code('requisition') or '0' result = super(Requisition, self).create(vals) return result - + + def check_product_line_to_so(self): + for req in self: + for prod_line in req.requisition_lines: + match = self.env['sale.order.line'].search([ + ('product_id', '=', prod_line.product_id.id), ('order_id', '=', req.sale_order_id.id) + ]) + if match: + raise UserError ('Product sudah di SO tidak approve') + + def button_approve(self): state = ['done', 'sale'] + self.check_product_line_to_so() if self.sale_order_id.state in state: raise UserError('SO sudah Confirm, akan berakibat double Purchase melalui PJ') if self.env.user.id not in [21, 19, 28]: @@ -98,9 +109,9 @@ class Requisition(models.Model): raise UserError('Sudah pernah di create PO') if not self.sale_order_id: raise UserError('Tidak ada link dengan Sales Order, tidak bisa dihitung sebagai Plafon Qty di PO') - + vendor_ids = self.env['requisition.line'].read_group([ - ('requisition_id', '=', self.id), + ('requisition_id', '=', self.id), ('partner_id', '!=', False) ], fields=['partner_id'], groupby=['partner_id']) @@ -116,7 +127,7 @@ class Requisition(models.Model): 'type': 'ir.actions.act_window', 'domain': [('id', 'in', po_ids)], } - + def create_po_by_vendor(self, vendor_id): current_time = datetime.now() @@ -137,7 +148,7 @@ class Requisition(models.Model): } domain = [ - ('requisition_id', '=', self.id), + ('requisition_id', '=', self.id), ('partner_id', '=', vendor_id), ('qty_purchase', '>', 0) ] @@ -151,8 +162,8 @@ class Requisition(models.Model): new_po.name = new_po.name + "/R/" + str(i + 1) po_ids.append(new_po.id) lines = requisition_line.search( - domain, - offset=i * PRODUCT_PER_PO, + domain, + offset=i * PRODUCT_PER_PO, limit=PRODUCT_PER_PO ) tax = [22] @@ -179,7 +190,7 @@ class Requisition(models.Model): self.is_po = True return po_ids - + # def create_po_from_requisition(self): # if not self.requisition_lines: # raise UserError('Tidak ada Lines, belum bisa create PO') @@ -187,7 +198,7 @@ class Requisition(models.Model): # raise UserError('Sudah pernah di create PO') # current_time = datetime.now() # vendor_ids = self.env['requisition.line'].read_group([('requisition_id', '=', self.id), ('partner_id', '!=', False)], fields=['partner_id'], groupby=['partner_id']) - + # counter_po_number = 0 # po_ids = [] # for vendor in vendor_ids: @@ -203,7 +214,7 @@ class Requisition(models.Model): # 'note_description': 'from Purchase Requisition' # } # param_requisition_line = [ - # ('requisition_id', '=', self.id), + # ('requisition_id', '=', self.id), # ('partner_id', '=', vendor['partner_id'][0]), # ('qty_purchase', '>', 0) # ] @@ -238,7 +249,7 @@ class Requisition(models.Model): # tax = [22] # param_line = { - + # 'sequence': count, # 'product_id': product.product_id.id, # 'product_qty': product.qty_purchase, @@ -251,7 +262,7 @@ class Requisition(models.Model): # new_line = self.env['purchase.order.line'].create([param_line]) # if new_po: # new_line.write({ - # 'order_id': new_po.id, + # 'order_id': new_po.id, # }) # product.current_po_id = new_po.id # product.current_po_line_id = new_line.id @@ -298,7 +309,7 @@ class RequisitionLine(models.Model): taxes = 24 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 or 24 @@ -307,7 +318,7 @@ class RequisitionLine(models.Model): #if purchase_price.taxes_system_id.type_tax_use == 'purchase': price = purchase_price.system_price taxes = purchase_price.taxes_system_id.id or 24 - + return price, taxes @api.onchange('price_unit') -- cgit v1.2.3 From 015269c0268f2cd9a38ad708c8e26bf85a79fcf3 Mon Sep 17 00:00:00 2001 From: Mqdd Date: Wed, 3 Dec 2025 09:26:03 +0700 Subject: requisition add product match in create po button --- indoteknik_custom/models/requisition.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/requisition.py b/indoteknik_custom/models/requisition.py index 39251a45..64ef4fc8 100644 --- a/indoteknik_custom/models/requisition.py +++ b/indoteknik_custom/models/requisition.py @@ -85,7 +85,7 @@ class Requisition(models.Model): ('product_id', '=', prod_line.product_id.id), ('order_id', '=', req.sale_order_id.id) ]) if match: - raise UserError ('Product sudah di SO tidak approve') + raise UserError ('Product sudah di SO tidak approve/create PO') def button_approve(self): @@ -101,6 +101,7 @@ class Requisition(models.Model): self.merchandise_approve = True def create_po_from_requisition(self): + self.check_product_line_to_so() if not self.sales_approve and not self.merchandise_approve: raise UserError('Harus Di Approve oleh Darren atau Rafly') if not self.requisition_lines: -- cgit v1.2.3