diff options
| author | IT Fixcomart <it@fixcomart.co.id> | 2025-08-21 15:39:31 +0000 |
|---|---|---|
| committer | IT Fixcomart <it@fixcomart.co.id> | 2025-08-21 15:39:31 +0000 |
| commit | 1d5bd9c3b7c89eefe8a06e21ec5a53af3e72b4bb (patch) | |
| tree | becff9838f92c9ead50db31cea16eebb469ea2a7 | |
| parent | 4b549234856b810bd99f8b1e18e01da90ccdc1e1 (diff) | |
| parent | 3f28815704346d81e42ea03a95f591ef1131a622 (diff) | |
Merged in reminder-tempo-v2 (pull request #391)
Reminder tempo v2
| -rw-r--r-- | indoteknik_custom/models/account_move.py | 131 | ||||
| -rw-r--r-- | indoteknik_custom/models/res_partner.py | 8 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/account_move.xml | 40 | ||||
| -rw-r--r-- | indoteknik_custom/views/res_partner.xml | 5 |
5 files changed, 180 insertions, 8 deletions
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 94774f0f..a211d739 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,36 @@ class AccountMove(models.Model): else: move.payment_date = False + def action_sync_promise_date(self): + 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 + + 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() @@ -168,6 +204,24 @@ 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 + + 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), @@ -175,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: @@ -689,4 +739,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 diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py index e5e382a1..08b04e7d 100644 --- a/indoteknik_custom/models/res_partner.py +++ b/indoteknik_custom/models/res_partner.py @@ -31,6 +31,14 @@ class ResPartner(models.Model): string='Reminder Invoice?', help='Centang jika kontak ini harus menerima email pengingat invoice.', default=False ) + dont_send_reminder_inv_parent = fields.Boolean( + string='Dont Send Reminder Invoices Parent?', + help='Centang jika kontak utama tidak perlu menerima sent Reminder Invoices Otomatis', default=False + ) + dont_send_reminder_inv_all = fields.Boolean( + string='Dont Send Reminder Invoices to All?', + help='Centang jika semua kontak utama dan child tidak menerima sent Reminder Invoices', default=False + ) # informasi perusahaan name_tempo = fields.Many2one('res.partner', string='Nama Perusahaan',tracking=True) diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index d6e44f9d..78b3dc0f 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -192,4 +192,6 @@ access_tukar_guling_line_all_users,tukar.guling.line.all.users,model_tukar_gulin access_tukar_guling_po_all_users,tukar.guling.po.all.users,model_tukar_guling_po,base.group_user,1,1,1,1 access_tukar_guling_line_po_all_users,tukar.guling.line.po.all.users,model_tukar_guling_line_po,base.group_user,1,1,1,1 access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,model_tukar_guling_mapping_koli,base.group_user,1,1,1,1 -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
\ No newline at end of file +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
\ No newline at end of file diff --git a/indoteknik_custom/views/account_move.xml b/indoteknik_custom/views/account_move.xml index e5d1cf8a..b399d4c9 100644 --- a/indoteknik_custom/views/account_move.xml +++ b/indoteknik_custom/views/account_move.xml @@ -68,6 +68,14 @@ <field name="nomor_kwitansi"/> <field name="down_payment"/> </field> + <field name="website_id" position="after"> + <field name="customer_promise_date"/> + <button name="action_sync_promise_date" + string="Sync Janji Bayar ke Invoice Lain" + type="object" + class="btn-primary" + help="Sync Janji Bayar Customer ke Invoices dengan jumlah Due Date yang sama"/> + </field> <field name="to_check" position="after"> <field name="already_paid"/> <field name="so_shipping_paid_by"/> @@ -195,5 +203,37 @@ <field name="state">code</field> <field name="code">action = records.export_faktur_to_xml()</field> </record> + + <record id="view_sync_promise_date_wizard_form" model="ir.ui.view"> + <field name="name">sync.promise.date.wizard.form</field> + <field name="model">sync.promise.date.wizard</field> + <field name="arch" type="xml"> + <form string="Sync Janji Bayar"> + <group> + <field name="invoice_id" readonly="1"/> + <field name="promise_date" readonly="1"/> + </group> + <field name="line_ids"> + <tree create="false" delete="false" editable="bottom"> + <field name="sync_check"/> + <field name="invoice_name" readonly="1"/> + <field name="invoice_date_due" readonly="1"/> + <field name="invoice_day_to_due" readonly="1"/> + <field name="new_invoice_day_to_due" readonly="1"/> + <field name="date_terima_tukar_faktur" readonly="1"/> + <field name="amount_total" readonly="1"/> + </tree> + </field> + + <button name="action_check_all" string="Check All" type="object" class="btn-secondary"/> + <button name="action_uncheck_all" string="Uncheck All" type="object" class="btn-secondary"/> + + <footer> + <button name="action_confirm" string="Konfirmasi Sync" type="object" class="btn-primary"/> + <button string="Batal" class="btn-secondary" special="cancel"/> + </footer> + </form> + </field> + </record> </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml index b081f6f2..ca1a36de 100644 --- a/indoteknik_custom/views/res_partner.xml +++ b/indoteknik_custom/views/res_partner.xml @@ -87,6 +87,7 @@ <field name="use_so_approval" attrs="{'invisible': [('parent_id', '!=', False), ('company_type', '!=', 'company')]}" /> <field name="use_only_ready_stock" attrs="{'invisible': [('parent_id', '!=', False), ('company_type', '!=', 'company')]}" /> <field name="web_role" attrs="{'invisible': ['|', ('parent_id', '=', False), ('company_type', '=', 'company')]}" /> + <field name="reminder_invoices" attrs="{'invisible': ['|', ('parent_id', '=', False), ('company_type', '=', 'company')]}"/> </field> <xpath expr="//field[@name='child_ids']/form//field[@name='name']" position="before"> <field name="parent_id" invisible="1" /> @@ -215,6 +216,10 @@ <field name="dokumen_laporan_keuangan" /> <field name="dokumen_ktp_dirut" /> </group> + <group string="Reminder Invoices" attrs="{'invisible': [('parent_id', '!=', False), ('company_type', '!=', 'company')]}"> + <field name="dont_send_reminder_inv_parent"/> + <field name="dont_send_reminder_inv_all" /> + </group> </page> <page string="Aging Info"> <group string="Aging Info"> |
