From dde108ba7e3690b0ef655fe7449814e9021bab74 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Wed, 20 Aug 2025 09:58:00 +0700 Subject: (andri) add field janji bayar & button sync ke inv customer dengan due date yang sama --- indoteknik_custom/models/account_move.py | 48 +++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index b0ffd8b9..3a07cf87 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -99,6 +99,12 @@ class AccountMove(models.Model): reminder_sent_date = fields.Date(string="Tanggal Reminder Terkirim") + customer_promise_date = fields.Date( + string="Janji Bayar", + help="Tanggal janji bayar dari customer setelah reminder dikirim.", + tracking=True + ) + def compute_partial_payment(self): for move in self: if move.amount_total_signed > 0 and move.amount_residual_signed > 0 and move.payment_state == 'partial': @@ -121,6 +127,46 @@ class AccountMove(models.Model): else: move.payment_date = False + def action_sync_promise_date(self): + for inv in self: + if not inv.customer_promise_date: + inv.env.user.notify_warning( + message="Isi Janji Bayar terlebih dahulu sebelum melakukan sinkronisasi.", + title="Sync Gagal", + ) + continue + + # Cari invoice lain milik partner yang due date sama + other_invoices = self.search([ + ('id', '!=', inv.id), + ('partner_id', '=', inv.partner_id.id), + ('invoice_date_due', '=', inv.invoice_date_due), + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ]) + + if not other_invoices: + inv.env.user.notify_info( + message="Tidak ada invoice lain dengan due date yang sama untuk disinkronkan.", + title="Sync Janji Bayar", + ) + continue + + # Sync field + other_invoices.write({'customer_promise_date': inv.customer_promise_date}) + + # Log di invoices lain + for other in other_invoices: + other.message_post( + body=f"Janji Bayar {inv.customer_promise_date} disinkronkan dari invoice {inv.name}." + ) + + # Log di invoice asal + other_names = ", ".join(other_invoices.mapped("name")) + inv.message_post( + body=f"Janji Bayar {inv.customer_promise_date} disinkronkan ke {len(other_invoices)} invoice lain: {other_names}." + ) + def send_due_invoice_reminder(self): today = fields.Date.today() @@ -279,7 +325,7 @@ class AccountMove(models.Model): } _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") - template.send_mail(invs[0].id, force_send=True, email_values=values) + # template.send_mail(invs[0].id, force_send=True, email_values=values) # flag invs.write({'reminder_sent_date': today}) # Post ke chatter -- cgit v1.2.3 From caaef86e4c60f026a2b2b7abcad355f2d18366c3 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Wed, 20 Aug 2025 10:10:03 +0700 Subject: (andri) add flag janji bayar di send mail reminder --- indoteknik_custom/models/account_move.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 3a07cf87..e5e68146 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -214,6 +214,15 @@ class AccountMove(models.Model): _logger.info(f"Reminder untuk {partner.name} sudah terkirim hari ini, skip.") continue + promise_dates = [inv.customer_promise_date for inv in invs if inv.customer_promise_date] + if promise_dates: + earliest_promise = min(promise_dates) # ambil janji paling awal + if today <= earliest_promise: + _logger.info( + f"Skip reminder untuk {partner.name} karena ada Janji Bayar sampai {earliest_promise}" + ) + continue + # Ambil child contact yang di-checklist reminder_invoices reminder_contacts = self.env['res.partner'].search([ ('parent_id', '=', partner.id), @@ -325,7 +334,7 @@ class AccountMove(models.Model): } _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") - # template.send_mail(invs[0].id, force_send=True, email_values=values) + template.send_mail(invs[0].id, force_send=True, email_values=values) # flag invs.write({'reminder_sent_date': today}) # Post ke chatter -- cgit v1.2.3 From 3b19e1ad701ddd8ab5d7d226a1776d857451b078 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 21 Aug 2025 09:10:57 +0700 Subject: (andri) fix --- indoteknik_custom/models/account_move.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index b0ffd8b9..bda9101d 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -278,8 +278,8 @@ class AccountMove(models.Model): 'reply_to': 'finance@indoteknik.co.id', } - _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") template.send_mail(invs[0].id, force_send=True, email_values=values) + _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") # flag invs.write({'reminder_sent_date': today}) # Post ke chatter -- cgit v1.2.3 From ebec9f8f1404d19e145b9d5c4218779faf9263e5 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 21 Aug 2025 11:07:57 +0700 Subject: (andri) add wizard sync janji bayar --- indoteknik_custom/models/account_move.py | 133 ++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 38 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index e5e68146..6713e87c 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -128,45 +128,35 @@ class AccountMove(models.Model): move.payment_date = False def action_sync_promise_date(self): - for inv in self: - if not inv.customer_promise_date: - inv.env.user.notify_warning( - message="Isi Janji Bayar terlebih dahulu sebelum melakukan sinkronisasi.", - title="Sync Gagal", - ) - continue - - # Cari invoice lain milik partner yang due date sama - other_invoices = self.search([ - ('id', '!=', inv.id), - ('partner_id', '=', inv.partner_id.id), - ('invoice_date_due', '=', inv.invoice_date_due), - ('move_type', '=', 'out_invoice'), - ('state', '=', 'posted'), - ]) - - if not other_invoices: - inv.env.user.notify_info( - message="Tidak ada invoice lain dengan due date yang sama untuk disinkronkan.", - title="Sync Janji Bayar", - ) - continue - - # Sync field - other_invoices.write({'customer_promise_date': inv.customer_promise_date}) - - # Log di invoices lain - for other in other_invoices: - other.message_post( - body=f"Janji Bayar {inv.customer_promise_date} disinkronkan dari invoice {inv.name}." - ) + self.ensure_one() + if not self.customer_promise_date: + raise UserError("Isi Janji Bayar terlebih dahulu sebelum melakukan sinkronisasi.") + + other_invoices = self.env['account.move'].search([ + ('id', '!=', self.id), + ('partner_id', '=', self.partner_id.id), + ('invoice_date_due', '=', self.invoice_date_due), + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('date_terima_tukar_faktur', '!=', False) + ]) + lines = [] + for inv in other_invoices: + lines.append((0, 0, {'invoice_id': inv.id, 'sync_check': True})) # default dicentang semua - # Log di invoice asal - other_names = ", ".join(other_invoices.mapped("name")) - inv.message_post( - body=f"Janji Bayar {inv.customer_promise_date} disinkronkan ke {len(other_invoices)} invoice lain: {other_names}." - ) + wizard = self.env['sync.promise.date.wizard'].create({ + 'invoice_id': self.id, + 'line_ids': lines, + }) + return { + 'name': 'Sync Janji Bayar', + 'type': 'ir.actions.act_window', + 'res_model': 'sync.promise.date.wizard', + 'view_mode': 'form', + 'res_id': wizard.id, + 'target': 'new', + } def send_due_invoice_reminder(self): today = fields.Date.today() @@ -744,4 +734,71 @@ class AccountMove(models.Model): 'date_efaktur_exported': datetime.utcnow(), }) - return response \ No newline at end of file + return response + +class SyncPromiseDateWizard(models.TransientModel): + _name = "sync.promise.date.wizard" + _description = "Sync Janji Bayar Wizard" + + invoice_id = fields.Many2one('account.move', string="Invoice Utama", required=True) + promise_date = fields.Date(string="Janji Bayar", related="invoice_id.customer_promise_date", readonly=True) + line_ids = fields.One2many('sync.promise.date.wizard.line', 'wizard_id', string="Invoices Terkait") + + def action_check_all(self): + for line in self.line_ids: + line.sync_check = True + return { + 'type': 'ir.actions.act_window', + 'res_model': 'sync.promise.date.wizard', + 'view_mode': 'form', + 'res_id': self.id, + 'target': 'new', + } + + def action_uncheck_all(self): + for line in self.line_ids: + line.sync_check = False + return { + 'type': 'ir.actions.act_window', + 'res_model': 'sync.promise.date.wizard', + 'view_mode': 'form', + 'res_id': self.id, + 'target': 'new', + } + + def action_confirm(self): + self.ensure_one() + selected_lines = self.line_ids.filtered(lambda l: l.sync_check) + selected_invoices = selected_lines.mapped('invoice_id') + + if not selected_invoices: + raise UserError("Tidak ada invoice dipilih untuk sinkronisasi.") + + # Update hanya invoice yang dipilih + for inv in selected_invoices: + inv.write({'customer_promise_date': self.promise_date}) + inv.message_post( + body=f"Janji Bayar {self.promise_date} disinkronkan dari invoice {self.invoice_id.name}." + ) + + # Log di invoice utama + self.invoice_id.message_post( + body=f"Janji Bayar {self.promise_date} disinkronkan ke {len(selected_invoices)} invoice lain: {', '.join(selected_invoices.mapped('name'))}." + ) + return {'type': 'ir.actions.act_window_close'} + + +class SyncPromiseDateWizardLine(models.TransientModel): + _name = "sync.promise.date.wizard.line" + _description = "Sync Janji Bayar Wizard Line" + + wizard_id = fields.Many2one('sync.promise.date.wizard', string="Wizard") + invoice_id = fields.Many2one('account.move', string="Invoice") + sync_check = fields.Boolean(string="Sync?") + invoice_name = fields.Char(related="invoice_id.name", string="Nomor Invoice", readonly=True) + invoice_date_due = fields.Date(related="invoice_id.invoice_date_due", string="Due Date", readonly=True) + invoice_day_to_due = fields.Integer(related="invoice_id.invoice_day_to_due", string="Day to Due", readonly=True) + new_invoice_day_to_due = fields.Integer(related="invoice_id.new_invoice_day_to_due", string="New Day Due", readonly=True) + date_terima_tukar_faktur = fields.Date(related="invoice_id.date_terima_tukar_faktur", string="Tanggal Terima Tukar Faktur", readonly=True) + amount_total = fields.Monetary(related="invoice_id.amount_total", string="Total", readonly=True) + currency_id = fields.Many2one(related="invoice_id.currency_id", readonly=True) \ No newline at end of file -- cgit v1.2.3 From 80ed075e95d915f00c1abd0cde456516db439373 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 21 Aug 2025 13:06:43 +0700 Subject: (andri) fix --- indoteknik_custom/models/account_move.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index bda9101d..94774f0f 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -280,6 +280,7 @@ class AccountMove(models.Model): template.send_mail(invs[0].id, force_send=True, email_values=values) _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") + _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag invs.write({'reminder_sent_date': today}) # Post ke chatter @@ -293,7 +294,6 @@ class AccountMove(models.Model): author_id=system_id, ) - _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") @api.onchange('invoice_date') -- cgit v1.2.3 From 3f28815704346d81e42ea03a95f591ef1131a622 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 21 Aug 2025 22:31:53 +0700 Subject: (andri) add flag dont send parent & all untuk reminder inv tempo --- indoteknik_custom/models/account_move.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index e09f9c5c..a211d739 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -213,6 +213,15 @@ class AccountMove(models.Model): ) continue + emails = [] + # skip semua jika partner centang dont_send_reminder_inv_all + if partner.dont_send_reminder_inv_all: + _logger.info(f"Partner {partner.name} skip karena dont_send_reminder_inv_all aktif") + continue + # cek parent hanya dengan flag dont_sent_reminder_inv_parent + if not partner.dont_sent_reminder_inv_parent and partner.email: + emails.append(partner.email) + # Ambil child contact yang di-checklist reminder_invoices reminder_contacts = self.env['res.partner'].search([ ('parent_id', '=', partner.id), @@ -220,12 +229,8 @@ class AccountMove(models.Model): ('email', '!=', False), ]) _logger.info(f"Email Reminder Child {reminder_contacts}") - - # if not reminder_contacts: - # _logger.info(f"Partner {partner.name} tidak memiliki email yang sudah ceklis reminder") - # continue - - emails = list(filter(None, [partner.email])) + reminder_contacts.mapped('email') + + emails += reminder_contacts.mapped('email') if reminder_contacts: _logger.info(f"Email Reminder Child {reminder_contacts}") else: -- cgit v1.2.3 From 70a2b42b40932936bb0cf194005c9523ebd8a9df Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 21 Aug 2025 23:05:24 +0700 Subject: (andri) fix typo --- indoteknik_custom/models/account_move.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index a211d739..8493bb24 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -219,7 +219,7 @@ class AccountMove(models.Model): _logger.info(f"Partner {partner.name} skip karena dont_send_reminder_inv_all aktif") continue # cek parent hanya dengan flag dont_sent_reminder_inv_parent - if not partner.dont_sent_reminder_inv_parent and partner.email: + if not partner.dont_send_reminder_inv_parent and partner.email: emails.append(partner.email) # Ambil child contact yang di-checklist reminder_invoices -- cgit v1.2.3 From dab315df817429db7a8445f4dd08c9722e4d328a Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Fri, 22 Aug 2025 08:20:42 +0700 Subject: (andri) sync promise date hanya untuk User Finance --- indoteknik_custom/models/account_move.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 8493bb24..599b3220 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -129,6 +129,9 @@ class AccountMove(models.Model): def action_sync_promise_date(self): self.ensure_one() + finance_user_ids = [688] + if self.env.user.id not in finance_user_ids: + raise UserError('Hanya Finance (Widya) yang dapat menggunakan fitur ini.') if not self.customer_promise_date: raise UserError("Isi Janji Bayar terlebih dahulu sebelum melakukan sinkronisasi.") @@ -177,7 +180,7 @@ class AccountMove(models.Model): ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('invoice_date_due', 'in', target_dates), ('date_terima_tukar_faktur', '!=', False) - ]) + ], limit=5) _logger.info(f"Invoices: {invoices}") invoices = invoices.filtered( @@ -328,7 +331,7 @@ class AccountMove(models.Model): 'reply_to': 'finance@indoteknik.co.id', } - template.send_mail(invs[0].id, force_send=True, email_values=values) + # template.send_mail(invs[0].id, force_send=True, email_values=values) _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag -- cgit v1.2.3 From e1621acf8c11052405aa3ca46ad160fedc310e0a Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Mon, 25 Aug 2025 13:45:25 +0700 Subject: (andri) on reminder --- indoteknik_custom/models/account_move.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 599b3220..905855c6 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -180,7 +180,7 @@ class AccountMove(models.Model): ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('invoice_date_due', 'in', target_dates), ('date_terima_tukar_faktur', '!=', False) - ], limit=5) + ]) _logger.info(f"Invoices: {invoices}") invoices = invoices.filtered( @@ -331,7 +331,7 @@ class AccountMove(models.Model): 'reply_to': 'finance@indoteknik.co.id', } - # template.send_mail(invs[0].id, force_send=True, email_values=values) + template.send_mail(invs[0].id, force_send=True, email_values=values) _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag -- cgit v1.2.3 From 0fe7320b3b32fa41fd06e30040171c6bf9800897 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 26 Aug 2025 09:57:51 +0700 Subject: (andri) add grand total inv --- indoteknik_custom/models/account_move.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 599b3220..6f3190f0 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -247,8 +247,10 @@ class AccountMove(models.Model): _logger.info(f"Email tujuan: {email_to}") invoice_table_rows = "" + grand_total = 0 for inv in invs: days_to_due = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0 + grand_total += inv.amount_total invoice_table_rows += f""" {inv.partner_id.name} @@ -261,6 +263,15 @@ class AccountMove(models.Model): {days_to_due} """ + invoice_table_footer = f""" + + + Grand Total + {formatLang(self.env, grand_total, currency_obj=invs[0].currency_id)} + + + + """ days_to_due_message = "" closing_message = "" @@ -302,7 +313,7 @@ class AccountMove(models.Model): body_html = re.sub( r"]*>.*?", - f"{invoice_table_rows}", + f"{invoice_table_rows}{invoice_table_footer}", template.body_html, flags=re.DOTALL ).replace('${object.name}', partner.name) \ @@ -323,16 +334,16 @@ class AccountMove(models.Model): # Siapkan email values values = { 'subject': f"Reminder Invoice Due - {partner.name}", - # 'email_to': 'andrifebriyadiputra@gmail.com', - 'email_to': email_to, + 'email_to': 'andrifebriyadiputra@gmail.com', + # 'email_to': email_to, 'email_from': 'finance@indoteknik.co.id', - 'email_cc': ",".join(sorted(set(cc_list))), + # 'email_cc': ",".join(sorted(set(cc_list))), 'body_html': body_html, - 'reply_to': 'finance@indoteknik.co.id', + # 'reply_to': 'finance@indoteknik.co.id', } - # template.send_mail(invs[0].id, force_send=True, email_values=values) - _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") + template.send_mail(invs[0].id, force_send=True, email_values=values) + # _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag invs.write({'reminder_sent_date': today}) -- cgit v1.2.3 From bb75985009a318cbbe9c4410806e06ed07aae6d1 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 26 Aug 2025 13:58:48 +0700 Subject: (andri) add limit berdasarkan blocking amount dan limit terpakai berdasarkan total amount invoices yang ada --- indoteknik_custom/models/account_move.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 6f3190f0..49bfe762 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -273,6 +273,27 @@ class AccountMove(models.Model): """ + blocking_limit = partner.blocking_stage or 0.0 + + outstanding_invoices = self.env['account.move'].search([ + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), + ('partner_id', '=', partner.id), + ('invoice_payment_term_id.name', 'ilike', 'tempo') + + ]) + _logger.info(f"Outstanding invoices for {partner.name}: {outstanding_invoices}") + outstanding_amount = sum(outstanding_invoices.mapped('amount_total')) + currency = invs[0].currency_id if invs else partner.company_id.currency_id + limit_info_html = f""" +

