1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
from odoo import models, api, fields
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import timedelta, date
import logging
_logger = logging.getLogger(__name__)
class DunningRun(models.Model):
_name = 'dunning.run'
_description = 'Dunning Run'
_order = 'dunning_date desc, id desc'
_inherit = ['mail.thread']
_rec_name = 'number'
number = fields.Char(string='Document No', index=True, copy=False, readonly=True)
dunning_date = fields.Date(string='Dunning Date', required=True)
partner_id = fields.Many2one(
'res.partner', string='Customer',
required=True, change_default=True, index=True, tracking=1)
dunning_line = fields.One2many('dunning.run.line', 'dunning_id', string='Dunning Lines', auto_join=True, order='invoice_id desc')
# dunning_level = fields.Integer(string='Dunning Level', default=30, help='30 hari sebelum jatuh tempo invoice')
date_kirim_tukar_faktur = fields.Date(string='Kirim Faktur')
resi_tukar_faktur = fields.Char(string='Resi Faktur')
date_terima_tukar_faktur = fields.Date(string='Terima Faktur')
shipper_faktur_id = fields.Many2one('delivery.carrier', string='Shipper Faktur')
is_validated = fields.Boolean(string='Validated')
notification = fields.Char(string='Notification')
is_paid = fields.Boolean(string='Paid')
description = fields.Char(string='Description')
comment = fields.Char(string='Comment')
grand_total = fields.Float(string='Grand Total', compute="_compute_grand_total")
def _compute_grand_total(self):
for record in self:
grand_total = 0
for line in record.dunning_line:
grand_total += line.total_amt
record.grand_total = grand_total
def copy_date_faktur(self):
if not self.is_validated:
raise UserError('Harus di validate dulu')
for line in self.dunning_line:
invoice = line.invoice_id
if not invoice.date_kirim_tukar_faktur and self.date_kirim_tukar_faktur:
invoice.date_kirim_tukar_faktur = self.date_kirim_tukar_faktur
tukar_date = self.date_kirim_tukar_faktur
term = invoice.invoice_payment_term_id
add_days = 0
for line in term.line_ids:
add_days += line.days
due_date = tukar_date + timedelta(days=add_days)
invoice.invoice_date_due = due_date
if not invoice.resi_tukar_faktur:
invoice.resi_tukar_faktur = self.resi_tukar_faktur
if not invoice.date_terima_tukar_faktur and self.date_terima_tukar_faktur:
invoice.date_terima_tukar_faktur = self.date_terima_tukar_faktur
tukar_date = self.date_terima_tukar_faktur
term = invoice.invoice_payment_term_id
add_days = 0
for line in term.line_ids:
add_days += line.days
due_date = tukar_date + timedelta(days=add_days)
invoice.invoice_date_due = due_date
if not invoice.shipper_faktur_id:
invoice.shipper_faktur_id = self.shipper_faktur_id
self.notification = 'Berhasil copy tanggal terima faktur ke setiap invoice %s' % self.date_terima_tukar_faktur
def validate_dunning(self):
if not self.dunning_line:
raise UserError('Dunning Line masih kosong, generate dulu')
else:
self.is_validated = True
self.notification = 'Jangan lupa klik Copy Date jika sudah ada tanggal kirim / tanggal terima faktur'
def generate_dunning_line(self):
if self.is_validated:
raise UserError('Sudah di validate, tidak bisa digenerate ulang')
if self.dunning_line:
raise UserError('Harus hapus semua line jika ingin generate ulang')
if self.partner_id.parent_id:
raise UserError('Harus pilih parent company')
partners = []
partners += self.partner_id.child_ids
partners.append(self.partner_id)
for partner in partners:
query = [
('move_type', '=', 'out_invoice'),
('state', '=', 'posted'),
('partner_id', '=', partner.id),
('date_kirim_tukar_faktur', '=', False),
]
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([{
'dunning_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,
'due_date': invoice.invoice_date_due
}])
count += 1
_logger.info("Dunning Line generated %s" % count)
@api.model
def create(self, vals):
vals['number'] = self.env['ir.sequence'].next_by_code('dunning.run') or '0'
result = super(DunningRun, self).create(vals)
return result
class DunningRunLine(models.Model):
_name = 'dunning.run.line'
_description = 'Dunning Run Line'
# _order = 'dunning_id, 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')
date_invoice = fields.Date(string='Invoice Date')
# due_date = fields.Date(string='Due Date')
efaktur_id = fields.Many2one('vit.efaktur', string='Faktur Pajak')
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')
payment_term = fields.Many2one('account.payment.term', related='invoice_id.invoice_payment_term_id', string='Payment Term')
information_line = fields.Text(string='Information')
|