odoo-addon-contract 17.0.1.4.5__py3-none-any.whl → 18.0.2.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 (58) hide show
  1. odoo/addons/contract/README.rst +14 -10
  2. odoo/addons/contract/__manifest__.py +3 -10
  3. odoo/addons/contract/controllers/main.py +1 -8
  4. odoo/addons/contract/data/contract_cron.xml +0 -2
  5. odoo/addons/contract/data/mail_template.xml +18 -17
  6. odoo/addons/contract/data/template_mail_notification.xml +1 -1
  7. odoo/addons/contract/i18n/ca.po +120 -33
  8. odoo/addons/contract/i18n/contract.pot +141 -823
  9. odoo/addons/contract/migrations/18.0.2.0.0/pre-migrate.py +90 -0
  10. odoo/addons/contract/models/__init__.py +2 -6
  11. odoo/addons/contract/models/account_move.py +0 -8
  12. odoo/addons/contract/models/account_move_line.py +14 -0
  13. odoo/addons/contract/models/contract.py +266 -308
  14. odoo/addons/contract/models/contract_line.py +34 -861
  15. odoo/addons/contract/models/{contract_recurrency_mixin.py → contract_recurring_mixin.py} +101 -82
  16. odoo/addons/contract/models/contract_tag.py +1 -3
  17. odoo/addons/contract/models/contract_template.py +81 -2
  18. odoo/addons/contract/models/contract_template_line.py +249 -3
  19. odoo/addons/contract/report/contract_views.xml +0 -2
  20. odoo/addons/contract/report/report_contract.xml +13 -13
  21. odoo/addons/contract/security/contract_security.xml +6 -15
  22. odoo/addons/contract/security/contract_tag.xml +1 -3
  23. odoo/addons/contract/security/ir.model.access.csv +0 -2
  24. odoo/addons/contract/static/description/index.html +24 -18
  25. odoo/addons/contract/static/src/js/contract_portal_tour.esm.js +6 -3
  26. odoo/addons/contract/tests/test_contract.py +42 -927
  27. odoo/addons/contract/tests/test_multicompany.py +5 -4
  28. odoo/addons/contract/tests/test_portal.py +6 -3
  29. odoo/addons/contract/views/contract.xml +91 -234
  30. odoo/addons/contract/views/contract_line.xml +48 -117
  31. odoo/addons/contract/views/contract_portal_templates.xml +181 -222
  32. odoo/addons/contract/views/contract_tag.xml +3 -3
  33. odoo/addons/contract/views/contract_template.xml +100 -72
  34. odoo/addons/contract/views/contract_template_line.xml +76 -5
  35. odoo/addons/contract/views/res_config_settings.xml +5 -6
  36. odoo/addons/contract/views/res_partner_view.xml +0 -5
  37. odoo/addons/contract/wizards/__init__.py +0 -2
  38. odoo/addons/contract/wizards/contract_manually_create_invoice.py +6 -6
  39. odoo/addons/contract/wizards/contract_manually_create_invoice.xml +2 -3
  40. {odoo_addon_contract-17.0.1.4.5.dist-info → odoo_addon_contract-18.0.2.0.0.8.dist-info}/METADATA +17 -13
  41. {odoo_addon_contract-17.0.1.4.5.dist-info → odoo_addon_contract-18.0.2.0.0.8.dist-info}/RECORD +43 -56
  42. odoo/addons/contract/data/contract_renew_cron.xml +0 -14
  43. odoo/addons/contract/models/abstract_contract.py +0 -82
  44. odoo/addons/contract/models/abstract_contract_line.py +0 -271
  45. odoo/addons/contract/models/contract_line_constraints.py +0 -429
  46. odoo/addons/contract/models/contract_terminate_reason.py +0 -14
  47. odoo/addons/contract/models/res_company.py +0 -15
  48. odoo/addons/contract/models/res_config_settings.py +0 -18
  49. odoo/addons/contract/security/contract_terminate_reason.xml +0 -23
  50. odoo/addons/contract/security/groups.xml +0 -9
  51. odoo/addons/contract/views/abstract_contract_line.xml +0 -117
  52. odoo/addons/contract/views/contract_terminate_reason.xml +0 -38
  53. odoo/addons/contract/wizards/contract_contract_terminate.py +0 -42
  54. odoo/addons/contract/wizards/contract_contract_terminate.xml +0 -33
  55. odoo/addons/contract/wizards/contract_line_wizard.py +0 -53
  56. odoo/addons/contract/wizards/contract_line_wizard.xml +0 -111
  57. {odoo_addon_contract-17.0.1.4.5.dist-info → odoo_addon_contract-18.0.2.0.0.8.dist-info}/WHEEL +0 -0
  58. {odoo_addon_contract-17.0.1.4.5.dist-info → odoo_addon_contract-18.0.2.0.0.8.dist-info}/top_level.txt +0 -0
