From 7965212570e382b1fe94a96cfe16f3d2babb1d27 Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP Date: Mon, 22 Sep 2025 09:53:47 +0700 Subject: (andri) init button --- indoteknik_custom/models/approval_payment_term.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 449bd90b..fbdabe7f 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -56,6 +56,10 @@ class ApprovalPaymentTerm(models.Model): change_log_688 = fields.Text(string="Change Log", readonly=True, copy=False) + def button_closing_mail(self): + + return + def write(self, vals): # Ambil nilai lama sebelum perubahan old_values_dict = { -- cgit v1.2.3 From d32684d5d69a76c97ac962e898f3bb58f708fca4 Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP Date: Thu, 25 Sep 2025 11:06:24 +0700 Subject: (andri) penambahan perihal penutupan tempo pada surat piutang --- indoteknik_custom/models/letter_receivable.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py index 16034938..6f95e5e7 100644 --- a/indoteknik_custom/models/letter_receivable.py +++ b/indoteknik_custom/models/letter_receivable.py @@ -23,6 +23,7 @@ class SuratPiutang(models.Model): tujuan_nama = fields.Char(string="Nama Tujuan", tracking=True) tujuan_email = fields.Char(string="Email Tujuan", tracking=True) perihal = fields.Selection([ + ('tutup_tempo', 'Surat Penutupan Pembayaran Tempo'), ('penagihan', 'Surat Resmi Penagihan'), ('sp1', 'Surat Peringatan Piutang ke-1'), ('sp2', 'Surat Peringatan Piutang ke-2'), @@ -36,6 +37,7 @@ class SuratPiutang(models.Model): ("sent", "Approved & Sent") ], default="draft", tracking=True) send_date = fields.Datetime(string="Tanggal Kirim", tracking=True) + due_date = fields.Date(string="Tanggal Jatuh Tempo", tracking=True, default= fields.Date.today) seven_days_after_sent_date = fields.Char(string="7 Hari Setelah Tanggal Kirim") periode_invoices_terpilih = fields.Char( string="Periode Invoices Terpilih", @@ -228,14 +230,14 @@ class SuratPiutang(models.Model): continue # === Surat penagihan biasa (langsung Pimpinan approve) === - if rec.perihal == "penagihan": + if rec.perihal in ("tutup_tempo", "penagihan"): # if self.env.user.id not in pimpinan_user_ids: # raise UserError("Hanya Pimpinan yang boleh menyetujui surat penagihan.") rec.state = "sent" now_utc = now_wib.astimezone(pytz.UTC).replace(tzinfo=None) rec.send_date = now_utc rec.action_send_letter() - rec.message_post(body="Surat Penagihan disetujui dan berhasil dikirim.") + rec.message_post(body=f"{rec.perihal_label} disetujui dan berhasil dikirim.") self.env.user.notify_info( message=f"Surat piutang {rec.name} berhasil dikirim ke {rec.partner_id.name} ({rec.tujuan_email})", @@ -453,6 +455,18 @@ class SuratPiutang(models.Model): body=f"Line Invoices diperbarui. Total line saat ini: {len(rec.line_ids)}" ) + @api.onchange('perihal', 'partner_id') + def _onchange_perihal_tutup_tempo(self): + if self.perihal == 'tutup_tempo': + for line in self.line_ids: + if line.new_invoice_day_to_due < -30: + line.selected = True + else: + line.selected = False + else: + for line in self.line_ids: + line.selected = False + @api.model def create(self, vals): # Generate nomor surat otomatis @@ -462,7 +476,7 @@ class SuratPiutang(models.Model): bulan_romawi = ["I","II","III","IV","V","VI","VII","VIII","IX","X","XI","XII"][today.month-1] tahun = today.strftime("%y") vals["name"] = f"{seq}/LO/FAT/IDG/{bulan_romawi}/{tahun}" - if vals.get("perihal") == "penagihan": + if vals.get("perihal") in ("tutup_tempo", "penagihan"): vals["state"] = "waiting_approval_pimpinan" else: vals["state"] = "waiting_approval_sales" -- cgit v1.2.3 From 1b574687a7f4b612a1fd221da1ca920009cc963b Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP Date: Thu, 25 Sep 2025 14:33:51 +0700 Subject: (andri) make report & mail template close tempo --- indoteknik_custom/models/letter_receivable.py | 145 +++++++++++++++----------- 1 file changed, 83 insertions(+), 62 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py index 6f95e5e7..bfa1e966 100644 --- a/indoteknik_custom/models/letter_receivable.py +++ b/indoteknik_custom/models/letter_receivable.py @@ -244,6 +244,13 @@ class SuratPiutang(models.Model): title="Informasi", sticky=False ) + + def action_print(self): + self.ensure_one() + if self.perihal == 'tutup_tempo': + return self.env.ref('indoteknik_custom.action_report_surat_tutup_tempo').report_action(self) + else: + return self.env.ref('indoteknik_custom.action_report_surat_piutang').report_action(self) def action_send_letter(self): self.ensure_one() @@ -255,64 +262,79 @@ class SuratPiutang(models.Model): if not self.tujuan_email: raise UserError(_("Email tujuan harus diisi.")) - template = self.env.ref('indoteknik_custom.letter_receivable_mail_template') - # today = fields.Date.today() - - month_map = { - 1: "Januari", 2: "Februari", 3: "Maret", 4: "April", - 5: "Mei", 6: "Juni", 7: "Juli", 8: "Agustus", - 9: "September", 10: "Oktober", 11: "November", 12: "Desember", - } - target_date = (self.send_date or fields.Datetime.now()).date() + timedelta(days=7) - self.seven_days_after_sent_date = f"{target_date.day} {month_map[target_date.month]}" - - perihal_map = { - 'penagihan': 'Surat Resmi Penagihan', - 'sp1': 'Surat Peringatan Pertama (I)', - 'sp2': 'Surat Peringatan Kedua (II)', - 'sp3': 'Surat Peringatan Ketiga (III)', - } - perihal_text = perihal_map.get(self.perihal, self.perihal or '') - - invoice_table_rows = "" - grand_total = 0 - for line in selected_lines: - # days_to_due = (line.invoice_date_due - today).days if line.invoice_date_due else 0 - grand_total += line.amount_residual - invoice_table_rows += f""" - - {line.invoice_number or '-'} - {self.partner_id.name or '-'} - {fields.Date.to_string(line.invoice_date) or '-'} - {fields.Date.to_string(line.invoice_date_due) or '-'} - {line.new_invoice_day_to_due} - {line.ref or '-'} - {formatLang(self.env, line.amount_residual, currency_obj=line.currency_id)} - {line.payment_term_id.name or '-'} - - """ - - invoice_table_footer = f""" - - - Grand Total - {formatLang(self.env, grand_total, currency_obj=self.currency_id, monetary=True)} - + template = None + report = None + body_html = None + subject = None + + # Logika untuk memilih template dan report berdasarkan 'perihal' + if self.perihal == 'tutup_tempo': + template = self.env.ref('indoteknik_custom.close_tempo_mail_template') + report = self.env.ref('indoteknik_custom.action_report_surat_tutup_tempo') + due_date_str = self.due_date.strftime('%d %B %Y') if self.due_date else 'yang telah ditentukan' + body_html = template.body_html \ + .replace('${object.partner_id.name}', self.partner_id.name or '') \ + .replace('${object.due_date}', due_date_str or '') + subject = f"Pemberitahuan Penutupan Pembayaran Tempo – {self.partner_id.name}" + else: + template = self.env.ref('indoteknik_custom.letter_receivable_mail_template') + + month_map = { + 1: "Januari", 2: "Februari", 3: "Maret", 4: "April", + 5: "Mei", 6: "Juni", 7: "Juli", 8: "Agustus", + 9: "September", 10: "Oktober", 11: "November", 12: "Desember", + } + target_date = (self.send_date or fields.Datetime.now()).date() + timedelta(days=7) + self.seven_days_after_sent_date = f"{target_date.day} {month_map[target_date.month]}" + + perihal_map = { + 'penagihan': 'Surat Resmi Penagihan', + 'sp1': 'Surat Peringatan Pertama (I)', + 'sp2': 'Surat Peringatan Kedua (II)', + 'sp3': 'Surat Peringatan Ketiga (III)', + } + perihal_text = perihal_map.get(self.perihal, self.perihal or '') + + invoice_table_rows = "" + grand_total = 0 + for line in selected_lines: + grand_total += line.amount_residual + invoice_table_rows += f""" + + {line.invoice_number or '-'} + {self.partner_id.name or '-'} + {fields.Date.to_string(line.invoice_date) or '-'} + {fields.Date.to_string(line.invoice_date_due) or '-'} + {line.new_invoice_day_to_due} + {line.ref or '-'} + {formatLang(self.env, line.amount_residual, currency_obj=line.currency_id)} + {line.payment_term_id.name or '-'} - - """ - # inject table rows ke template - body_html = re.sub( - r"]*>.*?", - f"{invoice_table_rows}{invoice_table_footer}", - template.body_html, - flags=re.DOTALL - ).replace('${object.name}', self.name or '') \ - .replace('${object.partner_id.name}', self.partner_id.name or '') \ - .replace('${object.seven_days_after_sent_date}', self.seven_days_after_sent_date or '') \ - .replace('${object.perihal}', perihal_text or '') - - report = self.env.ref('indoteknik_custom.action_report_surat_piutang') + """ + + invoice_table_footer = f""" + + + Grand Total + {formatLang(self.env, grand_total, currency_obj=self.currency_id, monetary=True)} + + + + """ + + body_html = re.sub( + r"]*>.*?", + f"{invoice_table_rows}{invoice_table_footer}", + template.body_html, + flags=re.DOTALL + ).replace('${object.name}', self.name or '') \ + .replace('${object.partner_id.name}', self.partner_id.name or '') \ + .replace('${object.seven_days_after_sent_date}', self.seven_days_after_sent_date or '') \ + .replace('${object.perihal}', perihal_text or '') + + report = self.env.ref('indoteknik_custom.action_report_surat_piutang') + subject = perihal_map.get(self.perihal, self.perihal or '') + " - " + (self.partner_id.name or '') + pdf_content, _ = report._render_qweb_pdf([self.id]) attachment_base64 = base64.b64encode(pdf_content) @@ -337,14 +359,13 @@ class SuratPiutang(models.Model): cc_list.append(sales_email) values = { - # 'subject': template.subject.replace('${object.name}', self.name or ''), - 'subject': perihal_map.get(self.perihal, self.perihal or '') + " - " + (self.partner_id.name or ''), + 'subject': subject, # Menggunakan subject yang sudah ditentukan di atas 'email_to': self.tujuan_email, 'email_from': 'finance@indoteknik.co.id', - 'email_cc': ",".join(sorted(set(cc_list))), - 'body_html': body_html, + # 'email_cc': ",".join(sorted(set(cc_list))), + 'body_html': body_html, # Menggunakan body_html yang sudah ditentukan di atas 'attachments': [(attachment.name, attachment.datas)], - 'reply_to': 'finance@indoteknik.co.id', + # 'reply_to': 'finance@indoteknik.co.id', } template.with_context(mail_post_autofollow=False).send_mail( -- cgit v1.2.3 From 31a22f2f26b29f91bd43ea48ce84e8dc9aaf3c12 Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP Date: Thu, 25 Sep 2025 15:35:43 +0700 Subject: fix --- indoteknik_custom/models/letter_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py index bfa1e966..ffe14491 100644 --- a/indoteknik_custom/models/letter_receivable.py +++ b/indoteknik_custom/models/letter_receivable.py @@ -375,7 +375,7 @@ class SuratPiutang(models.Model): ) _logger.info( - f"Surat Piutang {self.name} terkirim ke {self.tujuan_email} " + f"{self.name} terkirim ke {self.tujuan_email} " f"({self.partner_id.name}), total {len(selected_lines)} invoice." ) -- cgit v1.2.3 From 6239b00631bd709557349d8d3635001659b83d93 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 29 Sep 2025 15:17:43 +0700 Subject: push --- indoteknik_custom/models/stock_picking.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index b27e6b5d..ae4f64a8 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -152,6 +152,7 @@ class StockPicking(models.Model): state_reserve = fields.Selection([ ('waiting', 'Waiting For Fullfilment'), ('ready', 'Ready to Ship'), + ('partial', 'Ready to Ship Partial'), ('done', 'Done'), ('cancel', 'Cancelled'), ], string='Status Reserve', tracking=True, copy=False, help="The current state of the stock picking.") @@ -393,7 +394,7 @@ class StockPicking(models.Model): deadline = kirim_date + timedelta(days=1) deadline = deadline.replace(hour=10, minute=0, second=0) - if now > deadline: + if now > deadline and not self.so_lama: raise ValidationError( _("Anda tidak dapat mengubah Tanggal Kirim setelah jam 10:00 pada hari berikutnya!") ) -- cgit v1.2.3 From a66344ded40391a3a2591581141d2d44ed1ad712 Mon Sep 17 00:00:00 2001 From: FIN-IT_AndriFP Date: Mon, 29 Sep 2025 16:07:26 +0700 Subject: (andri) del --- indoteknik_custom/models/approval_payment_term.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index fbdabe7f..e45305db 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -56,9 +56,6 @@ class ApprovalPaymentTerm(models.Model): change_log_688 = fields.Text(string="Change Log", readonly=True, copy=False) - def button_closing_mail(self): - - return def write(self, vals): # Ambil nilai lama sebelum perubahan -- cgit v1.2.3 From 1f58d7d4973edf04d6a3f3092115492585c1545b Mon Sep 17 00:00:00 2001 From: Miqdad Date: Tue, 30 Sep 2025 08:09:02 +0700 Subject: Need approval logistic when IU from BU/Stock --- indoteknik_custom/models/stock_picking.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index b27e6b5d..51f4cccd 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -97,6 +97,7 @@ class StockPicking(models.Model): approval_status = fields.Selection([ ('pengajuan1', 'Approval Accounting'), + ('pengajuan2', 'Approval Logistic'), ('approved', 'Approved'), ], string='Approval Status', readonly=True, copy=False, index=True, tracking=3, help="Approval Status untuk Internal Use") @@ -1082,6 +1083,10 @@ class StockPicking(models.Model): def ask_approval(self): if self.env.user.is_accounting: raise UserError("Bisa langsung Validate") + if self.env.user.is_logistic_approver and self.location_id.id == 57 or self.location_id== 57: + raise UserError("Bisa langsung Validate") + + # for calendar distribute only # if self.is_internal_use: @@ -1104,6 +1109,9 @@ class StockPicking(models.Model): if line.qty_done <= 0: raise UserError("Qty tidak boleh 0") pick.approval_status = 'pengajuan1' + if pick.location_id.id == 57: + pick.approval_status = 'pengajuan2' + return def ask_receipt_approval(self): if self.env.user.is_logistic_approver: @@ -1306,6 +1314,9 @@ class StockPicking(models.Model): if self.picking_type_id.code == 'incoming' and self.group_id.id == False and self.is_internal_use == False: raise UserError(_('Tidak bisa Validate jika tidak dari Document SO / PO')) + if self.is_internal_use and not self.env.user.is_logistic_approver and self.location_id.id == 57: + raise UserError("Harus di Approve oleh Logistik") + if self.is_internal_use and not self.env.user.is_accounting: raise UserError("Harus di Approve oleh Accounting") @@ -1348,6 +1359,9 @@ class StockPicking(models.Model): ) self.validation_minus_onhand_quantity() + loc = self.location_id + if loc.id == 57 and not self.env.user.is_logistic_approver and self.approval_status in ['pengajuan2']: + raise UserError ("Harus Ask Approval Logistik") self.responsible = self.env.user.id # self.send_koli_to_so() if self.picking_type_code == 'outgoing' and 'BU/OUT/' in self.name: -- cgit v1.2.3 From e92f83f5938966aa6b171be3743ea853d1cffdc7 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Tue, 30 Sep 2025 13:46:42 +0700 Subject: remove p putra from appove user pengajuan request tempo --- indoteknik_custom/models/user_pengajuan_tempo_request.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/user_pengajuan_tempo_request.py b/indoteknik_custom/models/user_pengajuan_tempo_request.py index 600381c0..8ed92fc8 100644 --- a/indoteknik_custom/models/user_pengajuan_tempo_request.py +++ b/indoteknik_custom/models/user_pengajuan_tempo_request.py @@ -381,7 +381,8 @@ class UserPengajuanTempoRequest(models.Model): if tempo.env.user.id in (688, 28, 7): raise UserError("Pengajuan tempo harus di approve oleh sales manager terlebih dahulu") else: - if tempo.env.user.id not in (375, 19): + # if tempo.env.user.id not in (375, 19): + if tempo.env.user.id != 19: # if tempo.env.user.id != 12182: raise UserError("Pengajuan tempo hanya bisa di approve oleh sales manager") else: -- cgit v1.2.3 From ae360ebbe575c5ede395b0b396b9627b89b0e226 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 2 Oct 2025 13:53:42 +0700 Subject: fix bug --- indoteknik_custom/models/stock_picking.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 16e235da..ae7121da 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -2552,9 +2552,22 @@ class ScanKoli(models.Model): out_moves = self.env['stock.move.line'].search([('picking_id', '=', picking.linked_out_picking_id.id)]) for pick_move in pick_moves: - corresponding_out_move = out_moves.filtered(lambda m: m.product_id == pick_move.product_id) - if corresponding_out_move: - corresponding_out_move.qty_done += pick_move.qty_done + corresponding_out_moves = out_moves.filtered(lambda m: m.product_id == pick_move.product_id) + + if len(corresponding_out_moves) == 1: + corresponding_out_moves.qty_done += pick_move.qty_done + + elif len(corresponding_out_moves) > 1: + qty_koli = pick_move.qty_done + for out_move in corresponding_out_moves: + if qty_koli <= 0: + break + # ambil sesuai kebutuhan atau sisa qty + qty_to_assign = min(qty_koli, out_move.product_uom_qty) + out_move.qty_done += qty_to_assign + qty_koli -= qty_to_assign + + def _reset_qty_done_if_no_scan(self, picking_id): product_bu_pick = self.env['stock.move.line'].search([('picking_id', '=', picking_id)]) -- cgit v1.2.3 From 6baf4d55e6dbaef2f5bd270a18effa55a821677a Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 2 Oct 2025 14:45:43 +0700 Subject: push --- indoteknik_custom/models/mrp_production.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index b39995b5..4ebfa244 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -21,6 +21,21 @@ class MrpProduction(models.Model): ], 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) + def action_cancel(self): + for production in self: + moves_with_forecast = production.move_raw_ids.filtered( + lambda m: m.forecast_availability > 0 + ) + if moves_with_forecast: + # bikin list produk per baris + product_list = "\n".join( + "- %s" % p.display_name for p in moves_with_forecast.mapped('product_id') + ) + raise UserError(_( + "You cannot cancel this Manufacturing Order because the following raw materials " + "still have forecast availability:\n\n%s" % product_list + )) + return super(MrpProduction, self).action_cancel() @api.constrains('check_bom_product_lines') def constrains_check_bom_product_lines(self): -- cgit v1.2.3 From 67294c9cacdf2e4da1348c41cb23a02d50aea374 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 2 Oct 2025 15:38:34 +0700 Subject: fixb ug --- indoteknik_custom/models/mrp_production.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 4ebfa244..30956082 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -24,8 +24,9 @@ class MrpProduction(models.Model): def action_cancel(self): for production in self: moves_with_forecast = production.move_raw_ids.filtered( - lambda m: m.forecast_availability > 0 + lambda m: m.reserved_availability > 0 ) + if moves_with_forecast: # bikin list produk per baris product_list = "\n".join( -- cgit v1.2.3 From 35d01765f9b925467b6ac20d2ff83c81f49e4d3e Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 2 Oct 2025 16:03:44 +0700 Subject: fix cannot apply voucher when cart has promotion item --- indoteknik_custom/models/sale_order.py | 65 +++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 663cba58..3aaae12d 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -2871,6 +2871,7 @@ class SaleOrder(models.Model): def action_apply_voucher(self): for line in self.order_line: if line.order_promotion_id: + _logger.warning(f"[CHECKOUT FAILED] Produk promo ditemukan: {line.product_id.display_name}") raise UserError('Voucher tidak dapat digabung dengan promotion program') voucher = self.voucher_id @@ -2913,42 +2914,82 @@ class SaleOrder(models.Model): self.apply_voucher_shipping() def apply_voucher(self): + def _is_promo_line(line): + # TRUE jika baris tidak boleh kena voucher + if getattr(line, 'order_promotion_id', False): + return True # baris dari program promo + if (line.price_unit or 0.0) == 0.0: + return True # free item + if getattr(line, 'is_has_disc', False): + return True # sudah promo/flashsale/berdiskon + if (line.discount or 0.0) >= 100.0: + return True # safety + return False + + # --- LOOP 1: susun input untuk voucher.apply() --- order_line = [] for line in self.order_line: + if _is_promo_line(line): + continue order_line.append({ 'product_id': line.product_id, 'price': line.price_unit, 'discount': line.discount, 'qty': line.product_uom_qty, - 'subtotal': line.price_subtotal + 'subtotal': line.price_subtotal, }) + + if not order_line: + return + voucher = self.voucher_id.apply(order_line) + # --- LOOP 2: tulis hasilnya HANYA ke non-promo --- for line in self.order_line: + if _is_promo_line(line): + continue + line.initial_discount = line.discount voucher_type = voucher['type'] - used_total = voucher['total'][voucher_type] - used_discount = voucher['discount'][voucher_type] + total_map = voucher['total'][voucher_type] + discount_map = voucher['discount'][voucher_type] - manufacture_id = line.product_id.x_manufacture.id if voucher_type == 'brand': - used_total = used_total.get(manufacture_id) - used_discount = used_discount.get(manufacture_id) + m_id = line.product_id.x_manufacture.id + used_total = (total_map or {}).get(m_id) + used_discount = (discount_map or {}).get(m_id) + else: + used_total = total_map + used_discount = discount_map - if not used_total or not used_discount: + if not used_total or not used_discount or (line.product_uom_qty or 0.0) == 0.0: continue line_contribution = line.price_subtotal / used_total line_voucher = used_discount * line_contribution - line_voucher_item = line_voucher / line.product_uom_qty + per_item_voucher = line_voucher / line.product_uom_qty - line_price_unit = line.price_unit / 1.11 if any(tax.id == 23 for tax in line.tax_id) else line.price_unit - line_discount_item = line_price_unit * line.discount / 100 + line_voucher_item - line_voucher_item = line_discount_item / line_price_unit * 100 + has_ppn_11 = any(tax.id == 23 for tax in line.tax_id) + base_unit = line.price_unit / 1.11 if has_ppn_11 else line.price_unit + + new_disc_value = base_unit * line.discount / 100 + per_item_voucher + new_disc_pct = (new_disc_value / base_unit) * 100 line.amount_voucher_disc = line_voucher - line.discount = line_voucher_item + line.discount = new_disc_pct + + _logger.info( + "[VOUCHER_APPLIED] SO=%s voucher=%s type=%s line_id=%s product=%s qty=%s discount_pct=%.2f amount_voucher=%s", + self.name, + getattr(self.voucher_id, "code", None), + voucher.get("type"), + line.id, + line.product_id.display_name, + line.product_uom_qty, + line.discount, + line.amount_voucher_disc, + ) self.amount_voucher_disc = voucher['discount']['all'] self.applied_voucher_id = self.voucher_id -- cgit v1.2.3 From 6dda561fa704add3be34ecb16fa44e72fcf1bf56 Mon Sep 17 00:00:00 2001 From: HafidBuroiroh Date: Fri, 3 Oct 2025 09:44:09 +0700 Subject: push --- indoteknik_custom/models/refund_sale_order.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index de9870f6..a866af6e 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -571,7 +571,9 @@ class RefundSaleOrder(models.Model): domain = [ ('journal_id', '=', 11), ('state', '=', 'posted'), - ('ref', 'ilike', 'dp') + '|', + ('ref', 'ilike', 'dp'), + ('ref', 'ilike', 'payment'), ] domain += ['|'] * (len(so_names) - 1) for n in so_names: -- cgit v1.2.3 From d3fc7f9dfbd3df9687c9531813ac59c3318c6b43 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 6 Oct 2025 09:08:31 +0700 Subject: rollback --- indoteknik_custom/models/stock_picking.py | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'indoteknik_custom/models') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index ae7121da..0b91e79d 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1080,14 +1080,9 @@ class StockPicking(models.Model): return res - def ask_approval(self): if self.env.user.is_accounting: raise UserError("Bisa langsung Validate") - if self.env.user.is_logistic_approver and self.location_id.id == 57 or self.location_id== 57: - raise UserError("Bisa langsung Validate") - - # for calendar distribute only # if self.is_internal_use: @@ -1110,9 +1105,6 @@ class StockPicking(models.Model): if line.qty_done <= 0: raise UserError("Qty tidak boleh 0") pick.approval_status = 'pengajuan1' - if pick.location_id.id == 57: - pick.approval_status = 'pengajuan2' - return def ask_receipt_approval(self): if self.env.user.is_logistic_approver: @@ -1315,9 +1307,6 @@ class StockPicking(models.Model): if self.picking_type_id.code == 'incoming' and self.group_id.id == False and self.is_internal_use == False: raise UserError(_('Tidak bisa Validate jika tidak dari Document SO / PO')) - if self.is_internal_use and not self.env.user.is_logistic_approver and self.location_id.id == 57: - raise UserError("Harus di Approve oleh Logistik") - if self.is_internal_use and not self.env.user.is_accounting: raise UserError("Harus di Approve oleh Accounting") @@ -1344,7 +1333,6 @@ class StockPicking(models.Model): current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.date_reserved = current_time - # Validate Qty Demand Can't higher than Qty Product if self.location_dest_id.id == 58 and 'BU/INPUT/' in self.name: for move in self.move_ids_without_package: @@ -1360,22 +1348,19 @@ class StockPicking(models.Model): ) self.validation_minus_onhand_quantity() - loc = self.location_id - if loc.id == 57 and not self.env.user.is_logistic_approver and self.approval_status in ['pengajuan2']: - raise UserError ("Harus Ask Approval Logistik") self.responsible = self.env.user.id # self.send_koli_to_so() if self.picking_type_code == 'outgoing' and 'BU/OUT/' in self.name: self.check_koli() res = super(StockPicking, self).button_validate() - + # Penambahan link PO di Stock Journal untuk Picking BD for picking in self: if picking.name and 'BD/' in picking.name and picking.purchase_id: stock_journal = self.env['account.move'].search([ ('ref', 'ilike', picking.name + '%'), - ('journal_id', '=', 3) # Stock Journal ID - ], limit = 1) + ('journal_id', '=', 3) # Stock Journal ID + ], limit=1) if stock_journal: stock_journal.write({ 'purchase_order_id': picking.purchase_id.id -- cgit v1.2.3