from odoo import models, api, fields from odoo.exceptions import AccessError, UserError, ValidationError from datetime import timedelta, date, datetime import logging _logger = logging.getLogger(__name__) class DueExtension(models.Model): _name = "due.extension" _description = "Due Extension" _inherit = ['mail.thread'] _rec_name = 'number' number = fields.Char(string='Document No', index=True, copy=False, readonly=True, tracking=True) partner_id = fields.Many2one('res.partner', string="Customer", readonly=True) payment_term = fields.Char(string="Payment Term", readonly=True, compute='_compute_payment_term') order_id = fields.Many2one('sale.order', string="SO", readonly=True) amount_total = fields.Monetary( string="Amount Total SO", compute="_compute_amount_total", readonly=True ) currency_id = fields.Many2one( 'res.currency', related="order_id.currency_id", readonly=True ) invoice_id = fields.Many2one('account.move', related='due_line.invoice_id', string='Invoice', readonly=False) due_line = fields.One2many('due.extension.line', 'due_id', string='Due Extension Lines', auto_join=True) old_due = fields.Date(string="Old Due") description = fields.Text(string="Description") is_approve = fields.Boolean(string="Is Approve", readonly=True, tracking=True) approval_status = fields.Selection([ ('pengajuan', 'Pengajuan'), ('approved', 'Approved'), ], string='Approval Status', readonly=True, copy=False, index=True, tracking=3) day_extension = fields.Selection([ ('1', '1 Hari'), ('3', '3 Hari'), ('7', '7 Hari'), ('14', '14 Hari'), ('21', '21 Hari'), ], string='Day Extension', help='Menambah Due Date yang sudah limit dari hari ini', tracking=True) counter = fields.Integer(string="Counter", compute='_compute_counter') approve_by = fields.Many2one('res.users', string="Approve By", readonly=True) date_approve = fields.Datetime(string="Date Approve", readonly=True) @api.depends('partner_id') def _compute_payment_term(self): for rec in self: rec.payment_term = rec.partner_id.property_payment_term_id.name @api.depends('order_id') def _compute_amount_total(self): for rec in self: rec.amount_total = rec.order_id.amount_total if rec.order_id else 0.0 def _compute_counter(self): for due in self: due.counter = due.partner_id.counter @api.model def create(self, vals): vals['number'] = self.env['ir.sequence'].next_by_code('due.extension') or '0' result = super(DueExtension, self).create(vals) return result def due_extension_approval(self): if not self.approval_status: self.approval_status = 'pengajuan' elif self.approval_status == 'pengajuan': raise UserError('Anda sudah mengajukan ask approval') elif self.approval_status == 'approved': raise UserError('Document sudah di approve') def due_extension_cancel(self): if self.env.user.is_accounting: if not self.approval_status or self.approval_status == 'pengajuan': self.approval_status = False sales = self.env['sale.order'].search([ ('id', '=', self.order_id.id) ]) sales.action_cancel() elif self.approval_status == 'approved': raise UserError('Document sudah di approve, Tidak bisa di cancel') else: raise UserError('Hanya Finance yang bisa cancel') def approve_new_due(self): if not self.env.user.is_accounting: raise UserError('Hanya Finance Yang Bisa Approve') if self.approval_status == 'approved': raise UserError('Document ini sudah di approve') self.is_approve = True self.approval_status = 'approved' self.partner_id.counter+=1 day_extension = int(self.day_extension) if self.partner_id: new_due = date.today() + timedelta(days=day_extension) for line in self.due_line: line.invoice_id.new_due_date = new_due line.invoice_id.due_extension = day_extension if self.order_id._requires_approval_margin_leader(): self.order_id.approval_status = 'pengajuan2' return self.order_id._create_approval_notification('Pimpinan') if self.order_id._requires_approval_margin_manager(): self.order_id.check_credit_limit() self.order_id.approval_status = 'pengajuan1' return self.order_id._create_approval_notification('Sales Manager') if self.order_id._requires_approval_team_sales(): self.order_id.check_credit_limit() self.order_id.approval_status = 'pengajuan1' return self.order_id._create_approval_notification('Team Sales') sales = self.env['sale.order'].browse(self.order_id.id) sales.with_context({'due_approve': True}).action_confirm() self.order_id.due_id = self.id self.approve_by = self.env.user.id self.date_approve = datetime.utcnow() # self.order_id.message_post("Due Extension telah di approve") self.order_id.message_post(body="Due Extension telah di approve") template = self.env.ref('indoteknik_custom.mail_template_due_extension_approve') template.send_mail(self.id, force_send=True) return { 'type': 'ir.actions.act_window', 'res_model': 'sale.order', 'view_mode': 'form', 'res_id': self.order_id.id, 'views': [(False, 'form')], 'target': 'current', } def generate_due_line(self): partners = self.partner_id.get_child_ids() query = [ ('partner_id', 'in', partners), ('state', '=', 'posted'), ('move_type', '=', 'out_invoice'), ('amount_residual_signed', '>', 0) ] invoices = self.env['account.move'].search(query, order='invoice_date') count = 0 for invoice in invoices: day_to_due = invoice.invoice_day_to_due + invoice.due_extension if day_to_due < 0: self.env['due.extension.line'].create([{ 'due_id': self.id, 'partner_id': invoice.partner_id.id, 'invoice_id': invoice.id, 'date_invoice': invoice.invoice_date, 'efaktur_id': invoice.efaktur_id.id, 'reference': invoice.ref, 'total_amt': invoice.amount_total, 'open_amt': invoice.amount_residual_signed }]) count += 1 invoice.counter+=1 _logger.info("Due Extension Line generated %s" % count) def unlink(self): res = super(DueExtension, self).unlink() if not self._name == 'due.extension': raise UserError('Due Extension tidak bisa didelete') return res class DueExtensionLine(models.Model): _name = 'due.extension.line' _description = 'Due Extension Line' _order = 'due_id, id' due_id = fields.Many2one('due.extension', string='Due Ref', required=True, ondelete='cascade', index=True, copy=False) due_description = fields.Text(string="Description", compute="_compute_due_description") due_approval_status = fields.Selection([ ('pengajuan', 'Pengajuan'), ('approved', 'Approved'), ], string="Approval Status", compute="_compute_due_approval_status") due_day_extension = fields.Char(string="Day Extension", compute="_compute_due_day_extension") partner_id = fields.Many2one('res.partner', string='Customer') invoice_id = fields.Many2one('account.move', string='Invoice') date_invoice = fields.Date(string='Invoice Date') efaktur_id = fields.Many2one('vit.efaktur', string='Faktur Pajak') user_id = fields.Many2one('res.users', string='Salesperson', related='invoice_id.invoice_user_id') reference = fields.Char(string='Reference') total_amt = fields.Float(string='Total Amount') open_amt = fields.Float(string='Open Amount') due_date = fields.Date(string='Due Date', compute="_compute_due_date") day_to_due = fields.Integer(string='Day To Due', compute="_compute_day_to_due") def _compute_due_description(self): for line in self: line.due_description = line.due_id.description def _compute_due_approval_status(self): for line in self: line.due_approval_status = line.due_id.approval_status def _compute_due_day_extension(self): for line in self: line.due_day_extension = line.due_id.day_extension def _compute_day_to_due(self): for line in self: # line.day_to_due = line.invoice_id.invoice_day_to_due line.day_to_due = line.invoice_id.new_invoice_day_to_due def _compute_due_date(self): for line in self: if line.invoice_id.new_due_date: line.due_date = line.invoice_id.new_due_date else: line.due_date = line.invoice_id.invoice_date_due