@@ -1,14 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8" ?>
2
- <odoo noupdate="1">
3
- <record model="ir.cron" id="contract_line_cron_for_renew">
4
- <field name="name">Renew Contract lines</field>
5
- <field name="model_id" ref="model_contract_line" />
6
- <field name="state">code</field>
7
- <field name="code">model.cron_renew_contract_line()</field>
8
- <field name="user_id" ref="base.user_root" />
9
- <field name="interval_number">1</field>
10
- <field name="interval_type">days</field>
11
- <field name="numbercall">-1</field>
12
- <field eval="False" name="doall" />
13
- </record>
14
- </odoo>
@@ -1,82 +0,0 @@
1
- # Copyright 2004-2010 OpenERP SA
2
- # Copyright 2014 Angel Moya <angel.moya@domatix.com>
3
- # Copyright 2015-2020 Tecnativa - Pedro M. Baeza
4
- # Copyright 2016-2018 Carlos Dauden <carlos.dauden@tecnativa.com>
5
- # Copyright 2016-2017 LasLabs Inc.
6
- # Copyright 2018 ACSONE SA/NV
7
- # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
8
-
9
- from odoo import api, fields, models
10
-
11
-
12
- class ContractAbstractContract(models.AbstractModel):
13
- _inherit = "contract.recurrency.basic.mixin"
14
- _name = "contract.abstract.contract"
15
- _description = "Abstract Recurring Contract"
16
- _check_company_auto = True
17
-
18
- # These fields will not be synced to the contract
19
- NO_SYNC = ["name", "partner_id", "company_id"]
20
-
21
- name = fields.Char(required=True)
22
- # Needed for avoiding errors on several inherited behaviors
23
- partner_id = fields.Many2one(
24
- comodel_name="res.partner", string="Partner", index=True
25
- )
26
- pricelist_id = fields.Many2one(comodel_name="product.pricelist", string="Pricelist")
27
- contract_type = fields.Selection(
28
- selection=[("sale", "Customer"), ("purchase", "Supplier")],
29
- default="sale",
30
- index=True,
31
- )
32
- journal_id = fields.Many2one(
33
- comodel_name="account.journal",
34
- string="Journal",
35
- domain="[('type', '=', contract_type)]",
36
- compute="_compute_journal_id",
37
- store=True,
38
- readonly=False,
39
- index=True,
40
- check_company=True,
41
- )
42
- company_id = fields.Many2one(
43
- "res.company",
44
- string="Company",
45
- required=True,
46
- default=lambda self: self.env.company.id,
47
- )
48
- line_recurrence = fields.Boolean(
49
- string="Recurrence at line level?",
50
- help="Mark this check if you want to control recurrrence at line level instead"
51
- " of all together for the whole contract.",
52
- )
53
- generation_type = fields.Selection(
54
- selection=[("invoice", "Invoice")],
55
- default=lambda self: self._default_generation_type(),
56
- help="Choose the document that will be automatically generated by cron.",
57
- )
58
-
59
- @api.model
60
- def _default_generation_type(self):
61
- return "invoice"
62
-
63
- @api.onchange("contract_type")
64
- def _onchange_contract_type(self):
65
- if self.contract_type == "purchase":
66
- self.contract_line_ids.filtered("automatic_price").update(
67
- {"automatic_price": False}
68
- )
69
-
70
- @api.depends("contract_type", "company_id")
71
- def _compute_journal_id(self):
72
- AccountJournal = self.env["account.journal"]
73
- for contract in self:
74
- domain = [
75
- ("type", "=", contract.contract_type),
76
- ("company_id", "=", contract.company_id.id),
77
- ]
78
- journal = AccountJournal.search(domain, limit=1)
79
- if journal:
80
- contract.journal_id = journal.id
81
- else:
82
- contract.journal_id = None
@@ -1,271 +0,0 @@
1
- # Copyright 2004-2010 OpenERP SA
2
- # Copyright 2014 Angel Moya <angel.moya@domatix.com>
3
- # Copyright 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com>
4
- # Copyright 2016-2018 Carlos Dauden <carlos.dauden@tecnativa.com>
5
- # Copyright 2016-2017 LasLabs Inc.
6
- # Copyright 2018 ACSONE SA/NV
7
- # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
8
-
9
- from odoo import api, fields, models
10
- from odoo.exceptions import ValidationError
11
- from odoo.tools.translate import _
12
-
13
-
14
- class ContractAbstractContractLine(models.AbstractModel):
15
- _inherit = "contract.recurrency.basic.mixin"
16
- _name = "contract.abstract.contract.line"
17
- _description = "Abstract Recurring Contract Line"
18
-
19
- product_id = fields.Many2one("product.product", string="Product")
20
- name = fields.Text(string="Description", required=True)
21
- partner_id = fields.Many2one(
22
- comodel_name="res.partner", related="contract_id.partner_id"
23
- )
24
- quantity = fields.Float(default=1.0, required=True)
25
- product_uom_category_id = fields.Many2one( # Used for domain of field uom_id
26
- comodel_name="uom.category",
27
- related="product_id.uom_id.category_id",
28
- )
29
- uom_id = fields.Many2one(
30
- comodel_name="uom.uom",
31
- string="Unit of Measure",
32
- domain="[('category_id', '=', product_uom_category_id)]",
33
- )
34
- automatic_price = fields.Boolean(
35
- string="Auto-price?",
36
- help="If this is marked, the price will be obtained automatically "
37
- "applying the pricelist to the product. If not, you will be "
38
- "able to introduce a manual price",
39
- )
40
- # Just to have a currency_id here - will get overwriten in contract.line
41
- # model with the related currency from the contract
42
- currency_id = fields.Many2one("res.currency")
43
- specific_price = fields.Float()
44
- price_unit = fields.Float(
45
- string="Unit Price",
46
- compute="_compute_price_unit",
47
- inverse="_inverse_price_unit",
48
- )
49
- price_subtotal = fields.Monetary(
50
- compute="_compute_price_subtotal",
51
- string="Sub Total",
52
- )
53
- discount = fields.Float(
54
- string="Discount (%)",
55
- digits="Discount",
56
- help="Discount that is applied in generated invoices."
57
- " It should be less or equal to 100",
58
- )
59
- sequence = fields.Integer(
60
- default=10,
61
- help="Sequence of the contract line when displaying contracts",
62
- )
63
- recurring_rule_type = fields.Selection(
64
- compute="_compute_recurring_rule_type",
65
- store=True,
66
- readonly=False,
67
- required=True,
68
- copy=True,
69
- )
70
- recurring_invoicing_type = fields.Selection(
71
- compute="_compute_recurring_invoicing_type",
72
- store=True,
73
- readonly=False,
74
- required=True,
75
- copy=True,
76
- )
77
- recurring_interval = fields.Integer(
78
- compute="_compute_recurring_interval",
79
- store=True,
80
- readonly=False,
81
- required=True,
82
- copy=True,
83
- )
84
- date_start = fields.Date(
85
- compute="_compute_date_start",
86
- store=True,
87
- readonly=False,
88
- copy=True,
89
- )
90
- last_date_invoiced = fields.Date()
91
- is_canceled = fields.Boolean(string="Canceled", default=False)
92
- is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
93
- auto_renew_interval = fields.Integer(
94
- default=1,
95
- string="Renew Every",
96
- help="Renew every (Days/Week/Month/Year)",
97
- )
98
- auto_renew_rule_type = fields.Selection(
99
- [
100
- ("daily", "Day(s)"),
101
- ("weekly", "Week(s)"),
102
- ("monthly", "Month(s)"),
103
- ("yearly", "Year(s)"),
104
- ],
105
- default="yearly",
106
- string="Renewal type",
107
- help="Specify Interval for automatic renewal.",
108
- )
109
- termination_notice_interval = fields.Integer(
110
- default=1, string="Termination Notice Before"
111
- )
112
- termination_notice_rule_type = fields.Selection(
113
- [("daily", "Day(s)"), ("weekly", "Week(s)"), ("monthly", "Month(s)")],
114
- default="monthly",
115
- string="Termination Notice type",
116
- )
117
- contract_id = fields.Many2one(
118
- string="Contract",
119
- comodel_name="contract.abstract.contract",
120
- required=True,
121
- ondelete="cascade",
122
- )
123
- display_type = fields.Selection(
124
- selection=[("line_section", "Section"), ("line_note", "Note")],
125
- default=False,
126
- help="Technical field for UX purpose.",
127
- )
128
- note_invoicing_mode = fields.Selection(
129
- selection=[
130
- ("with_previous_line", "With previous line"),
131
- ("with_next_line", "With next line"),
132
- ("custom", "Custom"),
133
- ],
134
- default="with_previous_line",
135
- help="Defines when the Note is invoiced:\n"
136
- "- With previous line: If the previous line can be invoiced.\n"
137
- "- With next line: If the next line can be invoiced.\n"
138
- "- Custom: Depending on the recurrence to be define.",
139
- )
140
- is_recurring_note = fields.Boolean(compute="_compute_is_recurring_note")
141
- company_id = fields.Many2one(related="contract_id.company_id", store=True)
142
-
143
- def _set_recurrence_field(self, field):
144
- """Helper method for computed methods that gets the equivalent field
145
- in the header.
146
-
147
- We need to re-assign the original value for avoiding a missing error.
148
- """
149
- for record in self:
150
- if record.contract_id.line_recurrence:
151
- record[field] = record[field]
152
- else:
153
- record[field] = record.contract_id[field]
154
-
155
- @api.depends("contract_id.recurring_rule_type", "contract_id.line_recurrence")
156
- def _compute_recurring_rule_type(self):
157
- self._set_recurrence_field("recurring_rule_type")
158
-
159
- @api.depends("contract_id.recurring_invoicing_type", "contract_id.line_recurrence")
160
- def _compute_recurring_invoicing_type(self):
161
- self._set_recurrence_field("recurring_invoicing_type")
162
-
163
- @api.depends("contract_id.recurring_interval", "contract_id.line_recurrence")
164
- def _compute_recurring_interval(self):
165
- self._set_recurrence_field("recurring_interval")
166
-
167
- @api.depends("contract_id.date_start", "contract_id.line_recurrence")
168
- def _compute_date_start(self):
169
- self._set_recurrence_field("date_start")
170
-
171
- # pylint: disable=missing-return
172
- @api.depends("contract_id.recurring_next_date", "contract_id.line_recurrence")
173
- def _compute_recurring_next_date(self):
174
- super()._compute_recurring_next_date()
175
- self._set_recurrence_field("recurring_next_date")
176
-
177
- @api.depends("display_type", "note_invoicing_mode")
178
- def _compute_is_recurring_note(self):
179
- for record in self:
180
- record.is_recurring_note = (
181
- record.display_type == "line_note"
182
- and record.note_invoicing_mode == "custom"
183
- )
184
-
185
- @api.depends(
186
- "automatic_price",
187
- "specific_price",
188
- "product_id",
189
- "quantity",
190
- "contract_id.pricelist_id",
191
- "contract_id.partner_id",
192
- )
193
- def _compute_price_unit(self):
194
- """Get the specific price if no auto-price, and the price obtained
195
- from the pricelist otherwise.
196
- """
197
- for line in self:
198
- if line.automatic_price and line.product_id:
199
- pricelist = (
200
- line.contract_id.pricelist_id
201
- or line.contract_id.partner_id.with_company(
202
- line.contract_id.company_id
203
- ).property_product_pricelist
204
- )
205
- product = line.product_id.with_context(
206
- quantity=line.env.context.get(
207
- "contract_line_qty",
208
- line.quantity,
209
- ),
210
- pricelist=pricelist.id,
211
- partner=line.contract_id.partner_id.id,
212
- date=line.env.context.get(
213
- "old_date", fields.Date.context_today(line)
214
- ),
215
- )
216
- line.price_unit = pricelist._get_product_price(product, quantity=1)
217
- else:
218
- line.price_unit = line.specific_price
219
-
220
- # Tip in https://github.com/odoo/odoo/issues/23891#issuecomment-376910788
221
- @api.onchange("price_unit")
222
- def _inverse_price_unit(self):
223
- """Store the specific price in the no auto-price records."""
224
- for line in self.filtered(lambda x: not x.automatic_price):
225
- line.specific_price = line.price_unit
226
-
227
- @api.depends("quantity", "price_unit", "discount")
228
- def _compute_price_subtotal(self):
229
- for line in self:
230
- subtotal = line.quantity * line.price_unit
231
- discount = line.discount / 100
232
- subtotal *= 1 - discount
233
- if line.contract_id.pricelist_id:
234
- cur = line.contract_id.pricelist_id.currency_id
235
- line.price_subtotal = cur.round(subtotal)
236
- else:
237
- line.price_subtotal = subtotal
238
-
239
- @api.constrains("discount")
240
- def _check_discount(self):
241
- for line in self:
242
- if line.discount > 100:
243
- raise ValidationError(_("Discount should be less or equal to 100"))
244
-
245
- @api.onchange("product_id")
246
- def _onchange_product_id(self):
247
- vals = {}
248
- if not self.uom_id or (
249
- self.product_id.uom_id.category_id.id != self.uom_id.category_id.id
250
- ):
251
- vals["uom_id"] = self.product_id.uom_id
252
-
253
- date = self.recurring_next_date or fields.Date.context_today(self)
254
- partner = self.contract_id.partner_id or self.env.user.partner_id
255
- if self.product_id:
256
- product = self.product_id.with_context(
257
- lang=partner.lang,
258
- partner=partner.id,
259
- quantity=self.quantity,
260
- date=date,
261
- pricelist=self.contract_id.pricelist_id.id,
262
- uom=self.uom_id.id,
263
- )
264
- vals["name"] = self.product_id.get_product_multiline_description_sale()
265
- if self.contract_id.pricelist_id:
266
- vals["price_unit"] = self.contract_id.pricelist_id._get_product_price(
267
- product, quantity=1
268
- )
269
- else:
270
- vals["price_unit"] = 0.0
271
- self.update(vals)