summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzka Nathan <darizkyfaz@gmail.com>2025-07-11 15:27:51 +0700
committerAzka Nathan <darizkyfaz@gmail.com>2025-07-11 15:27:51 +0700
commit887db07ff8a79fdbaeddc07b6b09ff169f428a6c (patch)
tree802b919825785a9fb648408241df58048b0766ac
parent3021a1d4836a47721500d03eeed80ba029334b98 (diff)
parent575a7a506382487a625914a7bde9a18b20173cc6 (diff)
Merge branch 'odoo-backup' of bitbucket.org:altafixco/indoteknik-addons into odoo-backup
-rwxr-xr-xindoteknik_custom/__manifest__.py1
-rw-r--r--indoteknik_custom/models/account_move.py97
-rw-r--r--indoteknik_custom/models/dunning_run.py20
-rw-r--r--indoteknik_custom/models/sale_order_line.py1
-rw-r--r--indoteknik_custom/views/ir_sequence.xml2
-rw-r--r--indoteknik_custom/views/mail_template_invoice_reminder.xml49
6 files changed, 152 insertions, 18 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 17cec7b6..21afc26f 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -97,6 +97,7 @@
'views/mail_template_po.xml',
'views/mail_template_efaktur.xml',
'views/mail_template_invoice_po.xml',
+ 'views/mail_template_invoice_reminder.xml',
'views/price_group.xml',
'views/mrp_production.xml',
'views/apache_solr.xml',
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index b6627867..5ac1c6e5 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -8,12 +8,15 @@ import PyPDF2
import os
import re
from terbilang import Terbilang
+from collections import defaultdict
+from odoo.tools.misc import formatLang
_logger = logging.getLogger(__name__)
class AccountMove(models.Model):
_inherit = 'account.move'
+ _description = 'Account Move'
invoice_day_to_due = fields.Integer(string="Day to Due", compute="_compute_invoice_day_to_due")
bill_day_to_due = fields.Date(string="Day to Due", compute="_compute_bill_day_to_due")
date_send_fp = fields.Datetime(string="Tanggal Kirim Faktur Pajak")
@@ -72,21 +75,87 @@ class AccountMove(models.Model):
bill_id = fields.Many2one('account.move', string='Vendor Bill', domain=[('move_type', '=', 'in_invoice')], help='Bill asal dari proses reklas ini')
down_payment = fields.Boolean('Down Payments?')
+ 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', 'FLYNINDO MEGA PERSADA')], 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,
+ }
+
+ _logger.info(f"VALUES: {values}")
+
+ template.send_mail(invs[0].id, force_send=True, email_values=values)
+ _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice")
- # def name_get(self):
- # result = []
- # for move in self:
- # if move.move_type == 'entry':
- # # Jika masih draft, tampilkan 'Draft CAB'
- # if move.state == 'draft':
- # label = 'Draft CAB'
- # else:
- # label = move.name
- # result.append((move.id, label))
- # else:
- # # Untuk invoice dan lainnya, pakai default
- # result.append((move.id, move.display_name))
- # return result
@api.onchange('invoice_date')
def _onchange_invoice_date(self):
diff --git a/indoteknik_custom/models/dunning_run.py b/indoteknik_custom/models/dunning_run.py
index bb53fc0c..5a6aebac 100644
--- a/indoteknik_custom/models/dunning_run.py
+++ b/indoteknik_custom/models/dunning_run.py
@@ -92,10 +92,23 @@ class DunningRun(models.Model):
('move_type', '=', 'out_invoice'),
('state', '=', 'posted'),
('partner_id', '=', partner.id),
- # ('amount_residual_signed', '>', 0),
('date_kirim_tukar_faktur', '=', False),
]
- invoices = self.env['account.move'].search(query, order='invoice_date')
+ invoices = self.env['account.move'].search(query)
+
+ # sort full berdasarkan tahun, bulan, nomor
+ def invoice_key(x):
+ try:
+ parts = x.name.split('/')
+ tahun = int(parts[1])
+ bulan = int(parts[2])
+ nomor = int(parts[3])
+ return (tahun, bulan, nomor)
+ except Exception:
+ return (0, 0, 0)
+
+ invoices = sorted(invoices, key=invoice_key)
+
count = 0
for invoice in invoices:
self.env['dunning.run.line'].create([{
@@ -123,8 +136,9 @@ class DunningRunLine(models.Model):
_name = 'dunning.run.line'
_description = 'Dunning Run Line'
# _order = 'dunning_id, id'
- _order = 'invoice_id desc, id'
+ _order = 'invoice_number asc, id'
+ invoice_number = fields.Char('Invoice Number', related='invoice_id.name')
dunning_id = fields.Many2one('dunning.run', string='Dunning Ref', required=True, ondelete='cascade', index=True, copy=False)
partner_id = fields.Many2one('res.partner', string='Customer')
invoice_id = fields.Many2one('account.move', string='Invoice')
diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py
index 291940ed..2a0160e8 100644
--- a/indoteknik_custom/models/sale_order_line.py
+++ b/indoteknik_custom/models/sale_order_line.py
@@ -5,6 +5,7 @@ from datetime import datetime, timedelta
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
+
item_margin = fields.Float('Margin', compute='compute_item_margin', help="Total Margin in Sales Order Header")
item_before_margin = fields.Float('Before Margin', compute='compute_item_before_margin',
help="Total Margin in Sales Order Header")
diff --git a/indoteknik_custom/views/ir_sequence.xml b/indoteknik_custom/views/ir_sequence.xml
index a0f5fc6b..d9b93ff3 100644
--- a/indoteknik_custom/views/ir_sequence.xml
+++ b/indoteknik_custom/views/ir_sequence.xml
@@ -154,7 +154,7 @@
<record id="sequence_approval_payment_term" model="ir.sequence">
<field name="name">Approval Payment Term</field>
<field name="code">approval.payment.term</field>
- <field name="prefix">APP/%(year)s/</field>
+ <field name="prefix">APT/%(year)s/</field>
<field name="padding">5</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
diff --git a/indoteknik_custom/views/mail_template_invoice_reminder.xml b/indoteknik_custom/views/mail_template_invoice_reminder.xml
new file mode 100644
index 00000000..8b3b9880
--- /dev/null
+++ b/indoteknik_custom/views/mail_template_invoice_reminder.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data noupdate="0">
+ <record id="mail_template_invoice_due_reminder" model="mail.template">
+ <field name="name">Invoice Reminder: Due Date Notification</field>
+ <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="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>
+
+ <table border="1" cellpadding="6" cellspacing="0" style="border-collapse: collapse; width: 100%;">
+ <thead>
+ <tr style="background-color: #f2f2f2;" align="left">
+ <th>Invoice Number</th>
+ <th>Tanggal Invoice</th>
+ <th>Jatuh Tempo</th>
+ <th>Sisa Hari</th>
+ <th>Total</th>
+ <th>Referensi</th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+
+ <p>Mohon bantuan dan kerjasamanya agar tetap bisa bekerjasama dengan baik</p>
+ <p>Terima Kasih.</p>
+ <br/>
+ <br/>
+ <p><b>Best Regards,
+ <br/>
+ <br/>
+ Widya R.<br/>
+ Dept. Finance<br/>
+ PT. INDOTEKNIK DOTCOM GEMILANG</b><br/>
+ <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2135765" alt="Indoteknik" style="max-width: 18%; height: auto;"></img><br/>
+ +62-857-1697-0374 | finance@indoteknik.co.id</p>
+
+ </div>
+ </field>
+ <field name="auto_delete" eval="True"/>
+ </record>
+ </data>
+</odoo>