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, fields, api, _
from odoo.exceptions import ValidationError
from datetime import datetime
import base64
import xlrd
class UploadPayments(models.Model):
_name = "upload.payments"
_description = "Upload Payments"
_order = "create_date desc"
payments_lines = fields.One2many('upload.payments.line', 'upload_payments_id', string='Upload Payments Lines', auto_join=True, copy=False)
number = fields.Char('Number', copy=False)
date_upload = fields.Date('Upload Date', copy=False, default=fields.Date.context_today)
user_id = fields.Many2one('res.users', string='Created By', copy=False, default=lambda self: self.env.user.id)
excel_file = fields.Binary('Excel File', attachment=True)
filename = fields.Char('File Name')
state = fields.Selection([('draft', 'Draft'), ('running', 'Running'), ('done', 'Done')], default='draft')
@api.model
def create(self, vals):
vals['number'] = self.env['ir.sequence'].next_by_code('upload.payments') or '/'
return super(UploadPayments, self).create(vals)
def action_import_excel(self):
self.ensure_one()
if not self.excel_file:
raise ValidationError(_("Please upload an Excel file first."))
try:
file_content = base64.b64decode(self.excel_file)
workbook = xlrd.open_workbook(file_contents=file_content)
sheet = workbook.sheet_by_index(0)
except:
raise ValidationError(_("Invalid Excel file format."))
# Process Excel rows (skip header row if exists)
line_vals_list = []
for row in range(1, sheet.nrows):
try:
no_invoice = str(sheet.cell(row, 0).value).strip()
date_invoice = xlrd.xldate.xldate_as_datetime(sheet.cell(row, 1).value, workbook.datemode).date()
line_vals = {
'no_invoice': no_invoice,
'date_invoice': date_invoice,
}
line_vals_list.append((0, 0, line_vals))
except:
continue
# Update current record with lines
self.write({
'payments_lines': line_vals_list,
})
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Imported %s lines from Excel.') % len(line_vals_list),
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'},
}
}
def action_create_payments(self):
self.state = 'running'
def queue_job(self, limit=100):
payments = self.env['upload.payments'].search([ ('state', '=', 'running') ], limit=1, order='id asc')
for payment in payments:
payment.date_upload = fields.Datetime.now()
lines = payment.payments_lines.filtered(
lambda l: not l.payment_id and not l.is_queued
)[:limit]
existing_jobs = self.env['queue.job'].search([
('model_name', '=', 'upload.payments.line'),
('method_name', '=', 'action_create_payments'),
('res_id', 'in', lines.ids),
('state', '!=', 'error'),
])
existing_res_ids = set(existing_jobs.mapped('res_id'))
for line in lines:
if line.id in existing_res_ids:
continue
self.env['queue.job'].create({
'name': f'Upload Payments {line.no_invoice}',
'model_name': 'upload.payments.line',
'method_name': 'action_create_payments',
'res_id': line.id,
})
line.is_queued = True
self.env.cr.commit()
class UploadPaymentsLine(models.Model):
_name = "upload.payments.line"
_description = "Upload Payments Line"
_inherit = ['mail.thread']
upload_payments_id = fields.Many2one('upload.payments', string='Upload Payments')
no_invoice = fields.Char('Invoice Number', required=True)
date_invoice = fields.Date('Invoice Date', required=True)
move_id = fields.Many2one('account.move', string='Invoice')
payment_id = fields.Many2one('account.payment', string='Created Payment')
message_error = fields.Text('Error Message')
is_queued = fields.Boolean(default=False)
def action_create_payments(self):
self.ensure_one()
try:
invoice = self.env['account.move'].search([
('invoice_marketplace', '=', self.no_invoice),
('state', '=', 'posted'),
('payment_state', '!=', 'paid'),
], limit=1)
if not invoice:
raise ValidationError('Invoice tidak ditemukan / sudah lunas')
payment = invoice._register_payment_automatically(self.date_invoice)
self.payment_id = payment.id
self.message_error = 'DONE'
except Exception as e:
self.message_error = str(e)
finally:
self._check_parent_done()
def _check_parent_done(self):
upload = self.upload_payments_id
if not upload:
return
unfinished = upload.payments_lines.filtered(
lambda l: not l.is_queued
)
if not unfinished:
upload.state = 'done'
|