Informasi Tambahan:

+
    +
  • Total Limit: {formatLang(self.env, blocking_limit, currency_obj=currency)}
  • +
  • Total Limit Terpakai: {formatLang(self.env, outstanding_amount, currency_obj=currency)}
  • +
+ """ + days_to_due_message = "" closing_message = "" if dtd > 0: @@ -319,7 +340,7 @@ class AccountMove(models.Model): ).replace('${object.name}', partner.name) \ .replace('${object.partner_id.name}', partner.name) \ .replace('${days_to_due_message}', days_to_due_message) \ - .replace('${closing_message}', closing_message) + .replace('${closing_message}', closing_message + limit_info_html) cc_list = [ 'finance@indoteknik.co.id', @@ -333,7 +354,7 @@ class AccountMove(models.Model): # Siapkan email values values = { - 'subject': f"Reminder Invoice Due - {partner.name}", + 'subject': f"Reminder Invoice Due Test - {partner.name}", 'email_to': 'andrifebriyadiputra@gmail.com', # 'email_to': email_to, 'email_from': 'finance@indoteknik.co.id', -- cgit v1.2.3 From 43049cea86883ffcfb6ae988dc46b74ad38def85 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Tue, 26 Aug 2025 17:05:58 +0700 Subject: (andri) fix layout mail reminder & add limit, sisa limit, limit terpakai, & jatuh tempo seperti pada tempo di webite --- indoteknik_custom/models/account_move.py | 66 +++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 10 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 49bfe762..f5dd5a39 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -179,8 +179,9 @@ class AccountMove(models.Model): ('state', '=', 'posted'), ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('invoice_date_due', 'in', target_dates), - ('date_terima_tukar_faktur', '!=', False) - ], limit=5) + ('date_terima_tukar_faktur', '!=', False), + ('partner_id', 'in', [88813, 80163]) + ]) _logger.info(f"Invoices: {invoices}") invoices = invoices.filtered( @@ -275,23 +276,68 @@ class AccountMove(models.Model): blocking_limit = partner.blocking_stage or 0.0 + # semua invoice tempo yang masih open outstanding_invoices = self.env['account.move'].search([ ('move_type', '=', 'out_invoice'), ('state', '=', 'posted'), ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('partner_id', '=', partner.id), ('invoice_payment_term_id.name', 'ilike', 'tempo') - ]) - _logger.info(f"Outstanding invoices for {partner.name}: {outstanding_invoices}") + outstanding_amount = sum(outstanding_invoices.mapped('amount_total')) + + # invoice tempo yang sudah jatuh tempo + overdue_invoices = outstanding_invoices.filtered( + lambda inv: inv.invoice_date_due and inv.invoice_date_due < fields.Date.today() + ) + + overdue_amount = sum(overdue_invoices.mapped('amount_total')) + currency = invs[0].currency_id if invs else partner.company_id.currency_id limit_info_html = f""" -

