summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-08-09 13:59:43 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-08-09 13:59:43 +0700
commit48159b92cfa466ff7df454aa3c860b79c7e18467 (patch)
tree8f50df9b54dadac53d40d2f487de1b89c24ca561
parentb6ae7b2c9f1c564f3bf2a471f4871fda745d215d (diff)
parent06b661f2fa9e07e4b3d1d2b5c7aa9f16f057a3a3 (diff)
Merge branch 'odoo-backup' of https://bitbucket.org/altafixco/indoteknik-addons into odoo-backup
-rw-r--r--indoteknik_custom/models/account_move.py265
-rw-r--r--indoteknik_custom/models/res_partner.py5
-rwxr-xr-xindoteknik_custom/models/sale_order.py9
-rw-r--r--indoteknik_custom/models/stock_picking.py9
-rw-r--r--indoteknik_custom/views/mail_template_invoice_reminder.xml22
-rw-r--r--indoteknik_custom/views/res_partner.xml3
6 files changed, 202 insertions, 111 deletions
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index c5e01f0c..fd08ed60 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -134,102 +134,175 @@ class AccountMove(models.Model):
# result.append((move.id, move.display_name))
# return result
- # def send_due_invoice_reminder(self):
- # today = fields.Date.today()
- # target_dates = [
- # today - timedelta(days=7),
- # today - timedelta(days=3),
- # today,
- # today + timedelta(days=3),
- # today + timedelta(days=7),
- # ]
-
- # partner = self.env['res.partner'].search([('name', 'ilike', 'BANGUNAN TEKNIK GRUP')], limit=1)
- # if not partner:
- # _logger.info("Partner tidak ditemukan.")
- # return
-
- # invoices = self.env['account.move'].search([
- # ('move_type', '=', 'out_invoice'),
- # ('state', '=', 'posted'),
- # ('payment_state', 'not in', ['paid','in_payment', 'reversed']),
- # ('invoice_date_due', 'in', target_dates),
- # ('partner_id', '=', partner.id),
- # ])
-
- # _logger.info(f"Invoices tahap 1: {invoices}")
-
- # invoices = invoices.filtered(
- # lambda inv: inv.invoice_payment_term_id and 'tempo' in (inv.invoice_payment_term_id.name or '').lower()
- # )
- # _logger.info(f"Invoices tahap 2: {invoices}")
-
- # if not invoices:
- # _logger.info(f"Tidak ada invoice yang due untuk partner: {partner.name}")
- # return
-
- # grouped = {}
- # for inv in invoices:
- # grouped.setdefault(inv.partner_id, []).append(inv)
-
- # template = self.env.ref('indoteknik_custom.mail_template_invoice_due_reminder')
-
- # for partner, invs in grouped.items():
- # if not partner.email:
- # _logger.info(f"Partner {partner.name} tidak memiliki email")
- # continue
-
- # invoice_table_rows = ""
- # for inv in invs:
- # days_to_due = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0
- # invoice_table_rows += f"""
- # <tr>
- # <td>{inv.name}</td>
- # <td>{fields.Date.to_string(inv.invoice_date) or '-'}</td>
- # <td>{fields.Date.to_string(inv.invoice_date_due) or '-'}</td>
- # <td>{days_to_due}</td>
- # <td>{formatLang(self.env, inv.amount_total, currency_obj=inv.currency_id)}</td>
- # <td>{inv.ref or '-'}</td>
- # </tr>
- # """
-
- # subject = f"Reminder Invoice Due - {partner.name}"
- # body_html = re.sub(
- # r"<tbody[^>]*>.*?</tbody>",
- # f"<tbody>{invoice_table_rows}</tbody>",
- # template.body_html,
- # flags=re.DOTALL
- # ).replace('${object.name}', partner.name) \
- # .replace('${object.partner_id.name}', partner.name)
- # # .replace('${object.email}', partner.email or '')
-
- # values = {
- # 'subject': subject,
- # 'email_to': 'andrifebriyadiputra@gmail.com', # Ubah ke partner.email untuk produksi
- # 'email_from': 'finance@indoteknik.co.id',
- # 'body_html': body_html,
- # 'reply_to': f'invoice+account.move_{invs[0].id}@indoteknik.co.id',
- # }
-
- # _logger.info(f"VALUES: {values}")
-
- # template.send_mail(invs[0].id, force_send=True, email_values=values)
-
- # # Default System User
- # user_system = self.env['res.users'].browse(25)
- # system_id = user_system.partner_id.id if user_system else False
- # _logger.info(f"System User: {user_system.name} ({user_system.id})")
- # _logger.info(f"System User ID: {system_id}")
-
- # for inv in invs:
- # inv.message_post(
- # subject=subject,
- # body=body_html,
- # subtype_id=self.env.ref('mail.mt_note').id,
- # author_id=system_id,
- # )
-
- # _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice")
+ def send_due_invoice_reminder(self):
+ today = fields.Date.today()
+ target_dates = [
+ today - timedelta(days=7),
+ today - timedelta(days=3),
+ today,
+ today + timedelta(days=3),
+ today + timedelta(days=7),
+ ]
+
+ # --- TESTING ---
+ # partner = self.env['res.partner'].search([('name', 'ilike', 'DIRGANTARA YUDHA ARTHA')], limit=1)
+ # if not partner:
+ # _logger.info("Partner tidak ditemukan.")
+ # return
+ # invoices = self.env['account.move'].search([
+ # ('move_type', '=', 'out_invoice'),
+ # ('state', '=', 'posted'),
+ # ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']),
+ # ('invoice_date_due', 'in', target_dates),
+ # ('partner_id', '=', partner.id),
+ # ])
+
+ invoices = self.env['account.move'].search([
+ ('move_type', '=', 'out_invoice'),
+ ('state', '=', 'posted'),
+ ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']),
+ ('invoice_date_due', 'in', target_dates),
+ ])
+ _logger.info(f"Invoices tahap 1: {invoices}")
+
+ invoices = invoices.filtered(
+ lambda inv: inv.invoice_payment_term_id and 'tempo' in (inv.invoice_payment_term_id.name or '').lower()
+ )
+ _logger.info(f"Invoices tahap 2: {invoices}")
+
+ if not invoices:
+ _logger.info("Tidak ada invoice yang due")
+ return
+
+ invoice_group = {}
+ for inv in invoices:
+ dtd = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0
+ invoice_group.setdefault((inv.partner_id, dtd), []).append(inv)
+
+ template = self.env.ref('indoteknik_custom.mail_template_invoice_due_reminder')
+
+ for (partner, dtd), invs in invoice_group.items():
+ # Ambil child contact yang di-checklist reminder_invoices
+ reminder_contacts = self.env['res.partner'].search([
+ ('parent_id', '=', partner.id),
+ ('reminder_invoices', '=', True),
+ ('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')
+ if not emails:
+ _logger.info(f"Partner {partner.name} tidak memiliki email yang bisa dikirimi")
+ continue
+
+ email_to = ",".join(emails)
+ _logger.info(f"Email tujuan: {email_to}")
+
+ invoice_table_rows = ""
+ for inv in invs:
+ days_to_due = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0
+ invoice_table_rows += f"""
+ <tr>
+ <td>{inv.partner_id.name}</td>
+ <td>{inv.purchase_order_id.name or '-'}</td>
+ <td>{inv.name}</td>
+ <td>{fields.Date.to_string(inv.invoice_date) or '-'}</td>
+ <td>{fields.Date.to_string(inv.invoice_date_due) or '-'}</td>
+ <td>{formatLang(self.env, inv.amount_total, currency_obj=inv.currency_id)}</td>
+ <td>{inv.invoice_payment_term_id.name or '-'}</td>
+ <td>{days_to_due}</td>
+ </tr>
+ """
+
+ days_to_due_message = ""
+ closing_message = ""
+ if dtd < 0:
+ days_to_due_message = (
+ f"Kami ingin mengingatkan bahwa tagihan anda akan jatuh tempo dalam {abs(dtd)} hari ke depan, "
+ "dengan rincian sebagai berikut:"
+ )
+ closing_message = (
+ "Kami mengharapkan pembayaran dapat dilakukan tepat waktu untuk mendukung kelancaran "
+ "hubungan kerja sama yang baik antara kedua belah pihak.<br/>"
+ "Mohon konfirmasi apabila pembayaran telah dijadwalkan. "
+ "Terima kasih atas perhatian dan kerja samanya."
+ )
+
+ if dtd == 0:
+ days_to_due_message = (
+ "Kami ingin mengingatkan bahwa tagihan anda telah memasuki tanggal jatuh tempo pada hari ini, "
+ "dengan rincian sebagai berikut:"
+ )
+ closing_message = (
+ "Mohon kesediaannya untuk segera melakukan pembayaran tepat waktu guna menghindari status "
+ "keterlambatan dan menjaga kelancaran hubungan kerja sama yang telah terjalin dengan baik.<br/>"
+ "Apabila pembayaran telah dijadwalkan atau diproses, mohon dapat dikonfirmasi kepada kami. "
+ "Terima kasih atas perhatian dan kerja samanya."
+ )
+
+ if dtd > 0:
+ days_to_due_message = (
+ f"Kami ingin mengingatkan bahwa tagihan anda telah jatuh tempo selama {dtd} hari, "
+ "dengan rincian sebagai berikut:"
+ )
+ closing_message = (
+ "Mohon kesediaan Bapak/Ibu untuk segera melakukan pembayaran guna menghindari keterlambatan "
+ "dan menjaga kelancaran kerja sama yang telah terjalin dengan baik.<br/>"
+ "Apabila pembayaran sudah dilakukan, mohon konfirmasi dan lampirkan bukti transfer agar dapat kami proses lebih lanjut. "
+ "Terima kasih atas perhatian dan kerja samanya."
+ )
+
+ body_html = re.sub(
+ r"<tbody[^>]*>.*?</tbody>",
+ f"<tbody>{invoice_table_rows}</tbody>",
+ template.body_html,
+ flags=re.DOTALL
+ ).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)
+
+ cc_list = [
+ 'finance@indoteknik.co.id',
+ 'akbar@indoteknik.co.id',
+ 'stephan@indoteknik.co.id',
+ 'darren@indoteknik.co.id'
+ ]
+ sales_email = invs[0].invoice_user_id.partner_id.email if invs[0].invoice_user_id else None
+ if sales_email and sales_email not in cc_list:
+ cc_list.append(sales_email)
+
+ # Siapkan email values
+ values = {
+ '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(cc_list),
+ 'body_html': body_html,
+ 'reply_to': 'finance@indoteknik.co.id',
+ }
+
+ _logger.info(f"Mengirim email ke: {values['email_to']} CC: {values['email_cc']}")
+ template.send_mail(invs[0].id, force_send=True, email_values=values)
+
+ # Post ke chatter
+ user_system = self.env['res.users'].browse(25)
+ system_id = user_system.partner_id.id if user_system else False
+
+ for inv in invs:
+ inv.message_post(
+ subject=values['subject'],
+ body=body_html,
+ subtype_id=self.env.ref('mail.mt_note').id,
+ author_id=system_id,
+ )
+
+ _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice (dtd = {dtd})")
@api.onchange('invoice_date')
diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py
index 236df16f..f260f58e 100644
--- a/indoteknik_custom/models/res_partner.py
+++ b/indoteknik_custom/models/res_partner.py
@@ -27,6 +27,11 @@ class ResPartner(models.Model):
# Referensi
supplier_ids = fields.Many2many('user.pengajuan.tempo.line', string="Suppliers")
+ reminder_invoices = fields.Boolean(
+ string='Reminder Invoice?',
+ help='Centang jika kontak ini harus menerima email pengingat invoice.', default=False
+ )
+
# informasi perusahaan
name_tempo = fields.Many2one('res.partner', string='Nama Perusahaan',tracking=True)
industry_id_tempo = fields.Many2one('res.partner.industry', 'Customer Industry', readonly=True)
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 5eb90d83..e71e3830 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -2160,9 +2160,9 @@ class SaleOrder(models.Model):
# return self._create_notification_action('Notification',
# 'Terdapat invoice yang telah melewati batas waktu, mohon perbarui pada dokumen Due Extension')
- if not order._is_request_to_own_team_leader():
+ if not order.with_context(ask_approval=True)._is_request_to_own_team_leader():
return self._create_notification_action(
- 'Peringatan',
+ 'Peringatan',
'Hanya bisa konfirmasi SO tim Anda.'
)
if order._requires_approval_margin_leader():
@@ -2528,7 +2528,10 @@ class SaleOrder(models.Model):
if user.is_leader or user.is_sales_manager:
return True
- if not self.team_id or not self.team_id.user_id:
+ if user.id in (3401, 20, 3988): # admin (fida, nabila, ninda)
+ return True
+
+ if self.env.context.get("ask_approval") and user.id in (3401, 20, 3988):
return True
salesperson_id = self.user_id.id
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index 46bb6cee..82f81642 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -1059,10 +1059,13 @@ class StockPicking(models.Model):
return
self.sale_id.date_doc_kirim = self.date_doc_kirim
- from odoo import fields
-
def action_assign(self):
- pickings_to_assign = self.filtered(lambda p: not (p.sale_id and p.sale_id.hold_outgoing))
+ if self.env.context.get('default_picking_type_id'):
+ pickings_to_assign = self.filtered(
+ lambda p: not (p.sale_id and p.sale_id.hold_outgoing)
+ )
+ else:
+ pickings_to_assign = self
res = super(StockPicking, pickings_to_assign).action_assign()
diff --git a/indoteknik_custom/views/mail_template_invoice_reminder.xml b/indoteknik_custom/views/mail_template_invoice_reminder.xml
index 21055eb0..8450be28 100644
--- a/indoteknik_custom/views/mail_template_invoice_reminder.xml
+++ b/indoteknik_custom/views/mail_template_invoice_reminder.xml
@@ -6,29 +6,32 @@
<field name="model_id" ref="account.model_account_move"/>
<field name="subject">Reminder Invoice Due - ${object.name}</field>
<field name="email_from">finance@indoteknik.co.id</field>
- <field name="email_to">andrifebriyadiputra@gmail.com</field>
+ <field name="email_to"></field>
<field name="body_html" type="html">
<div>
<p><b>Dear ${object.name},</b></p>
- <p>Berikut adalah daftar invoice Anda yang mendekati atau telah jatuh tempo:</p>
+ <p>${days_to_due_message}</p>
- <table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; width: 100%; font-size: 12px">
+ <table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; font-size: 12px">
<thead>
<tr style="background-color: #f2f2f2;" align="left">
+ <th>Customer</th>
+ <th>No. PO</th>
<th>Invoice Number</th>
- <th>Tanggal Invoice</th>
- <th>Jatuh Tempo</th>
- <th>Sisa Hari</th>
- <th>Total</th>
- <th>Referensi</th>
+ <th>Invoice Date</th>
+ <th>Due Date</th>
+ <th>Amount</th>
+ <th>Term</th>
+ <th>Days To Due</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
- <p>Mohon bantuan dan kerjasamanya agar tetap bisa bekerjasama dengan baik</p>
+ <p>${closing_message}</p>
+ <br/>
<p>Terima Kasih.</p>
<br/>
<br/>
@@ -42,6 +45,7 @@
<a href="https://wa.me/6285716970374" target="_blank">+62-857-1697-0374</a> |
<a href="mailto:finance@indoteknik.co.id">finance@indoteknik.co.id</a>
</b></p>
+ <p><i>Email ini dikirim secara otomatis. Abaikan jika pembayaran telah dilakukan.</i></p>
</div>
</field>
diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml
index 38cd2756..b081f6f2 100644
--- a/indoteknik_custom/views/res_partner.xml
+++ b/indoteknik_custom/views/res_partner.xml
@@ -102,6 +102,9 @@
/>
</div>
</xpath>
+ <xpath expr="//field[@name='child_ids']/form//field[@name='mobile']" position="after">
+ <field name="reminder_invoices"/>
+ </xpath>
<xpath expr="//field[@name='property_payment_term_id']" position="attributes">
<attribute name="readonly">0</attribute>
</xpath>