diff options
Diffstat (limited to 'indoteknik_custom/models/account_move.py')
| -rw-r--r-- | indoteknik_custom/models/account_move.py | 227 |
1 files changed, 216 insertions, 11 deletions
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index 30de67be..1a6fad1c 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -1,5 +1,6 @@ from odoo import models, api, fields from odoo.exceptions import AccessError, UserError, ValidationError +from markupsafe import escape as html_escape from datetime import timedelta, date, datetime from pytz import timezone, utc import logging @@ -8,12 +9,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") @@ -67,13 +71,189 @@ class AccountMove(models.Model): is_hr = fields.Boolean(string="Is HR?", default=False) purchase_order_id = fields.Many2one('purchase.order', string='Purchase Order') length_of_payment = fields.Integer(string="Length of Payment", compute='compute_length_of_payment') + reklas_misc_id = fields.Many2one('account.move', string='Journal Entries Reklas') + # Di model account.move + 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?') + refund_id = fields.Many2one('refund.sale.order', string='Refund Reference') + refund_so_ids = fields.Many2many( + 'sale.order', + 'account_move_sale_order_rel', + 'move_id', + 'sale_order_id', + string='Group SO Number' + ) + + refund_so_links = fields.Html( + string="Group SO Numbers", + compute="_compute_refund_so_links", + ) + + has_refund_so = fields.Boolean( + string='Has Refund SO', + compute='_compute_has_refund_so', + ) + + # 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 + + # 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") + + + @api.onchange('invoice_date') + def _onchange_invoice_date(self): + if self.invoice_date: + self.date = self.invoice_date + + @api.onchange('date') + def _onchange_date(self): + if self.date: + self.invoice_date = self.date + + @api.depends('refund_so_ids') + def _compute_refund_so_links(self): + for rec in self: + links = [] + for so in rec.refund_so_ids: + url = f"/web#id={so.id}&model=sale.order&view_type=form" + name = html_escape(so.name or so.display_name) + links.append(f'<a href="{url}" target="_blank">{name}</a>') + rec.refund_so_links = ', '.join(links) if links else "-" + + @api.depends('refund_so_ids') + def _compute_has_refund_so(self): + for rec in self: + rec.has_refund_so = bool(rec.refund_so_ids) + + + # def compute_length_of_payment(self): + # for rec in self: + # payment_term = rec.invoice_payment_term_id.line_ids[0].days + # terima_faktur = rec.date_terima_tukar_faktur + # payment = self.search([('ref', '=', rec.name), ('move_type', '=', 'entry')], limit=1) + + # if payment and terima_faktur: + # date_diff = terima_faktur - payment.date + # rec.length_of_payment = date_diff.days + payment_term + # else: + # rec.length_of_payment = 0 def compute_length_of_payment(self): for rec in self: - payment_term = rec.invoice_payment_term_id.line_ids[0].days + payment_term = 0 + if rec.invoice_payment_term_id and rec.invoice_payment_term_id.line_ids: + payment_term = rec.invoice_payment_term_id.line_ids[0].days + terima_faktur = rec.date_terima_tukar_faktur payment = self.search([('ref', '=', rec.name), ('move_type', '=', 'entry')], limit=1) - + if payment and terima_faktur: date_diff = terima_faktur - payment.date rec.length_of_payment = date_diff.days + payment_term @@ -126,13 +306,38 @@ class AccountMove(models.Model): } template.send_mail(record.id, email_values=email_values, force_send=True) + # @api.model + # def create(self, vals): + # vals['nomor_kwitansi'] = self.env['ir.sequence'].next_by_code('nomor.kwitansi') or '0' + # result = super(AccountMove, self).create(vals) + # # result._update_line_name_from_ref() + # return result + @api.model def create(self, vals): - vals['nomor_kwitansi'] = self.env['ir.sequence'].next_by_code('nomor.kwitansi') or '0' + vals['nomor_kwitansi'] = self.env['ir.sequence'].next_by_code('nomor.kwitansi') or '0' result = super(AccountMove, self).create(vals) - # result._update_line_name_from_ref() + + # Tambahan: jika ini Vendor Bill dan tanggal belum diisi + if result.move_type == 'in_invoice' and not vals.get('invoice_date') and not vals.get('date'): + po = result.purchase_order_id + if po: + # Cari receipt dari PO + picking = self.env['stock.picking'].search([ + ('purchase_id', '=', po.id), + ('picking_type_code', '=', 'incoming'), + ('state', '=', 'done'), + ('date_done', '!=', False), + ], order='date_done desc', limit=1) + + if picking: + receipt_date = picking.date_done + result.invoice_date = receipt_date + result.date = receipt_date + return result + def compute_so_shipping_paid_by(self): for record in self: record.so_shipping_paid_by = record.sale_id.shipping_paid_by @@ -381,18 +586,18 @@ class AccountMove(models.Model): return invoices def export_faktur_to_xml(self): - valid_invoices = self - # Panggil model coretax.faktur untuk menghasilkan XML coretax_faktur = self.env['coretax.faktur'].create({}) - response = coretax_faktur.export_to_download(invoices=valid_invoices) - current_time = datetime.utcnow() - # Tandai faktur sebagai sudah diekspor + response = coretax_faktur.export_to_download( + invoices=valid_invoices, + down_payments=[inv.down_payment for inv in valid_invoices], + ) + valid_invoices.write({ 'is_efaktur_exported': True, - 'date_efaktur_exported': current_time, # Set tanggal ekspor + 'date_efaktur_exported': datetime.utcnow(), }) - return response + return response
\ No newline at end of file |