Informasi Tambahan:

-
    -
  • Total Limit: {formatLang(self.env, blocking_limit, currency_obj=currency)}
  • -
  • Total Limit Terpakai: {formatLang(self.env, outstanding_amount, currency_obj=currency)}
  • -
+ + + + + + + + + + + + + + + +
+ Pembayaran Tempo +
+

Kredit Limit Anda
+ {formatLang(self.env, blocking_limit, currency_obj=currency)} +

+

Status Detail Tempo Pembayaran Anda
+ {partner.property_payment_term_id.name or 'Review'} +

+
+
+ {formatLang(self.env, blocking_limit - outstanding_amount, currency_obj=currency)} +
+
Sisa Kredit Limit
+
+
+ {formatLang(self.env, outstanding_amount, currency_obj=currency)} +
+
Kredit Limit Terpakai
+
{len(outstanding_invoices)} Transaksi
+
+
+ {formatLang(self.env, overdue_amount, currency_obj=currency)} +
+
Jatuh Tempo
+
{len(overdue_invoices)} Invoice
+
""" days_to_due_message = "" @@ -340,7 +386,7 @@ class AccountMove(models.Model): ).replace('${object.name}', partner.name) \ .replace('${object.partner_id.name}', partner.name) \ .replace('${days_to_due_message}', days_to_due_message) \ - .replace('${closing_message}', closing_message + limit_info_html) + .replace('${closing_message}', limit_info_html + closing_message) cc_list = [ 'finance@indoteknik.co.id', -- cgit v1.2.3 From 9b0ce82de8518012198f526737403648f94d21c7 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Wed, 27 Aug 2025 16:05:55 +0700 Subject: (andri) test --- indoteknik_custom/models/account_move.py | 70 +++++++++++--------------------- 1 file changed, 23 insertions(+), 47 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index d9d15764..b97edd0a 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -179,7 +179,8 @@ class AccountMove(models.Model): ('state', '=', 'posted'), ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('invoice_date_due', 'in', target_dates), - ('date_terima_tukar_faktur', '!=', False) + ('date_terima_tukar_faktur', '!=', False), + ('partner_id', 'in' , [14709]) ], limit=5) _logger.info(f"Invoices: {invoices}") @@ -295,48 +296,22 @@ class AccountMove(models.Model): currency = invs[0].currency_id if invs else partner.company_id.currency_id limit_info_html = f""" - - - - - - - - - - - - - - - -
- Pembayaran Tempo -
-

