From 8bb599fc4b3e3de94fada7c277518446a88630fa Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Mon, 1 Sep 2025 15:50:14 +0700 Subject: (andri) add view unpaid invoices --- indoteknik_custom/__manifest__.py | 1 + indoteknik_custom/models/__init__.py | 3 +- indoteknik_custom/models/unpaid_invoice_view.py | 28 ++++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 3 +- indoteknik_custom/views/unpaid_invoice_view.xml | 38 +++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 indoteknik_custom/models/unpaid_invoice_view.py create mode 100644 indoteknik_custom/views/unpaid_invoice_view.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 31685005..9ebab15e 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -177,6 +177,7 @@ 'views/tukar_guling_po.xml', # 'views/refund_sale_order.xml', 'views/update_date_planned_po_wizard_view.xml', + 'views/unpaid_invoice_view.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 3a9f9312..ba3dbad9 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -156,4 +156,5 @@ from . import refund_sale_order # from . import patch from . import tukar_guling from . import tukar_guling_po -from . import update_date_planned_po_wizard \ No newline at end of file +from . import update_date_planned_po_wizard +from . import unpaid_invoice_view \ No newline at end of file diff --git a/indoteknik_custom/models/unpaid_invoice_view.py b/indoteknik_custom/models/unpaid_invoice_view.py new file mode 100644 index 00000000..77007102 --- /dev/null +++ b/indoteknik_custom/models/unpaid_invoice_view.py @@ -0,0 +1,28 @@ +from odoo import models, fields + +class UnpaidInvoiceView(models.Model): + _name = 'unpaid.invoice.view' + _description = 'Unpaid Invoices Monitoring' + _auto = False + _rec_name = 'partner_name' + + partner_id = fields.Many2one('res.partner', string='Partner') + partner_name = fields.Char(string='Partner Name') + email = fields.Char() + phone = fields.Char() + invoice_id = fields.Many2one('account.move', string='Invoice') + invoice_number = fields.Char(string='Invoice Number') + invoice_date = fields.Date() + invoice_date_due = fields.Date() + currency_id = fields.Many2one('res.currency', string='Currency') + amount_total = fields.Monetary(string='Total', currency_field='currency_id') + amount_residual = fields.Monetary(string='Residual', currency_field='currency_id') + payment_state = fields.Selection([ + ('not_paid','Not Paid'), + ('in_payment','In Payment'), + ('paid','Paid'), + ('reversed','Reversed') + ], string='Payment State') + payment_term = fields.Char() + invoice_day_to_due = fields.Integer(string="Day to Due") + new_invoice_day_to_due = fields.Integer(string="New Day Due") diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 3a320510..4649c743 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -195,4 +195,5 @@ access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,m access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizard,model_purchase_order_update_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard,access.sync.promise.date.wizard,model_sync_promise_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard_line,access.sync.promise.date.wizard.line,model_sync_promise_date_wizard_line,base.group_user,1,1,1,1 -access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 \ No newline at end of file +access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 +access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/indoteknik_custom/views/unpaid_invoice_view.xml b/indoteknik_custom/views/unpaid_invoice_view.xml new file mode 100644 index 00000000..f9c393c5 --- /dev/null +++ b/indoteknik_custom/views/unpaid_invoice_view.xml @@ -0,0 +1,38 @@ + + + + unpaid.invoice.view.tree + unpaid.invoice.view + + + + + + + + + + + + + + + + + + + Unpaid Invoices Monitoring + unpaid.invoice.view + tree,form + {} + + + + + -- cgit v1.2.3 From d839d9b4a120a2c6ab4a0b9044d578bf28cd4d47 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Mon, 1 Sep 2025 15:54:03 +0700 Subject: (andri) add badge due date --- indoteknik_custom/views/unpaid_invoice_view.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/views/unpaid_invoice_view.xml b/indoteknik_custom/views/unpaid_invoice_view.xml index f9c393c5..19cc07a6 100644 --- a/indoteknik_custom/views/unpaid_invoice_view.xml +++ b/indoteknik_custom/views/unpaid_invoice_view.xml @@ -8,7 +8,7 @@ - + -- cgit v1.2.3 From 1330742f90b32c6dd214925ad893696cfae5ef38 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Mon, 1 Sep 2025 16:05:52 +0700 Subject: (andri) add string due date --- indoteknik_custom/models/unpaid_invoice_view.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/unpaid_invoice_view.py b/indoteknik_custom/models/unpaid_invoice_view.py index 77007102..517d078b 100644 --- a/indoteknik_custom/models/unpaid_invoice_view.py +++ b/indoteknik_custom/models/unpaid_invoice_view.py @@ -5,6 +5,7 @@ class UnpaidInvoiceView(models.Model): _description = 'Unpaid Invoices Monitoring' _auto = False _rec_name = 'partner_name' + _order = 'partner_name, new_invoice_day_to_due DESC' partner_id = fields.Many2one('res.partner', string='Partner') partner_name = fields.Char(string='Partner Name') @@ -13,7 +14,7 @@ class UnpaidInvoiceView(models.Model): invoice_id = fields.Many2one('account.move', string='Invoice') invoice_number = fields.Char(string='Invoice Number') invoice_date = fields.Date() - invoice_date_due = fields.Date() + invoice_date_due = fields.Date(string='Due Date') currency_id = fields.Many2one('res.currency', string='Currency') amount_total = fields.Monetary(string='Total', currency_field='currency_id') amount_residual = fields.Monetary(string='Residual', currency_field='currency_id') -- cgit v1.2.3 From 0d0e2b9a448f6f96a7ab06ecb970dbbd2018f5fe Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 2 Sep 2025 14:19:33 +0700 Subject: (andri) fix layout dan revisi field yang dibutuhkan --- indoteknik_custom/models/unpaid_invoice_view.py | 11 +++---- indoteknik_custom/views/unpaid_invoice_view.xml | 39 +++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/indoteknik_custom/models/unpaid_invoice_view.py b/indoteknik_custom/models/unpaid_invoice_view.py index 517d078b..f6ce79b8 100644 --- a/indoteknik_custom/models/unpaid_invoice_view.py +++ b/indoteknik_custom/models/unpaid_invoice_view.py @@ -9,21 +9,22 @@ class UnpaidInvoiceView(models.Model): partner_id = fields.Many2one('res.partner', string='Partner') partner_name = fields.Char(string='Partner Name') - email = fields.Char() - phone = fields.Char() + # email = fields.Char() + # phone = fields.Char() invoice_id = fields.Many2one('account.move', string='Invoice') invoice_number = fields.Char(string='Invoice Number') invoice_date = fields.Date() invoice_date_due = fields.Date(string='Due Date') + date_terima_tukar_faktur = fields.Date(string='Terima Faktur') currency_id = fields.Many2one('res.currency', string='Currency') - amount_total = fields.Monetary(string='Total', currency_field='currency_id') - amount_residual = fields.Monetary(string='Residual', currency_field='currency_id') + amount_total = fields.Monetary(string='Total Amount', currency_field='currency_id') + amount_residual = fields.Monetary(string='Sisa Amount', currency_field='currency_id') payment_state = fields.Selection([ ('not_paid','Not Paid'), ('in_payment','In Payment'), ('paid','Paid'), ('reversed','Reversed') ], string='Payment State') - payment_term = fields.Char() + payment_term_id = fields.Many2one('account.payment.term', string='Payment Term') invoice_day_to_due = fields.Integer(string="Day to Due") new_invoice_day_to_due = fields.Integer(string="New Day Due") diff --git a/indoteknik_custom/views/unpaid_invoice_view.xml b/indoteknik_custom/views/unpaid_invoice_view.xml index 19cc07a6..0bbba60a 100644 --- a/indoteknik_custom/views/unpaid_invoice_view.xml +++ b/indoteknik_custom/views/unpaid_invoice_view.xml @@ -8,7 +8,9 @@ - + + + @@ -17,17 +19,48 @@ decoration-danger="payment_state == 'not_paid'" decoration-warning="payment_state in ('partial', 'in_payment')" decoration-success="payment_state in ('paid', 'reversed')"/> - + + + unpaid.invoice.view.form + unpaid.invoice.view + +
+ + + + + + + + + + + + + + + + + + + +
+
+
+ Unpaid Invoices Monitoring unpaid.invoice.view tree,form - {} + -- cgit v1.2.3 From a35dcc5907500e5189516459160c972bb72e1686 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 2 Sep 2025 15:04:33 +0700 Subject: (andri) menambahkan field yang dibutuhkan --- indoteknik_custom/models/unpaid_invoice_view.py | 15 ++++++++++----- indoteknik_custom/views/unpaid_invoice_view.xml | 13 +++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/indoteknik_custom/models/unpaid_invoice_view.py b/indoteknik_custom/models/unpaid_invoice_view.py index f6ce79b8..f35261eb 100644 --- a/indoteknik_custom/models/unpaid_invoice_view.py +++ b/indoteknik_custom/models/unpaid_invoice_view.py @@ -20,11 +20,16 @@ class UnpaidInvoiceView(models.Model): amount_total = fields.Monetary(string='Total Amount', currency_field='currency_id') amount_residual = fields.Monetary(string='Sisa Amount', currency_field='currency_id') payment_state = fields.Selection([ - ('not_paid','Not Paid'), - ('in_payment','In Payment'), - ('paid','Paid'), - ('reversed','Reversed') - ], string='Payment State') + ('not_paid', 'Not Paid'), + ('in_payment', 'In Payment'), + ('paid', 'Paid'), + ('partial', 'Partially Paid'), + ('reversed', 'Reversed')], string='Payment State') payment_term_id = fields.Many2one('account.payment.term', string='Payment Term') invoice_day_to_due = fields.Integer(string="Day to Due") new_invoice_day_to_due = fields.Integer(string="New Day Due") + + ref = fields.Char(string='Reference') + invoice_user_id = fields.Many2one('res.users', string='Salesperson') + date_kirim_tukar_faktur = fields.Date(string='Kirim Faktur') + sale_id = fields.Many2one('sale.order', string='Sale Order') diff --git a/indoteknik_custom/views/unpaid_invoice_view.xml b/indoteknik_custom/views/unpaid_invoice_view.xml index 0bbba60a..e898dd39 100644 --- a/indoteknik_custom/views/unpaid_invoice_view.xml +++ b/indoteknik_custom/views/unpaid_invoice_view.xml @@ -7,7 +7,9 @@ + + @@ -17,8 +19,8 @@ + decoration-warning="payment_state == 'partial'"/> +
@@ -34,18 +36,21 @@ + + + + + decoration-warning="payment_state == 'partial'"/> -- cgit v1.2.3 From d43eb7ff8ffd4b11120a7354295e86736135344a Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 2 Sep 2025 17:35:47 +0700 Subject: (andri) add menu surat piutang --- indoteknik_custom/__manifest__.py | 1 + indoteknik_custom/models/__init__.py | 3 +- indoteknik_custom/models/letter_receivable.py | 90 ++++++++++++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 4 +- indoteknik_custom/views/ir_sequence.xml | 9 +++ indoteknik_custom/views/letter_receivable.xml | 79 ++++++++++++++++++++++ 6 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 indoteknik_custom/models/letter_receivable.py create mode 100644 indoteknik_custom/views/letter_receivable.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 9ebab15e..e300670a 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -178,6 +178,7 @@ # 'views/refund_sale_order.xml', 'views/update_date_planned_po_wizard_view.xml', 'views/unpaid_invoice_view.xml', + 'views/letter_receivable.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index ba3dbad9..c8910669 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -157,4 +157,5 @@ from . import refund_sale_order from . import tukar_guling from . import tukar_guling_po from . import update_date_planned_po_wizard -from . import unpaid_invoice_view \ No newline at end of file +from . import unpaid_invoice_view +from . import letter_receivable \ No newline at end of file diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py new file mode 100644 index 00000000..541f64ff --- /dev/null +++ b/indoteknik_custom/models/letter_receivable.py @@ -0,0 +1,90 @@ +from odoo import models, fields, api + +class SuratPiutang(models.Model): + _name = "surat.piutang" + _description = "Surat Piutang" + _inherit = ['mail.thread', 'mail.activity.mixin'] + + name = fields.Char(string="Nomor Surat", readonly=True, copy=False) + partner_id = fields.Many2one("res.partner", string="Customer", required=True) + tujuan_nama = fields.Char(string="Nama Tujuan") + tujuan_email = fields.Char(string="Email Tujuan") + perihal = fields.Selection([ + ('sp1', 'Surat Peringatan Piutang'), + ('sp2', 'Surat Peringatan Piutang ke-2'), + ('sp3', 'Surat Peringatan Piutang ke-3') + ], string="Perihal", required=True, tracking=True) + line_ids = fields.One2many("surat.piutang.line", "surat_id", string="Invoice Lines") + state = fields.Selection([ + ("draft", "Draft"), + ("sent", "Sent") + ], default="draft", tracking=True) + send_date = fields.Datetime(string="Tanggal Kirim", tracking=True) + + currency_id = fields.Many2one('res.currency') + + # Grand total (total sisa semua line yang dicentang) + grand_total = fields.Monetary( + string='Total Sisa', + currency_field='currency_id', + compute='_compute_grand_total', + ) + + @api.depends('line_ids.amount_residual', 'line_ids.selected') + def _compute_grand_total(self): + for rec in self: + rec.grand_total = sum( + line.amount_residual or 0.0 for line in rec.line_ids if line.selected + ) + + @api.onchange('partner_id') + def _onchange_partner_id(self): + if self.partner_id: + invoice_lines = self.env['unpaid.invoice.view'].search( + [('partner_id', '=', self.partner_id.id)], + order='new_invoice_day_to_due asc' + ) + lines = [(0, 0, { + 'invoice_view_id': inv.id, + 'invoice_id': inv.invoice_id.id, + 'invoice_number': inv.invoice_number, + 'invoice_date': inv.invoice_date, + 'invoice_date_due': inv.invoice_date_due, + 'invoice_day_to_due': inv.invoice_day_to_due, + 'ref': inv.ref, + 'amount_residual': inv.amount_residual, + 'currency_id': inv.currency_id.id, + 'payment_term_id': inv.payment_term_id.id, + 'selected': False + }) for inv in invoice_lines] + self.line_ids = lines + + @api.model + def create(self, vals): + # Generate nomor surat otomatis + if not vals.get("name"): + seq = self.env["ir.sequence"].next_by_code("surat.piutang") or "000" + today = fields.Date.today() + 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}" + + return super().create(vals) + +class SuratPiutangLine(models.Model): + _name = 'surat.piutang.line' + _description = 'Surat Piutang Line' + + surat_id = fields.Many2one('surat.piutang', string='Surat Piutang', ondelete='cascade') + invoice_view_id = fields.Many2one('unpaid.invoice.view', string='Unpaid Invoice') + invoice_id = fields.Many2one('account.move', string='Invoice') + selected = fields.Boolean(string="Pilih", default=False) + + invoice_number = fields.Char(string='Invoice Number') + invoice_date = fields.Date(string='Invoice Date') + invoice_date_due = fields.Date(string='Due Date') + invoice_day_to_due = fields.Integer(string='Day to Due') + ref = fields.Char(string='Reference') + amount_residual = fields.Monetary(string='Amount Due Signed') + currency_id = fields.Many2one('res.currency') + payment_term_id = fields.Many2one('account.payment.term', string='Payment Terms') diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 4649c743..25273893 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -196,4 +196,6 @@ access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizar access_sync_promise_date_wizard,access.sync.promise.date.wizard,model_sync_promise_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard_line,access.sync.promise.date.wizard.line,model_sync_promise_date_wizard_line,base.group_user,1,1,1,1 access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 -access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,base.group_user,1,1,1,1 \ No newline at end of file +access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,base.group_user,1,1,1,1 +access_surat_piutang_user,surat.piutang user,model_surat_piutang,base.group_user,1,1,1,1 +access_surat_piutang_line_user,surat.piutang.line user,model_surat_piutang_line,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml index 94c2cd07..4b8fec53 100644 --- a/indoteknik_custom/views/ir_sequence.xml +++ b/indoteknik_custom/views/ir_sequence.xml @@ -228,5 +228,14 @@ 1 True + + + Surat Piutang + surat.piutang + + 3 + 1 + 1 + \ No newline at end of file diff --git a/indoteknik_custom/views/letter_receivable.xml b/indoteknik_custom/views/letter_receivable.xml new file mode 100644 index 00000000..72eae640 --- /dev/null +++ b/indoteknik_custom/views/letter_receivable.xml @@ -0,0 +1,79 @@ + + + + surat.piutang.tree + surat.piutang + + + + + + + + + + + + + + + surat.piutang.form + surat.piutang + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + Surat Piutang + + + + + + Surat Piutang + surat.piutang + tree,form + + + + +
-- cgit v1.2.3 From 1c71710dbf42106a82c0a8e30ec9cee7f452a387 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Wed, 3 Sep 2025 11:07:40 +0700 Subject: (andri) add refresh invoices agar data selalu update & fix layout form --- indoteknik_custom/models/letter_receivable.py | 61 ++++++++++++++++++++++++++- indoteknik_custom/views/letter_receivable.xml | 44 ++++++++++++++++--- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/indoteknik_custom/models/letter_receivable.py b/indoteknik_custom/models/letter_receivable.py index 541f64ff..10198fbf 100644 --- a/indoteknik_custom/models/letter_receivable.py +++ b/indoteknik_custom/models/letter_receivable.py @@ -4,19 +4,22 @@ class SuratPiutang(models.Model): _name = "surat.piutang" _description = "Surat Piutang" _inherit = ['mail.thread', 'mail.activity.mixin'] + _order = 'name desc' name = fields.Char(string="Nomor Surat", readonly=True, copy=False) partner_id = fields.Many2one("res.partner", string="Customer", required=True) tujuan_nama = fields.Char(string="Nama Tujuan") tujuan_email = fields.Char(string="Email Tujuan") perihal = fields.Selection([ - ('sp1', 'Surat Peringatan Piutang'), + ('penagihan', 'Surat Resmi Penagihan'), + ('sp1', 'Surat Peringatan Piutang ke-1'), ('sp2', 'Surat Peringatan Piutang ke-2'), ('sp3', 'Surat Peringatan Piutang ke-3') ], string="Perihal", required=True, tracking=True) line_ids = fields.One2many("surat.piutang.line", "surat_id", string="Invoice Lines") state = fields.Selection([ ("draft", "Draft"), + ("approval_pimpinan", "Menunggu Approval Pimpinan"), ("sent", "Sent") ], default="draft", tracking=True) send_date = fields.Datetime(string="Tanggal Kirim", tracking=True) @@ -59,6 +62,62 @@ class SuratPiutang(models.Model): }) for inv in invoice_lines] self.line_ids = lines + def action_refresh_lines(self): + for rec in self: + if not rec.partner_id: + continue + + # Ambil semua unpaid terbaru + invoice_views = self.env['unpaid.invoice.view'].search( + [('partner_id', '=', rec.partner_id.id)], + order='new_invoice_day_to_due asc' + ) + + existing_lines = {line.invoice_id.id: line for line in rec.line_ids} + + # Cache selected status per invoice id + selected_map = {line.invoice_id.id: line.selected for line in rec.line_ids} + + # Invoice id yang masih ada di unpaid + new_invoice_ids = invoice_views.mapped('invoice_id.id') + + for inv in invoice_views: + if inv.invoice_id.id in existing_lines: + # update line lama + line = existing_lines[inv.invoice_id.id] + line.write({ + 'invoice_view_id': inv.id, + 'invoice_number': inv.invoice_number, + 'invoice_date': inv.invoice_date, + 'invoice_date_due': inv.invoice_date_due, + 'invoice_day_to_due': inv.invoice_day_to_due, + 'ref': inv.ref, + 'amount_residual': inv.amount_residual, + 'currency_id': inv.currency_id.id, + 'payment_term_id': inv.payment_term_id.id, + 'selected': selected_map.get(inv.invoice_id.id, line.selected), + }) + else: + # preserve selected kalau pernah ada di cache + self.env['surat.piutang.line'].create({ + 'surat_id': rec.id, + 'invoice_view_id': inv.id, + 'invoice_id': inv.invoice_id.id, + 'invoice_number': inv.invoice_number, + 'invoice_date': inv.invoice_date, + 'invoice_date_due': inv.invoice_date_due, + 'invoice_day_to_due': inv.invoice_day_to_due, + 'ref': inv.ref, + 'amount_residual': inv.amount_residual, + 'currency_id': inv.currency_id.id, + 'payment_term_id': inv.payment_term_id.id, + 'selected': selected_map.get(inv.invoice_id.id, False), + }) + + # Hapus line yang tidak ada lagi di unpaid view + rec.line_ids.filtered(lambda l: l.invoice_id.id not in new_invoice_ids).unlink() + + @api.model def create(self, vals): # Generate nomor surat otomatis diff --git a/indoteknik_custom/views/letter_receivable.xml b/indoteknik_custom/views/letter_receivable.xml index 72eae640..fe60eb39 100644 --- a/indoteknik_custom/views/letter_receivable.xml +++ b/indoteknik_custom/views/letter_receivable.xml @@ -8,9 +8,12 @@ - + - + @@ -22,19 +25,48 @@
- +
+ + + +
+

+ +

+
- - - + + + +