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.
Files changed (61) hide show
  1. odoo/addons/l10n_it_riba_oca/README.rst +175 -0
  2. odoo/addons/l10n_it_riba_oca/__init__.py +9 -0
  3. odoo/addons/l10n_it_riba_oca/__manifest__.py +59 -0
  4. odoo/addons/l10n_it_riba_oca/data/riba_sequence.xml +14 -0
  5. odoo/addons/l10n_it_riba_oca/demo/riba_demo.xml +39 -0
  6. odoo/addons/l10n_it_riba_oca/hooks.py +17 -0
  7. odoo/addons/l10n_it_riba_oca/i18n/it.po +1686 -0
  8. odoo/addons/l10n_it_riba_oca/i18n/l10n_it_riba.pot +1573 -0
  9. odoo/addons/l10n_it_riba_oca/i18n/l10n_it_riba_oca.pot +1554 -0
  10. odoo/addons/l10n_it_riba_oca/migrations/18.0.1.0.0/pre-migrate.py +16 -0
  11. odoo/addons/l10n_it_riba_oca/models/__init__.py +14 -0
  12. odoo/addons/l10n_it_riba_oca/models/account.py +563 -0
  13. odoo/addons/l10n_it_riba_oca/models/account_config.py +35 -0
  14. odoo/addons/l10n_it_riba_oca/models/ir_ui_menu.py +27 -0
  15. odoo/addons/l10n_it_riba_oca/models/partner.py +35 -0
  16. odoo/addons/l10n_it_riba_oca/models/riba.py +560 -0
  17. odoo/addons/l10n_it_riba_oca/models/riba_config.py +120 -0
  18. odoo/addons/l10n_it_riba_oca/readme/CONFIGURE.md +33 -0
  19. odoo/addons/l10n_it_riba_oca/readme/CONTRIBUTORS.md +17 -0
  20. odoo/addons/l10n_it_riba_oca/readme/DESCRIPTION.md +3 -0
  21. odoo/addons/l10n_it_riba_oca/readme/USAGE.md +35 -0
  22. odoo/addons/l10n_it_riba_oca/report/__init__.py +4 -0
  23. odoo/addons/l10n_it_riba_oca/report/report.xml +16 -0
  24. odoo/addons/l10n_it_riba_oca/report/slip_qweb.py +18 -0
  25. odoo/addons/l10n_it_riba_oca/security/ir.model.access.csv +23 -0
  26. odoo/addons/l10n_it_riba_oca/security/riba_security.xml +34 -0
  27. odoo/addons/l10n_it_riba_oca/static/description/icon.png +0 -0
  28. odoo/addons/l10n_it_riba_oca/static/description/index.html +512 -0
  29. odoo/addons/l10n_it_riba_oca/tests/__init__.py +10 -0
  30. odoo/addons/l10n_it_riba_oca/tests/riba_common.py +339 -0
  31. odoo/addons/l10n_it_riba_oca/tests/test_account_move.py +54 -0
  32. odoo/addons/l10n_it_riba_oca/tests/test_menu.py +51 -0
  33. odoo/addons/l10n_it_riba_oca/tests/test_riba.py +905 -0
  34. odoo/addons/l10n_it_riba_oca/views/account_config_view.xml +46 -0
  35. odoo/addons/l10n_it_riba_oca/views/account_view.xml +205 -0
  36. odoo/addons/l10n_it_riba_oca/views/configuration_view.xml +94 -0
  37. odoo/addons/l10n_it_riba_oca/views/partner_view.xml +29 -0
  38. odoo/addons/l10n_it_riba_oca/views/riba_detail_view.xml +97 -0
  39. odoo/addons/l10n_it_riba_oca/views/riba_view.xml +296 -0
  40. odoo/addons/l10n_it_riba_oca/views/slip_report.xml +149 -0
  41. odoo/addons/l10n_it_riba_oca/views/wizard_credit.xml +46 -0
  42. odoo/addons/l10n_it_riba_oca/views/wizard_due_date_settlement.xml +37 -0
  43. odoo/addons/l10n_it_riba_oca/views/wizard_past_due.xml +67 -0
  44. odoo/addons/l10n_it_riba_oca/views/wizard_presentation.xml +48 -0
  45. odoo/addons/l10n_it_riba_oca/views/wizard_riba_file_export.xml +33 -0
  46. odoo/addons/l10n_it_riba_oca/views/wizard_riba_issue.xml +46 -0
  47. odoo/addons/l10n_it_riba_oca/views/wizard_riba_payment_date.xml +45 -0
  48. odoo/addons/l10n_it_riba_oca/wizard/__init__.py +16 -0
  49. odoo/addons/l10n_it_riba_oca/wizard/wizard_credit.py +280 -0
  50. odoo/addons/l10n_it_riba_oca/wizard/wizard_due_date_settlement.py +24 -0
  51. odoo/addons/l10n_it_riba_oca/wizard/wizard_past_due.py +319 -0
  52. odoo/addons/l10n_it_riba_oca/wizard/wizard_presentation_riba.py +47 -0
  53. odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_file_export.py +429 -0
  54. odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_issue.py +143 -0
  55. odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_multiple_payment.py +107 -0
  56. odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_multiple_payment_views.xml +46 -0
  57. odoo/addons/l10n_it_riba_oca/wizard/wizard_riba_payment_date.py +31 -0
  58. odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/METADATA +197 -0
  59. odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/RECORD +61 -0
  60. odoo_addon_l10n_it_riba_oca-18.0.1.0.0.8.dist-info/WHEEL +5 -0
  61. 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"}