Kredit Limit Anda
- {formatLang(self.env, blocking_limit, currency_obj=currency)} -

-

Status Detail Tempo Pembayaran Anda
- {partner.property_payment_term_id.name or 'Review'} -

-
-
- {formatLang(self.env, blocking_limit - outstanding_amount, currency_obj=currency)} -
-
Sisa Kredit Limit
-
-
- {formatLang(self.env, outstanding_amount, currency_obj=currency)} -
-
Kredit Limit Terpakai
-
{len(outstanding_invoices)} Transaksi
-
-
- {formatLang(self.env, overdue_amount, currency_obj=currency)} -
-
Jatuh Tempo
-
{len(overdue_invoices)} Invoice
-
+

Informasi Tambahan:

+
    +
  • Kredit Limit Anda: {formatLang(self.env, blocking_limit, currency_obj=currency)}
  • +
  • Status Detail Tempo: {partner.property_payment_term_id.name or 'Review'}
  • +
  • + Sisa Kredit Limit: {formatLang(self.env, blocking_limit - outstanding_amount, currency_obj=currency)} +
  • +
  • + Kredit Limit Terpakai: {formatLang(self.env, outstanding_amount, currency_obj=currency)} + ({len(outstanding_invoices)} Transaksi) +
  • +
  • + Jatuh Tempo: {formatLang(self.env, overdue_amount, currency_obj=currency)} + ({len(overdue_invoices)} Invoice) +
  • +
