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,319 @@
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 api, fields, models
11
+ from odoo.exceptions import UserError
12
+
13
+
14
+ class RibaPastDue(models.TransientModel):
15
+ @api.model
16
+ def _get_config_type(self):
17
+ return self.env["riba.configuration"].get_default_value_by_list_line("type")
18
+
19
+ @api.model
20
+ def _get_past_due_journal_id(self):
21
+ return self.env["riba.configuration"].get_default_value_by_list_line(
22
+ "past_due_journal_id"
23
+ )
24
+
25
+ @api.model
26
+ def _get_unsolved_past_due_fee_amount(self):
27
+ return self.env["riba.configuration"].get_default_value_by_list_line(
28
+ "past_due_fee_amount"
29
+ )
30
+
31
+ @api.model
32
+ def _get_acceptance_account_id(self):
33
+ return self.env["riba.configuration"].get_default_value_by_list_line(
34
+ "acceptance_account_id"
35
+ )
36
+
37
+ @api.model
38
+ def _get_credit_account_id(self):
39
+ return self.env["riba.configuration"].get_default_value_by_list_line(
40
+ "credit_account_id"
41
+ )
42
+
43
+ @api.model
44
+ def _get_credit_amount(self):
45
+ if not self.env.context.get("active_id", False):
46
+ return False
47
+ return self.env["riba.slip.line"].browse(self.env.context["active_id"]).amount
48
+
49
+ @api.model
50
+ def _get_overdue_credit_account_id(self):
51
+ return self.env["riba.configuration"].get_default_value_by_list_line(
52
+ "overdue_credit_account_id"
53
+ )
54
+
55
+ @api.model
56
+ def _get_bank_account_id(self):
57
+ return self.env["riba.configuration"].get_default_value_by_list_line(
58
+ "bank_account_id"
59
+ )
60
+
61
+ @api.model
62
+ def _get_bank_expense_account_id(self):
63
+ return self.env["riba.configuration"].get_default_value_by_list_line(
64
+ "protest_charge_account_id"
65
+ )
66
+
67
+ _name = "riba.past_due"
68
+ _description = "Manage Past Due RiBas"
69
+ config_type = fields.Selection(
70
+ [("sbf", "Subject To Collection"), ("incasso", "After Collection")],
71
+ "Issue Mode",
72
+ default=_get_config_type,
73
+ )
74
+ past_due_journal_id = fields.Many2one(
75
+ "account.journal",
76
+ "Past Due Journal",
77
+ domain=[("type", "=", "bank")],
78
+ default=_get_past_due_journal_id,
79
+ )
80
+ acceptance_account_id = fields.Many2one(
81
+ "account.account",
82
+ "Acceptance Account",
83
+ default=_get_acceptance_account_id,
84
+ )
85
+ credit_account_id = fields.Many2one(
86
+ "account.account",
87
+ "Credit Account",
88
+ default=_get_credit_account_id,
89
+ )
90
+ credit_amount = fields.Float(default=_get_credit_amount)
91
+ overdue_credit_account_id = fields.Many2one(
92
+ "account.account",
93
+ "Past Due Bills Account",
94
+ default=_get_overdue_credit_account_id,
95
+ )
96
+ overdue_credit_amount = fields.Float(
97
+ "Past Due Bills Amount", default=_get_credit_amount
98
+ )
99
+
100
+ bank_account_id = fields.Many2one(
101
+ "account.account", "A/C Bank Account", default=_get_bank_account_id
102
+ )
103
+ bank_expense_account_id = fields.Many2one(
104
+ "account.account", "Bank Fees Account", default=_get_bank_expense_account_id
105
+ )
106
+ expense_amount = fields.Float("Fees Amount")
107
+ date = fields.Date(
108
+ help="If empty, the due date in the line will be used.",
109
+ readonly=False,
110
+ )
111
+ past_due_fee_amount = fields.Float(
112
+ "Past Due Fees Amount", default=_get_unsolved_past_due_fee_amount
113
+ )
114
+
115
+ def skip(self):
116
+ active_id = self.env.context.get("active_id")
117
+ if not active_id:
118
+ raise UserError(self.env._("No active ID found."))
119
+ line_model = self.env["riba.slip.line"]
120
+ line = line_model.browse(active_id)
121
+ line.acceptance_move_id.button_draft()
122
+ line.acceptance_move_id.unlink()
123
+ line.state = "past_due"
124
+ line.slip_id.state = "past_due"
125
+ return {"type": "ir.actions.act_window_close"}
126
+
127
+ def _validate_accounts(self, riba_type):
128
+ """Validate that all required accounts are set based on RiBa type."""
129
+ account_check = (
130
+ not self.past_due_journal_id
131
+ or not self.overdue_credit_account_id
132
+ or not self.bank_expense_account_id
133
+ )
134
+ # only incasso type needs "Acceptance Account"
135
+ if riba_type == "incasso":
136
+ account_check = account_check or not self.acceptance_account_id
137
+ # only sbf type needs "RiBa Account"
138
+ else:
139
+ account_check = account_check or not self.credit_account_id
140
+ if account_check:
141
+ raise UserError(self.env._("Every account is mandatory."))
142
+
143
+ def _prepare_move_lines(self, slip_line, riba_type, date):
144
+ """Prepare move lines for the past due entry."""
145
+ line_ids = []
146
+
147
+ # Determine account and name based on RiBa type
148
+ if riba_type == "incasso":
149
+ aml_name = self.env._("Bills Account")
150
+ aml_account_id = self.acceptance_account_id.id
151
+ else:
152
+ aml_name = self.env._("RiBa Credit")
153
+ aml_account_id = self.credit_account_id.id
154
+
155
+ # Add bank fees line if applicable
156
+ if self.past_due_fee_amount:
157
+ line_ids.extend(
158
+ [
159
+ (
160
+ 0,
161
+ 0,
162
+ {
163
+ "name": self.env._("Bank Fee"),
164
+ "account_id": self.bank_expense_account_id.id,
165
+ "debit": self.past_due_fee_amount,
166
+ "credit": 0.0,
167
+ },
168
+ ),
169
+ (
170
+ 0,
171
+ 0,
172
+ {
173
+ "name": self.env._("Bank Fee"),
174
+ "account_id": self.bank_account_id.id,
175
+ "debit": 0.0,
176
+ "credit": self.past_due_fee_amount,
177
+ },
178
+ ),
179
+ ]
180
+ )
181
+
182
+ # Add main lines
183
+ line_ids.extend(
184
+ [
185
+ # Past due bills line
186
+ (
187
+ 0,
188
+ 0,
189
+ {
190
+ "name": self.env._("Past Due Bills"),
191
+ "account_id": self.overdue_credit_account_id.id,
192
+ "debit": self.overdue_credit_amount,
193
+ "credit": 0.0,
194
+ "partner_id": slip_line.partner_id.id,
195
+ "date_maturity": date,
196
+ },
197
+ ),
198
+ # Credit/acceptance line
199
+ (
200
+ 0,
201
+ 0,
202
+ {
203
+ "name": aml_name,
204
+ "account_id": aml_account_id,
205
+ "credit": self.overdue_credit_amount,
206
+ "debit": 0.0,
207
+ },
208
+ ),
209
+ ]
210
+ )
211
+
212
+ return line_ids
213
+
214
+ def _process_reconciliation(self, move, slip_line):
215
+ """Process reconciliation for the past due move."""
216
+ move_line_model = self.env["account.move.line"]
217
+ move_model = self.env["account.move"]
218
+
219
+ riba_credit_to_be_reconciled, customers_to_be_reconciled = [], []
220
+
221
+ # Process move lines for reconciliation
222
+ for move_line in move.line_ids:
223
+ if move_line.account_id.id == self.overdue_credit_account_id.id:
224
+ self._process_overdue_move_line(move_line, slip_line, move_model)
225
+ customers_to_be_reconciled.append(move_line.id)
226
+ if move_line.account_id.id == self.credit_account_id.id:
227
+ riba_credit_to_be_reconciled.append(move_line.id)
228
+
229
+ # Add credit move lines for reconciliation
230
+ for credit_move_line in slip_line.credit_move_id.line_ids:
231
+ if credit_move_line.account_id.id == self.credit_account_id.id:
232
+ riba_credit_to_be_reconciled.append(credit_move_line.id)
233
+
234
+ # Reconcile RiBa credit lines
235
+ if riba_credit_to_be_reconciled:
236
+ move_line_model.browse(riba_credit_to_be_reconciled).reconcile()
237
+
238
+ # Remove existing reconciliations
239
+ slip_line.move_line_ids.move_line_id.remove_move_reconcile()
240
+
241
+ # Add acceptance move lines for reconciliation
242
+ for acceptance_move_line in slip_line.acceptance_move_id.line_ids:
243
+ if acceptance_move_line.account_id.id == self.overdue_credit_account_id.id:
244
+ customers_to_be_reconciled.append(acceptance_move_line.id)
245
+
246
+ # Reconcile customer lines
247
+ customers_to_be_reconciled_lines = move_line_model.with_context(
248
+ past_due_reconciliation=True
249
+ ).browse(customers_to_be_reconciled)
250
+ customers_to_be_reconciled_lines.reconcile()
251
+
252
+ def _process_overdue_move_line(self, move_line, slip_line, move_model):
253
+ """Process overdue move line for invoice linking."""
254
+ for riba_move_line in slip_line.move_line_ids:
255
+ invoice_ids = []
256
+ if riba_move_line.move_line_id.move_id:
257
+ invoice_ids = [riba_move_line.move_line_id.move_id.id]
258
+ elif riba_move_line.move_line_id.past_due_invoice_ids:
259
+ invoice_ids = [
260
+ i.id for i in riba_move_line.move_line_id.past_due_invoice_ids
261
+ ]
262
+ move_model.browse(invoice_ids).write(
263
+ {
264
+ "past_due_move_line_ids": [(4, move_line.id)],
265
+ }
266
+ )
267
+
268
+ def create_move(self):
269
+ active_id = self.env.context.get("active_id", False)
270
+ if not active_id:
271
+ raise UserError(self.env._("No active ID found."))
272
+
273
+ move_model = self.env["account.move"]
274
+ slip_line = self.env["riba.slip.line"].browse(active_id)
275
+ riba_type = slip_line.slip_id.config_id.type
276
+
277
+ # Validate required accounts
278
+ self._validate_accounts(riba_type)
279
+
280
+ date = self.date or slip_line.due_date
281
+
282
+ # Prepare move lines
283
+ line_ids = self._prepare_move_lines(slip_line, riba_type, date)
284
+
285
+ # Create and post the move
286
+ move_vals = {
287
+ "ref": self.env._("Past Due RiBa %(name)s - Line %(sequence)s")
288
+ % {
289
+ "name": slip_line.slip_id.name,
290
+ "sequence": slip_line.sequence,
291
+ },
292
+ "journal_id": self.past_due_journal_id.id,
293
+ "date": date,
294
+ "line_ids": line_ids,
295
+ }
296
+
297
+ move = move_model.create(move_vals)
298
+ move.action_post()
299
+
300
+ # Process reconciliation
301
+ self._process_reconciliation(move, slip_line)
302
+
303
+ # Update slip line state
304
+ slip_line.write(
305
+ {
306
+ "past_due_move_id": move.id,
307
+ "state": "past_due",
308
+ }
309
+ )
310
+ slip_line.slip_id.state = "past_due"
311
+
312
+ return {
313
+ "name": self.env._("Past Due Entry"),
314
+ "view_mode": "form",
315
+ "res_model": "account.move",
316
+ "type": "ir.actions.act_window",
317
+ "target": "current",
318
+ "res_id": move.id or False,
319
+ }
@@ -0,0 +1,47 @@
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
+
12
+
13
+ class PresentationRibaIssue(models.TransientModel):
14
+ _name = "presentation.riba.issue"
15
+ _description = "Presentation Riba Issue"
16
+ currency_id = fields.Many2one(
17
+ "res.currency", default=lambda self: self.env.company.currency_id
18
+ )
19
+ presentation_amount = fields.Monetary(currency_field="currency_id")
20
+
21
+ def action_presentation_riba(self):
22
+ list_ids = []
23
+ for line in self.env["account.move.line"].search(
24
+ [
25
+ "&",
26
+ "|",
27
+ ("riba", "=", "True"),
28
+ ("past_due_invoice_ids", "!=", False),
29
+ ("account_id.account_type", "=", "asset_receivable"),
30
+ ],
31
+ order="date_maturity asc, price_total asc",
32
+ ):
33
+ if (
34
+ self.currency_id.compare_amounts(
35
+ line.amount_residual,
36
+ self.presentation_amount,
37
+ )
38
+ > 0
39
+ ):
40
+ break
41
+ self.presentation_amount -= line.amount_residual
42
+ list_ids.append(line.id)
43
+ res = self.env["ir.actions.act_window"]._for_xml_id(
44
+ "l10n_it_riba_oca.action_riba_to_issue"
45
+ )
46
+ res["domain"] = [("id", "in", list_ids)]
47
+ return res