odoo-addon-l10n-it-riba-oca 18.0.1.0.0.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/l10n_it_riba_oca/README.rst +175 -0
- odoo/addons/l10n_it_riba_oca/__init__.py +9 -0
- odoo/addons/l10n_it_riba_oca/__manifest__.py +59 -0
- odoo/addons/l10n_it_riba_oca/data/riba_sequence.xml +14 -0
- odoo/addons/l10n_it_riba_oca/demo/riba_demo.xml +39 -0
- odoo/addons/l10n_it_riba_oca/hooks.py +17 -0
- odoo/addons/l10n_it_riba_oca/i18n/it.po +1686 -0
- odoo/addons/l10n_it_riba_oca/i18n/l10n_it_riba.pot +1573 -0
- odoo/addons/l10n_it_riba_oca/i18n/l10n_it_riba_oca.pot +1554 -0
- odoo/addons/l10n_it_riba_oca/migrations/18.0.1.0.0/pre-migrate.py +16 -0
- odoo/addons/l10n_it_riba_oca/models/__init__.py +14 -0
- odoo/addons/l10n_it_riba_oca/models/account.py +563 -0
- odoo/addons/l10n_it_riba_oca/models/account_config.py +35 -0
- odoo/addons/l10n_it_riba_oca/models/ir_ui_menu.py +27 -0
- odoo/addons/l10n_it_riba_oca/models/partner.py +35 -0
- odoo/addons/l10n_it_riba_oca/models/riba.py +560 -0
- odoo/addons/l10n_it_riba_oca/models/riba_config.py +120 -0
- odoo/addons/l10n_it_riba_oca/readme/CONFIGURE.md +33 -0
- odoo/addons/l10n_it_riba_oca/readme/CONTRIBUTORS.md +17 -0
- odoo/addons/l10n_it_riba_oca/readme/DESCRIPTION.md +3 -0
- odoo/addons/l10n_it_riba_oca/readme/USAGE.md +35 -0
- odoo/addons/l10n_it_riba_oca/report/__init__.py +4 -0
- odoo/addons/l10n_it_riba_oca/report/report.xml +16 -0
- odoo/addons/l10n_it_riba_oca/report/slip_qweb.py +18 -0
- odoo/addons/l10n_it_riba_oca/security/ir.model.access.csv +23 -0
- odoo/addons/l10n_it_riba_oca/security/riba_security.xml +34 -0
- odoo/addons/l10n_it_riba_oca/static/description/icon.png +0 -0
- odoo/addons/l10n_it_riba_oca/static/description/index.html +512 -0
- odoo/addons/l10n_it_riba_oca/tests/__init__.py +10 -0
- odoo/addons/l10n_it_riba_oca/tests/riba_common.py +339 -0
- odoo/addons/l10n_it_riba_oca/tests/test_account_move.py +54 -0
- odoo/addons/l10n_it_riba_oca/tests/test_menu.py +51 -0
- odoo/addons/l10n_it_riba_oca/tests/test_riba.py +905 -0
- odoo/addons/l10n_it_riba_oca/views/account_config_view.xml +46 -0
- odoo/addons/l10n_it_riba_oca/views/account_view.xml +205 -0
- odoo/addons/l10n_it_riba_oca/views/configuration_view.xml +94 -0
- odoo/addons/l10n_it_riba_oca/views/partner_view.xml +29 -0
- odoo/addons/l10n_it_riba_oca/views/riba_detail_view.xml +97 -0
- odoo/addons/l10n_it_riba_oca/views/riba_view.xml +296 -0
- odoo/addons/l10n_it_riba_oca/views/slip_report.xml +149 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_credit.xml +46 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_due_date_settlement.xml +37 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_past_due.xml +67 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_presentation.xml +48 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_riba_file_export.xml +33 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_riba_issue.xml +46 -0
- odoo/addons/l10n_it_riba_oca/views/wizard_riba_payment_date.xml +45 -0
- odoo/addons/l10n_it_riba_oca/wizard/__init__.py +16 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_credit.py +280 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_due_date_settlement.py +24 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_past_due.py +319 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_presentation_riba.py +47 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_file_export.py +429 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_issue.py +143 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_multiple_payment.py +107 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_multiple_payment_views.xml +46 -0
- odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_payment_date.py +31 -0
- odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/METADATA +197 -0
- odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/RECORD +61 -0
- odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/WHEEL +5 -0
- odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# Copyright (C) 2011-2012 Associazione OpenERP Italia
|
|
2
|
+
# (<http://www.odoo-italia.org>).
|
|
3
|
+
# Copyright (C) 2012-2017 Lorenzo Battistini - Agile Business Group
|
|
4
|
+
# Thanks to Antonio de Vincentiis http://www.devincentiis.it/ ,
|
|
5
|
+
# GAzie http://gazie.sourceforge.net/
|
|
6
|
+
# and Cecchi s.r.l http://www.cecchi.com/
|
|
7
|
+
# Copyright 2023 Simone Rubino - Aion Tech
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import base64
|
|
11
|
+
import datetime
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
from unidecode import unidecode
|
|
15
|
+
|
|
16
|
+
from odoo import fields, models
|
|
17
|
+
from odoo.exceptions import UserError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class RibaStorage:
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.sequence = 0
|
|
23
|
+
self.creditor_bank = 0
|
|
24
|
+
self.sia = 0
|
|
25
|
+
self.riba_date = 0
|
|
26
|
+
self.support = 0
|
|
27
|
+
self.riba_total = 0
|
|
28
|
+
self.riba_creditor = 0
|
|
29
|
+
self.riba_description = ""
|
|
30
|
+
self.riba_debtor_city_province = ""
|
|
31
|
+
self.currency = 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class RibaFileExport(models.TransientModel):
|
|
35
|
+
"""
|
|
36
|
+
***************************************************************************
|
|
37
|
+
Questa classe genera il file RiBa standard ABI-CBI passando alla funzione
|
|
38
|
+
"createFile" i due array di seguito specificati:
|
|
39
|
+
$header = array monodimensionale con i seguenti index:
|
|
40
|
+
[0] = credit_sia variabile lunghezza 5 alfanumerico
|
|
41
|
+
[1] = credit_abi assuntrice variabile lunghezza 5 numerico
|
|
42
|
+
[2] = credit_cab assuntrice variabile lunghezza 5 numerico
|
|
43
|
+
[3] = credit_account conto variabile lunghezza 10 alfanumerico
|
|
44
|
+
[4] = creation_date variabile lunghezza 6 numerico formato
|
|
45
|
+
GGMMAA
|
|
46
|
+
[5] = support_name variabile lunghezza 20 alfanumerico
|
|
47
|
+
[6] = currency_code variabile lunghezza 1 alfanumerico
|
|
48
|
+
opzionale default "E"
|
|
49
|
+
[7] = company_name nome ragione sociale creditore variabile
|
|
50
|
+
lunghezza 24 alfanumerico
|
|
51
|
+
[8] = creditor_address variabile lunghezza 24 alfanumerico
|
|
52
|
+
[9] = creditor_zip_city variabile lunghezza 24 alfanumerico
|
|
53
|
+
[10] = ref (definizione attivita) creditore
|
|
54
|
+
[11] = codice fiscale/partita iva creditore alfanumerico
|
|
55
|
+
opzionale
|
|
56
|
+
$ribas = array bidimensionale con i seguenti index:
|
|
57
|
+
[0] = numero ricevuta lunghezza 10 numerico
|
|
58
|
+
[1] = data scadenza lunghezza 6 numerico
|
|
59
|
+
[2] = importo in centesimi di euro
|
|
60
|
+
[3] = nome debitore lunghezza 60 alfanumerico
|
|
61
|
+
[4] = codice fiscale/partita iva debitore lunghezza 16
|
|
62
|
+
alfanumerico
|
|
63
|
+
[5] = indirizzo debitore lunghezza 30 alfanumerico
|
|
64
|
+
[6] = cap debitore lunghezza 5 numerico
|
|
65
|
+
[7] = citta debitore alfanumerico
|
|
66
|
+
[8] = debitor_province debitore alfanumerico
|
|
67
|
+
[9] = abi banca domiciliataria lunghezza 5 numerico
|
|
68
|
+
[10] = cab banca domiciliataria lunghezza 5 numerico
|
|
69
|
+
[11] = descrizione banca domiciliataria lunghezza 50
|
|
70
|
+
alfanumerico
|
|
71
|
+
[12] = codice cliente attribuito dal creditore lunghezza
|
|
72
|
+
16 numerico
|
|
73
|
+
[13] = numero fattura lunghezza 40 alfanumerico
|
|
74
|
+
[14] = data effettiva della fattura
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
_name = "riba.file.export"
|
|
78
|
+
_description = "RiBa File Export Wizard"
|
|
79
|
+
_ribaStorage = RibaStorage()
|
|
80
|
+
|
|
81
|
+
def _RecordIB(
|
|
82
|
+
self,
|
|
83
|
+
sia_creditor_bank,
|
|
84
|
+
abi_creditor_bank,
|
|
85
|
+
creation_date,
|
|
86
|
+
support_name,
|
|
87
|
+
currency_code,
|
|
88
|
+
): # record di testa
|
|
89
|
+
self._ribaStorage.sia = sia_creditor_bank.rjust(5, "0")
|
|
90
|
+
self._ribaStorage.creditor_bank = abi_creditor_bank.rjust(5, "0")
|
|
91
|
+
self._ribaStorage.riba_date = creation_date.rjust(6, "0")
|
|
92
|
+
self._ribaStorage.currency = currency_code[0:1]
|
|
93
|
+
self._ribaStorage.support = support_name.ljust(20, " ")
|
|
94
|
+
return (
|
|
95
|
+
" IB"
|
|
96
|
+
+ self._ribaStorage.sia
|
|
97
|
+
+ self._ribaStorage.creditor_bank
|
|
98
|
+
+ self._ribaStorage.riba_date
|
|
99
|
+
+ self._ribaStorage.support
|
|
100
|
+
+ " " * 74
|
|
101
|
+
+ self._ribaStorage.currency
|
|
102
|
+
+ " " * 6
|
|
103
|
+
+ "\r\n"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def _Record14(
|
|
107
|
+
self,
|
|
108
|
+
due_date,
|
|
109
|
+
amount,
|
|
110
|
+
abi_creditor_bank,
|
|
111
|
+
cab_creditor_bank,
|
|
112
|
+
account,
|
|
113
|
+
abi_debtor_bank,
|
|
114
|
+
cab_debtor_bank,
|
|
115
|
+
sia_credit,
|
|
116
|
+
customer_code,
|
|
117
|
+
):
|
|
118
|
+
self._ribaStorage.riba_total += amount
|
|
119
|
+
return (
|
|
120
|
+
" 14"
|
|
121
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
122
|
+
+ " " * 12
|
|
123
|
+
+ due_date
|
|
124
|
+
+ "30000"
|
|
125
|
+
+ str(int(round(amount * 100))).rjust(13, "0")
|
|
126
|
+
+ "-"
|
|
127
|
+
+ abi_creditor_bank.rjust(5, "0")
|
|
128
|
+
+ cab_creditor_bank.rjust(5, "0")
|
|
129
|
+
+ account.ljust(12, "0")
|
|
130
|
+
+ abi_debtor_bank.rjust(5, "0")
|
|
131
|
+
+ cab_debtor_bank.rjust(5, "0")
|
|
132
|
+
+ " " * 12
|
|
133
|
+
+ str(sia_credit).rjust(5, "0")
|
|
134
|
+
+ "4"
|
|
135
|
+
+ customer_code.ljust(16)
|
|
136
|
+
+ " " * 6
|
|
137
|
+
+ self._ribaStorage.currency
|
|
138
|
+
+ "\r\n"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def _Record20(
|
|
142
|
+
self,
|
|
143
|
+
creditor_company_name,
|
|
144
|
+
creditor_address,
|
|
145
|
+
creditor_zip_city,
|
|
146
|
+
creditor_ref,
|
|
147
|
+
):
|
|
148
|
+
self._ribaStorage.riba_creditor = creditor_company_name.ljust(24)
|
|
149
|
+
return (
|
|
150
|
+
" 20"
|
|
151
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
152
|
+
+ self._ribaStorage.riba_creditor[0:24]
|
|
153
|
+
+ creditor_address.ljust(24)[0:24]
|
|
154
|
+
+ creditor_zip_city.ljust(24)[0:24]
|
|
155
|
+
+ creditor_ref.ljust(24)[0:24]
|
|
156
|
+
+ " " * 14
|
|
157
|
+
+ "\r\n"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def _Record30(self, debtor_name, debtor_fiscalcode):
|
|
161
|
+
return (
|
|
162
|
+
" 30"
|
|
163
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
164
|
+
+ debtor_name.ljust(60)[0:60]
|
|
165
|
+
+ debtor_fiscalcode.ljust(16, " ")
|
|
166
|
+
+ " " * 34
|
|
167
|
+
+ "\r\n"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def _Record40(
|
|
171
|
+
self,
|
|
172
|
+
debtor_address,
|
|
173
|
+
debtor_zip,
|
|
174
|
+
debtor_city,
|
|
175
|
+
debtor_province,
|
|
176
|
+
debtor_bank_description="",
|
|
177
|
+
):
|
|
178
|
+
self._ribaStorage.riba_debtor_city_province = (
|
|
179
|
+
debtor_city + debtor_province.rjust(25 - len(debtor_city), " ")
|
|
180
|
+
)
|
|
181
|
+
return (
|
|
182
|
+
" 40"
|
|
183
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
184
|
+
+ debtor_address.ljust(30)[0:30]
|
|
185
|
+
+ str(debtor_zip).rjust(5, "0")
|
|
186
|
+
+ self._ribaStorage.riba_debtor_city_province
|
|
187
|
+
+ debtor_bank_description.ljust(50)[0:50]
|
|
188
|
+
+ "\r\n"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def _Record50(
|
|
192
|
+
self, debit_amount, invoice_ref, invoice_date, creditor_vat_number, cig, cup
|
|
193
|
+
):
|
|
194
|
+
self._ribaStorage.riba_description = (
|
|
195
|
+
cig
|
|
196
|
+
+ cup
|
|
197
|
+
+ "PER LA FATTURA N. "
|
|
198
|
+
+ invoice_ref
|
|
199
|
+
+ " DEL "
|
|
200
|
+
+ invoice_date
|
|
201
|
+
+ " IMP "
|
|
202
|
+
+ str(debit_amount)
|
|
203
|
+
)
|
|
204
|
+
return (
|
|
205
|
+
" 50"
|
|
206
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
207
|
+
+ self._ribaStorage.riba_description.ljust(80)[0:80]
|
|
208
|
+
+ " " * 10
|
|
209
|
+
+ creditor_vat_number.ljust(16, " ")
|
|
210
|
+
+ " " * 4
|
|
211
|
+
+ "\r\n"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def _Record51(self, creditor_receipt_number):
|
|
215
|
+
return (
|
|
216
|
+
" 51"
|
|
217
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
218
|
+
+ str(creditor_receipt_number).rjust(10, "0")
|
|
219
|
+
+ self._ribaStorage.riba_creditor[0:20]
|
|
220
|
+
+ " " * 80
|
|
221
|
+
+ "\r\n"
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def _Record70(self):
|
|
225
|
+
return (
|
|
226
|
+
" 70" + str(self._ribaStorage.sequence).rjust(7, "0") + " " * 110 + "\r\n"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
def _RecordEF(self): # record di coda
|
|
230
|
+
return (
|
|
231
|
+
" EF"
|
|
232
|
+
+ self._ribaStorage.sia
|
|
233
|
+
+ self._ribaStorage.creditor_bank
|
|
234
|
+
+ self._ribaStorage.riba_date
|
|
235
|
+
+ self._ribaStorage.support
|
|
236
|
+
+ " " * 6
|
|
237
|
+
+ str(self._ribaStorage.sequence).rjust(7, "0")
|
|
238
|
+
+ str(int(round(self._ribaStorage.riba_total * 100))).rjust(15, "0")
|
|
239
|
+
+ "0" * 15
|
|
240
|
+
+ str(int(self._ribaStorage.sequence) * 7 + 2).rjust(7, "0")
|
|
241
|
+
+ " " * 24
|
|
242
|
+
+ self._ribaStorage.currency
|
|
243
|
+
+ " " * 6
|
|
244
|
+
+ "\r\n"
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
def _createFile(self, header, ribas):
|
|
248
|
+
accumulator = self._RecordIB(
|
|
249
|
+
header[0],
|
|
250
|
+
header[1],
|
|
251
|
+
header[4],
|
|
252
|
+
header[5],
|
|
253
|
+
header[6],
|
|
254
|
+
)
|
|
255
|
+
for value in ribas: # estraggo le ricevute dall'array
|
|
256
|
+
self._ribaStorage.sequence = self._ribaStorage.sequence + 1
|
|
257
|
+
accumulator = accumulator + self._Record14(
|
|
258
|
+
value[1],
|
|
259
|
+
value[2],
|
|
260
|
+
header[1],
|
|
261
|
+
header[2],
|
|
262
|
+
header[3],
|
|
263
|
+
value[9],
|
|
264
|
+
value[10],
|
|
265
|
+
header[0],
|
|
266
|
+
value[12],
|
|
267
|
+
)
|
|
268
|
+
accumulator = accumulator + self._Record20(
|
|
269
|
+
header[7], header[8], header[9], header[10]
|
|
270
|
+
)
|
|
271
|
+
accumulator = accumulator + self._Record30(value[3], value[4])
|
|
272
|
+
accumulator = accumulator + self._Record40(
|
|
273
|
+
value[5], value[6], value[7], value[8], value[11]
|
|
274
|
+
)
|
|
275
|
+
accumulator = accumulator + self._Record50(
|
|
276
|
+
value[2], value[13], value[14], header[11], value[15], value[16]
|
|
277
|
+
)
|
|
278
|
+
accumulator = accumulator + self._Record51(value[0])
|
|
279
|
+
accumulator = accumulator + self._Record70()
|
|
280
|
+
accumulator = accumulator + self._RecordEF()
|
|
281
|
+
self._ribaStorage.sequence = 0
|
|
282
|
+
self._ribaStorage.riba_total = 0
|
|
283
|
+
return accumulator
|
|
284
|
+
|
|
285
|
+
def act_getfile(self):
|
|
286
|
+
active_ids = self.env.context.get("active_ids", [])
|
|
287
|
+
order_obj = self.env["riba.slip"].browse(active_ids)[0]
|
|
288
|
+
credit_bank = order_obj.config_id.bank_id
|
|
289
|
+
company_name = order_obj.config_id.company_id.partner_id.name
|
|
290
|
+
if not credit_bank.acc_number:
|
|
291
|
+
raise UserError(self.env._("No IBAN specified."))
|
|
292
|
+
# remove spaces automatically added by odoo
|
|
293
|
+
credit_iban = credit_bank.acc_number.replace(" ", "")
|
|
294
|
+
credit_abi = credit_iban[5:10]
|
|
295
|
+
credit_cab = credit_iban[10:15]
|
|
296
|
+
credit_account = credit_iban[-12:]
|
|
297
|
+
if not credit_bank.codice_sia:
|
|
298
|
+
raise UserError(
|
|
299
|
+
self.env._(
|
|
300
|
+
"No SIA Code specified for %(company)s",
|
|
301
|
+
company=company_name,
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
credit_sia = credit_bank.codice_sia
|
|
305
|
+
issued_date = datetime.datetime.now().strftime("%d%m%y")
|
|
306
|
+
support_name = datetime.datetime.now().strftime("%d%m%y%H%M%S") + credit_sia
|
|
307
|
+
creditor_address = order_obj.config_id.company_id.partner_id
|
|
308
|
+
creditor_city = unidecode(creditor_address.city or "")
|
|
309
|
+
if (
|
|
310
|
+
not order_obj.config_id.company_id.partner_id.vat
|
|
311
|
+
and not order_obj.config_id.company_id.partner_id.l10n_it_codice_fiscale
|
|
312
|
+
):
|
|
313
|
+
raise UserError(
|
|
314
|
+
self.env._(
|
|
315
|
+
"No VAT or Fiscal Code specified for %(company)s",
|
|
316
|
+
company=company_name,
|
|
317
|
+
)
|
|
318
|
+
)
|
|
319
|
+
array_header = [
|
|
320
|
+
credit_sia,
|
|
321
|
+
credit_abi,
|
|
322
|
+
credit_cab,
|
|
323
|
+
credit_account,
|
|
324
|
+
issued_date,
|
|
325
|
+
support_name,
|
|
326
|
+
"E",
|
|
327
|
+
unidecode(company_name),
|
|
328
|
+
unidecode(creditor_address.street or ""),
|
|
329
|
+
creditor_address.zip or "" + " " + creditor_city,
|
|
330
|
+
unidecode(order_obj.config_id.company_id.partner_id.ref or ""),
|
|
331
|
+
(
|
|
332
|
+
order_obj.config_id.company_id.partner_id.vat
|
|
333
|
+
and order_obj.config_id.company_id.partner_id.vat[2:]
|
|
334
|
+
or order_obj.config_id.company_id.partner_id.l10n_it_codice_fiscale
|
|
335
|
+
),
|
|
336
|
+
]
|
|
337
|
+
array_riba = []
|
|
338
|
+
for line in order_obj.line_ids:
|
|
339
|
+
debit_bank = line.bank_id
|
|
340
|
+
debtor_address = line.partner_id
|
|
341
|
+
debtor_street = unidecode(debtor_address.street or "")
|
|
342
|
+
debtor_zip = debtor_address.zip or ""
|
|
343
|
+
if debit_bank.bank_abi and debit_bank.bank_cab:
|
|
344
|
+
debit_abi = debit_bank.bank_abi
|
|
345
|
+
debit_cab = debit_bank.bank_cab
|
|
346
|
+
elif debit_bank.acc_number:
|
|
347
|
+
debit_iban = debit_bank.acc_number.replace(" ", "")
|
|
348
|
+
debit_abi = debit_iban[5:10]
|
|
349
|
+
debit_cab = debit_iban[10:15]
|
|
350
|
+
else:
|
|
351
|
+
raise UserError(
|
|
352
|
+
self.env._(
|
|
353
|
+
"No IBAN or ABI/CAB specified for %(partner)s",
|
|
354
|
+
partner=line.partner_id.name,
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
debtor_city = unidecode(
|
|
358
|
+
debtor_address.city and debtor_address.city.ljust(23)[0:23] or ""
|
|
359
|
+
)
|
|
360
|
+
debtor_province = unidecode(
|
|
361
|
+
debtor_address.state_id and debtor_address.state_id.code or ""
|
|
362
|
+
)
|
|
363
|
+
if not line.due_date: # ??? VERIFICARE
|
|
364
|
+
due_date = "000000"
|
|
365
|
+
else:
|
|
366
|
+
due_date = line.due_date.strftime("%d%m%y")
|
|
367
|
+
|
|
368
|
+
if not line.partner_id.vat and not line.partner_id.l10n_it_codice_fiscale:
|
|
369
|
+
raise UserError(
|
|
370
|
+
self.env._(
|
|
371
|
+
"No VAT or Fiscal Code specified for %(partner)s",
|
|
372
|
+
partner=line.partner_id.name,
|
|
373
|
+
)
|
|
374
|
+
)
|
|
375
|
+
riba = [
|
|
376
|
+
line.sequence,
|
|
377
|
+
due_date,
|
|
378
|
+
line.amount,
|
|
379
|
+
# using regex we remove chars outside letters, numbers, space,
|
|
380
|
+
# dot and comma because, special chars cause errors.
|
|
381
|
+
re.sub(r"[^\w\s,.]+", "", line.partner_id.name)[:60],
|
|
382
|
+
line.partner_id.vat
|
|
383
|
+
and line.partner_id.vat[2:]
|
|
384
|
+
or line.partner_id.l10n_it_codice_fiscale,
|
|
385
|
+
re.sub(r"[^\w\s,.]+", "", debtor_street)[:30],
|
|
386
|
+
debtor_zip[:5],
|
|
387
|
+
debtor_city[:24],
|
|
388
|
+
debtor_province,
|
|
389
|
+
debit_abi,
|
|
390
|
+
debit_cab,
|
|
391
|
+
unidecode(debit_bank.bank_name and debit_bank.bank_name[:50] or ""),
|
|
392
|
+
unidecode(line.partner_id.ref and line.partner_id.ref[:16] or ""),
|
|
393
|
+
unidecode(line.invoice_number[:40]),
|
|
394
|
+
line.invoice_date,
|
|
395
|
+
unidecode(f"CIG: {line.cig if line.cig else ''} "),
|
|
396
|
+
"",
|
|
397
|
+
unidecode(f"CUP: {line.cup if line.cup else ''} "),
|
|
398
|
+
"",
|
|
399
|
+
]
|
|
400
|
+
array_riba.append(riba)
|
|
401
|
+
|
|
402
|
+
out = base64.encodebytes(
|
|
403
|
+
self._createFile(array_header, array_riba).encode("ascii", errors="replace")
|
|
404
|
+
)
|
|
405
|
+
self.write(
|
|
406
|
+
{"state": "get", "riba_txt": out, "file_name": f"{order_obj.name}.txt"}
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
view_rec = self.env.ref("l10n_it_riba_oca.wizard_riba_file_export")
|
|
410
|
+
view_id = view_rec.id if view_rec else False
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
"view_id": [view_id],
|
|
414
|
+
"view_mode": "form",
|
|
415
|
+
"res_model": "riba.file.export",
|
|
416
|
+
"res_id": self.id,
|
|
417
|
+
"type": "ir.actions.act_window",
|
|
418
|
+
"target": "new",
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
state = fields.Selection(
|
|
422
|
+
(
|
|
423
|
+
("choose", "choose"), # choose accounts
|
|
424
|
+
("get", "get"), # get the file
|
|
425
|
+
),
|
|
426
|
+
default="choose",
|
|
427
|
+
)
|
|
428
|
+
riba_txt = fields.Binary("File", readonly=True)
|
|
429
|
+
file_name = fields.Char(readonly=True)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Copyright (C) 2012 Andrea Cometa.
|
|
2
|
+
# Email: info@andreacometa.it
|
|
3
|
+
# Web site: http://www.andreacometa.it
|
|
4
|
+
# Copyright (C) 2012 Associazione OpenERP Italia
|
|
5
|
+
# (<http://www.odoo-italia.org>).
|
|
6
|
+
# Copyright (C) 2012-2017 Lorenzo Battistini - Agile Business Group
|
|
7
|
+
# Copyright 2023 Simone Rubino - Aion Tech
|
|
8
|
+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
9
|
+
|
|
10
|
+
from odoo import fields, models
|
|
11
|
+
from odoo.exceptions import UserError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# -------------------------------------------------------
|
|
15
|
+
# RIBA ISSUE
|
|
16
|
+
# -------------------------------------------------------
|
|
17
|
+
class RibaIssue(models.TransientModel):
|
|
18
|
+
_name = "riba.issue"
|
|
19
|
+
_description = "RiBa Issue"
|
|
20
|
+
configuration_id = fields.Many2one(
|
|
21
|
+
"riba.configuration", string="Configuration", required=True
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def create_list(self):
|
|
25
|
+
def create_rdl(
|
|
26
|
+
countme, bank_id, rd_id, date_maturity, partner_id, acceptance_account_id
|
|
27
|
+
):
|
|
28
|
+
rdl = {
|
|
29
|
+
"sequence": countme,
|
|
30
|
+
"bank_id": bank_id,
|
|
31
|
+
"slip_id": rd_id,
|
|
32
|
+
"due_date": date_maturity,
|
|
33
|
+
"partner_id": partner_id,
|
|
34
|
+
"state": "draft",
|
|
35
|
+
"acceptance_account_id": acceptance_account_id,
|
|
36
|
+
}
|
|
37
|
+
return riba_list_line.create(rdl)
|
|
38
|
+
|
|
39
|
+
self.ensure_one()
|
|
40
|
+
# Qui creiamo la distinta
|
|
41
|
+
# wizard_obj = self.browse(cr, uid, ids)[0]
|
|
42
|
+
# active_ids = context and context.get('active_ids', [])
|
|
43
|
+
riba_list = self.env["riba.slip"]
|
|
44
|
+
riba_list_line = self.env["riba.slip.line"]
|
|
45
|
+
riba_list_move_line = self.env["riba.slip.move.line"]
|
|
46
|
+
move_line_obj = self.env["account.move.line"]
|
|
47
|
+
|
|
48
|
+
# create distinta
|
|
49
|
+
rd = {
|
|
50
|
+
"name": self.env["ir.sequence"].next_by_code("seq.riba.slip"),
|
|
51
|
+
"config_id": self.configuration_id.id,
|
|
52
|
+
"user_id": self._uid,
|
|
53
|
+
"date_created": fields.Date.context_today(self),
|
|
54
|
+
}
|
|
55
|
+
rd_id = riba_list.create(rd).id
|
|
56
|
+
|
|
57
|
+
# group by partner and due date
|
|
58
|
+
grouped_lines = {}
|
|
59
|
+
move_lines = move_line_obj.search([("id", "in", self._context["active_ids"])])
|
|
60
|
+
if any(line.parent_state != "posted" for line in move_lines):
|
|
61
|
+
raise UserError(
|
|
62
|
+
self.env._("It is possible to issue C/O for posted move only!")
|
|
63
|
+
)
|
|
64
|
+
do_group_riba = True
|
|
65
|
+
if len({f"{x.l10n_it_cig}{x.l10n_it_cup}" for x in move_lines.move_id}) > 1:
|
|
66
|
+
do_group_riba = False
|
|
67
|
+
if do_group_riba:
|
|
68
|
+
for move_line in move_lines:
|
|
69
|
+
if move_line.partner_id.group_riba:
|
|
70
|
+
if not grouped_lines.get(
|
|
71
|
+
(move_line.partner_id.id, move_line.date_maturity), False
|
|
72
|
+
):
|
|
73
|
+
grouped_lines[
|
|
74
|
+
(move_line.partner_id.id, move_line.date_maturity)
|
|
75
|
+
] = []
|
|
76
|
+
grouped_lines[
|
|
77
|
+
(move_line.partner_id.id, move_line.date_maturity)
|
|
78
|
+
].append(move_line)
|
|
79
|
+
|
|
80
|
+
# create lines
|
|
81
|
+
countme = 1
|
|
82
|
+
|
|
83
|
+
for move_line in move_lines:
|
|
84
|
+
if move_line.move_id.riba_partner_bank_id:
|
|
85
|
+
bank_id = move_line.move_id.riba_partner_bank_id
|
|
86
|
+
else:
|
|
87
|
+
raise UserError(
|
|
88
|
+
self.env._(
|
|
89
|
+
"No bank has been specified for invoice %(invoice)s",
|
|
90
|
+
invoice=move_line.move_id.name,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
if move_line.partner_id.group_riba: # and do_group_riba:
|
|
94
|
+
for key in grouped_lines:
|
|
95
|
+
if (
|
|
96
|
+
key[0] == move_line.partner_id.id
|
|
97
|
+
and key[1] == move_line.date_maturity
|
|
98
|
+
):
|
|
99
|
+
rdl_id = create_rdl(
|
|
100
|
+
countme,
|
|
101
|
+
bank_id.id,
|
|
102
|
+
rd_id,
|
|
103
|
+
move_line.date_maturity,
|
|
104
|
+
move_line.partner_id.id,
|
|
105
|
+
self.configuration_id.acceptance_account_id.id,
|
|
106
|
+
).id
|
|
107
|
+
# total = 0.0
|
|
108
|
+
# invoice_date_group = ''
|
|
109
|
+
for grouped_line in grouped_lines[key]:
|
|
110
|
+
riba_list_move_line.create(
|
|
111
|
+
{
|
|
112
|
+
"riba_line_id": rdl_id,
|
|
113
|
+
"amount": grouped_line.amount_residual,
|
|
114
|
+
"move_line_id": grouped_line.id,
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
del grouped_lines[key]
|
|
118
|
+
break
|
|
119
|
+
else:
|
|
120
|
+
rdl_id = create_rdl(
|
|
121
|
+
countme,
|
|
122
|
+
bank_id.id,
|
|
123
|
+
rd_id,
|
|
124
|
+
move_line.date_maturity,
|
|
125
|
+
move_line.partner_id.id,
|
|
126
|
+
self.configuration_id.acceptance_account_id.id,
|
|
127
|
+
).id
|
|
128
|
+
riba_list_move_line.create(
|
|
129
|
+
{
|
|
130
|
+
"riba_line_id": rdl_id,
|
|
131
|
+
"amount": move_line.amount_residual,
|
|
132
|
+
"move_line_id": move_line.id,
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
countme += 1
|
|
137
|
+
|
|
138
|
+
# ----- show slip form
|
|
139
|
+
action_vals = self.env["ir.actions.act_window"]._for_xml_id(
|
|
140
|
+
"l10n_it_riba_oca.slip_riba_action"
|
|
141
|
+
)
|
|
142
|
+
action_vals["res_id"] = rd_id
|
|
143
|
+
return action_vals
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Copyright 2024 Simone Rubino - Aion Tech
|
|
2
|
+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
|
3
|
+
|
|
4
|
+
from odoo import api, fields, models
|
|
5
|
+
from odoo.exceptions import UserError
|
|
6
|
+
from odoo.tools.safe_eval import safe_eval
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RibaPaymentMultiple(models.TransientModel):
|
|
10
|
+
_name = "riba.payment.multiple"
|
|
11
|
+
_description = "Pay multiple RiBa lines"
|
|
12
|
+
|
|
13
|
+
riba_ids = fields.Many2many(
|
|
14
|
+
comodel_name="riba.slip",
|
|
15
|
+
default=lambda model: model.env.context["active_ids"],
|
|
16
|
+
readonly=True,
|
|
17
|
+
required=True,
|
|
18
|
+
string="Selected RiBas",
|
|
19
|
+
)
|
|
20
|
+
payment_date = fields.Date(
|
|
21
|
+
compute="_compute_payment_date",
|
|
22
|
+
help="Defaults to the 'Payment date' in the RiBas.\n"
|
|
23
|
+
"If empty, the due date in each line will be used.",
|
|
24
|
+
readonly=False,
|
|
25
|
+
store=True,
|
|
26
|
+
)
|
|
27
|
+
riba_line_ids = fields.Many2many(
|
|
28
|
+
comodel_name="riba.slip.line",
|
|
29
|
+
compute="_compute_riba_line_ids",
|
|
30
|
+
domain="["
|
|
31
|
+
"'&',"
|
|
32
|
+
"('slip_id', 'in', riba_ids),"
|
|
33
|
+
# The following domain must match the domain
|
|
34
|
+
# that shows the 'Pay' button in each RiBa line
|
|
35
|
+
"'|',"
|
|
36
|
+
"'&',"
|
|
37
|
+
"('type', '=', 'sbf'),"
|
|
38
|
+
"('state', '=', 'credited'),"
|
|
39
|
+
"'&',"
|
|
40
|
+
"('type', '=', 'incasso'),"
|
|
41
|
+
"('state', '=', 'confirmed'),"
|
|
42
|
+
"]",
|
|
43
|
+
readonly=False,
|
|
44
|
+
store=True,
|
|
45
|
+
string="RiBa lines to be paid",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
@api.depends(
|
|
49
|
+
"riba_ids.date_paid",
|
|
50
|
+
)
|
|
51
|
+
def _compute_payment_date(self):
|
|
52
|
+
for wizard in self:
|
|
53
|
+
ribas = wizard.riba_ids
|
|
54
|
+
wizard.payment_date = max(ribas.mapped("date_paid"))
|
|
55
|
+
|
|
56
|
+
@api.depends(
|
|
57
|
+
"riba_ids.line_ids",
|
|
58
|
+
)
|
|
59
|
+
def _compute_riba_line_ids(self):
|
|
60
|
+
riba_lines_domain = self.fields_get(
|
|
61
|
+
allfields=[
|
|
62
|
+
"riba_line_ids",
|
|
63
|
+
],
|
|
64
|
+
attributes=[
|
|
65
|
+
"domain",
|
|
66
|
+
],
|
|
67
|
+
)["riba_line_ids"]["domain"]
|
|
68
|
+
for wizard in self:
|
|
69
|
+
ribas = wizard.riba_ids
|
|
70
|
+
wizard_riba_lines_domain = safe_eval(
|
|
71
|
+
riba_lines_domain,
|
|
72
|
+
globals_dict={
|
|
73
|
+
"riba_ids": ribas.ids,
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
wizard.riba_line_ids = ribas.line_ids.filtered_domain(
|
|
77
|
+
wizard_riba_lines_domain
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def pay(self):
|
|
81
|
+
self.ensure_one()
|
|
82
|
+
lines = self.riba_line_ids
|
|
83
|
+
if not lines:
|
|
84
|
+
raise UserError(self.env._("Please select the RiBa lines to be paid"))
|
|
85
|
+
incasso_lines = lines.filtered(lambda line: line.type == "incasso")
|
|
86
|
+
sbf_lines = lines - incasso_lines
|
|
87
|
+
# type "incasso" lines need to be set as paid only without settlement
|
|
88
|
+
# and account moves creation
|
|
89
|
+
incasso_lines.state = "paid"
|
|
90
|
+
# type "sbf" lines need to be settled and account moves created
|
|
91
|
+
if sbf_lines:
|
|
92
|
+
sbf_lines.riba_line_settlement(
|
|
93
|
+
date=self.payment_date,
|
|
94
|
+
)
|
|
95
|
+
# set the state of the RiBa slips to 'paid' if all their lines are paid
|
|
96
|
+
for slip in lines.slip_id:
|
|
97
|
+
if list(set(slip.line_ids.mapped("state"))) == ["paid"]:
|
|
98
|
+
slip.state = "paid"
|
|
99
|
+
|
|
100
|
+
def skip(self):
|
|
101
|
+
active_id = self.env.context.get("active_id") or False
|
|
102
|
+
if not active_id:
|
|
103
|
+
raise UserError(self.env._("No active ID found."))
|
|
104
|
+
riba_slip = self.env["riba.slip"].browse(active_id)
|
|
105
|
+
riba_slip.state = "paid"
|
|
106
|
+
riba_slip.line_ids.state = "paid"
|
|
107
|
+
return {"type": "ir.actions.act_window_close"}
|