""" days_to_due_message = "" @@ -385,7 +360,8 @@ class AccountMove(models.Model): ).replace('${object.name}', partner.name) \ .replace('${object.partner_id.name}', partner.name) \ .replace('${days_to_due_message}', days_to_due_message) \ - .replace('${closing_message}', limit_info_html + closing_message) + .replace('${closing_message}', closing_message) \ + .replace('${limit_info_html}', limit_info_html) cc_list = [ 'finance@indoteknik.co.id', @@ -408,11 +384,11 @@ class AccountMove(models.Model): # 'reply_to': 'finance@indoteknik.co.id', } - # template.send_mail(invs[0].id, force_send=True, email_values=values) - _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") + template.send_mail(invs[0].id, force_send=True, email_values=values) + # _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag - invs.write({'reminder_sent_date': today}) + # invs.write({'reminder_sent_date': today}) # Post ke chatter user_system = self.env['res.users'].browse(25) system_id = user_system.partner_id.id if user_system else False -- cgit v1.2.3 From 4fcaaf9bc4e1e595e196437887dbe7c15acc5c41 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 28 Aug 2025 11:47:00 +0700 Subject: (andri) fix informasi tambahan dan menambahkan button cek selengkapnya --- indoteknik_custom/models/account_move.py | 45 ++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index b97edd0a..8e58ce6b 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -180,7 +180,7 @@ class AccountMove(models.Model): ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']), ('invoice_date_due', 'in', target_dates), ('date_terima_tukar_faktur', '!=', False), - ('partner_id', 'in' , [14709]) + ('partner_id', 'in' , [94603]) ], limit=5) _logger.info(f"Invoices: {invoices}") @@ -295,23 +295,34 @@ class AccountMove(models.Model): overdue_amount = sum(overdue_invoices.mapped('amount_total')) currency = invs[0].currency_id if invs else partner.company_id.currency_id + # tempo_link = 'https://www.indoteknik.com/my/tempo' + tempo_link = 'http://localhost:2100/my/tempo' + limit_info_html = f""" -

Informasi Tambahan:

-
    -
  • Kredit Limit Anda: {formatLang(self.env, blocking_limit, currency_obj=currency)}
  • -
  • Status Detail Tempo: {partner.property_payment_term_id.name or 'Review'}
  • -
  • - Sisa Kredit Limit: {formatLang(self.env, blocking_limit - outstanding_amount, currency_obj=currency)} -
  • -
  • - Kredit Limit Terpakai: {formatLang(self.env, outstanding_amount, currency_obj=currency)} - ({len(outstanding_invoices)} Transaksi) -
  • -
  • - Jatuh Tempo: {formatLang(self.env, overdue_amount, currency_obj=currency)} - ({len(overdue_invoices)} Invoice) -
  • -
+

Informasi Tambahan:

+
    +
  • Kredit Limit Anda: {formatLang(self.env, blocking_limit, currency_obj=currency)}
  • +
  • Status Detail Tempo: {partner.property_payment_term_id.name or 'Review'}
  • +
  • + Sisa Kredit Limit: {formatLang(self.env, blocking_limit - outstanding_amount, currency_obj=currency)} +
  • +
  • + Kredit Limit Terpakai: {formatLang(self.env, outstanding_amount, currency_obj=currency)} + ({len(outstanding_invoices)} Transaksi) +
  • +
  • + Jatuh Tempo: {formatLang(self.env, overdue_amount, currency_obj=currency)} + ({len(overdue_invoices)} Invoice) +
  • +
+

+ + Cek Selengkapnya + +

""" days_to_due_message = "" -- cgit v1.2.3 From 6f6c6c86d91c811984d6ce6c478f4024cd4fb3ed Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Thu, 28 Aug 2025 16:35:58 +0700 Subject: (andri) live --- indoteknik_custom/models/account_move.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indoteknik_custom/models/account_move.py') diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 8e58ce6b..c44cad78 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -295,8 +295,8 @@ class AccountMove(models.Model): overdue_amount = sum(overdue_invoices.mapped('amount_total')) currency = invs[0].currency_id if invs else partner.company_id.currency_id - # tempo_link = 'https://www.indoteknik.com/my/tempo' - tempo_link = 'http://localhost:2100/my/tempo' + tempo_link = 'https://indoteknik.com/my/tempo' + # tempo_link = 'http://localhost:2100/my/tempo' limit_info_html = f"""

Informasi Tambahan:

@@ -386,20 +386,20 @@ class AccountMove(models.Model): # Siapkan email values values = { - 'subject': f"Reminder Invoice Due Test - {partner.name}", - 'email_to': 'andrifebriyadiputra@gmail.com', - # 'email_to': email_to, + 'subject': f"Reminder Invoice Due - {partner.name}", + # 'email_to': 'andrifebriyadiputra@gmail.com', + 'email_to': email_to, 'email_from': 'finance@indoteknik.co.id', - # 'email_cc': ",".join(sorted(set(cc_list))), + 'email_cc': ",".join(sorted(set(cc_list))), 'body_html': body_html, - # 'reply_to': 'finance@indoteknik.co.id', + 'reply_to': 'finance@indoteknik.co.id', } template.send_mail(invs[0].id, force_send=True, email_values=values) - # _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") + _logger.info(f"Mengirim email ke: {values['email_to']} > email CC: {values['email_cc']}") _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})") # flag - # invs.write({'reminder_sent_date': today}) + invs.write({'reminder_sent_date': today}) # Post ke chatter user_system = self.env['res.users'].browse(25) system_id = user_system.partner_id.id if user_system else False -- cgit v1.2.3