odoo-addon-sale-blanket-order 16.0.2.0.0.2__py3-none-any.whl → 18.0.1.2.1__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 (41) hide show
  1. odoo/addons/sale_blanket_order/README.rst +111 -63
  2. odoo/addons/sale_blanket_order/__manifest__.py +8 -3
  3. odoo/addons/sale_blanket_order/data/ir_cron.xml +0 -2
  4. odoo/addons/sale_blanket_order/i18n/de.po +65 -80
  5. odoo/addons/sale_blanket_order/i18n/es.po +30 -59
  6. odoo/addons/sale_blanket_order/i18n/fr.po +30 -59
  7. odoo/addons/sale_blanket_order/i18n/fr_FR.po +30 -59
  8. odoo/addons/sale_blanket_order/i18n/it.po +68 -88
  9. odoo/addons/sale_blanket_order/i18n/pt.po +15 -59
  10. odoo/addons/sale_blanket_order/i18n/sale_blanket_order.pot +16 -60
  11. odoo/addons/sale_blanket_order/models/blanket_orders.py +77 -143
  12. odoo/addons/sale_blanket_order/models/sale_config_settings.py +0 -1
  13. odoo/addons/sale_blanket_order/models/sale_orders.py +8 -14
  14. odoo/addons/sale_blanket_order/readme/CONTEXT.md +5 -0
  15. odoo/addons/sale_blanket_order/readme/CONTRIBUTORS.md +17 -0
  16. odoo/addons/sale_blanket_order/readme/{CREDITS.rst → CREDITS.md} +2 -1
  17. odoo/addons/sale_blanket_order/readme/DESCRIPTION.md +5 -0
  18. odoo/addons/sale_blanket_order/readme/ROADMAP.md +3 -0
  19. odoo/addons/sale_blanket_order/readme/USAGE.md +58 -0
  20. odoo/addons/sale_blanket_order/report/report.xml +0 -2
  21. odoo/addons/sale_blanket_order/report/templates.xml +32 -35
  22. odoo/addons/sale_blanket_order/static/description/index.html +87 -62
  23. odoo/addons/sale_blanket_order/static/src/js/disable_add_order_line.esm.js +22 -0
  24. odoo/addons/sale_blanket_order/tests/test_blanket_orders.py +99 -50
  25. odoo/addons/sale_blanket_order/tests/test_sale_order.py +7 -80
  26. odoo/addons/sale_blanket_order/views/sale_blanket_order_line_views.xml +7 -16
  27. odoo/addons/sale_blanket_order/views/sale_blanket_order_views.xml +31 -57
  28. odoo/addons/sale_blanket_order/views/sale_config_settings.xml +11 -19
  29. odoo/addons/sale_blanket_order/views/sale_order_views.xml +5 -8
  30. odoo/addons/sale_blanket_order/wizard/create_sale_orders.py +28 -26
  31. odoo/addons/sale_blanket_order/wizard/create_sale_orders.xml +12 -2
  32. odoo_addon_sale_blanket_order-18.0.1.2.1.dist-info/METADATA +216 -0
  33. odoo_addon_sale_blanket_order-18.0.1.2.1.dist-info/RECORD +49 -0
  34. {odoo_addon_sale_blanket_order-16.0.2.0.0.2.dist-info → odoo_addon_sale_blanket_order-18.0.1.2.1.dist-info}/WHEEL +1 -1
  35. odoo_addon_sale_blanket_order-18.0.1.2.1.dist-info/top_level.txt +1 -0
  36. odoo/addons/sale_blanket_order/readme/CONTRIBUTORS.rst +0 -8
  37. odoo/addons/sale_blanket_order/readme/DESCRIPTION.rst +0 -4
  38. odoo/addons/sale_blanket_order/readme/USAGE.rst +0 -53
  39. odoo_addon_sale_blanket_order-16.0.2.0.0.2.dist-info/METADATA +0 -168
  40. odoo_addon_sale_blanket_order-16.0.2.0.0.2.dist-info/RECORD +0 -46
  41. odoo_addon_sale_blanket_order-16.0.2.0.0.2.dist-info/top_level.txt +0 -1
@@ -1,13 +1,12 @@
1
1
  <?xml version="1.0" encoding="utf-8" ?>
2
2
  <odoo>
3
-
4
3
  <!-- VIEWS -->
5
4
 
6
5
  <record id="view_blanket_order_tree" model="ir.ui.view">
7
- <field name="name">sale.blanket.order.tree</field>
6
+ <field name="name">sale.blanket.order.list</field>
8
7
  <field name="model">sale.blanket.order</field>
9
8
  <field name="arch" type="xml">
10
- <tree
9
+ <list
11
10
  decoration-info="state == 'draft'"
12
11
  decoration-muted="state == 'expired'"
13
12
  >
@@ -22,7 +21,7 @@
22
21
  optional="show"
23
22
  readonly="1"
24
23
  />
25
- </tree>
24
+ </list>
26
25
  </field>
27
26
  </record>
28
27
 
@@ -37,25 +36,25 @@
37
36
  string="Create Sale Order"
38
37
  type="action"
39
38
  class="btn-primary"
40
- attrs="{'invisible': [('state', '!=', 'open')]}"
39
+ invisible="state != 'open'"
41
40
  />
42
41
  <button
43
42
  name="set_to_draft"
44
- states="expired,done"
43
+ invisible="state not in ['expired', 'done']"
45
44
  string="To Draft"
46
45
  class="btn-secondary"
47
46
  type="object"
48
47
  />
49
48
  <button
50
49
  name="action_cancel"
51
- states="open"
50
+ invisible="state != 'open'"
52
51
  string="Cancel"
53
52
  class="btn-secondary"
54
53
  type="object"
55
54
  />
56
55
  <button
57
56
  name="action_confirm"
58
- states="draft"
57
+ invisible="state != 'draft'"
59
58
  string="Confirm"
60
59
  class="btn-primary o_sale_confirm"
61
60
  type="object"
@@ -84,7 +83,7 @@
84
83
  type="object"
85
84
  name="action_view_sale_blanket_order_line"
86
85
  class="oe_stat_button"
87
- attrs="{'invisible':[('line_count', '=', 0)]}"
86
+ invisible="not line_count"
88
87
  icon="fa-list"
89
88
  >
90
89
  <field name="line_count" widget="statinfo" string="Lines" />
@@ -100,7 +99,7 @@
100
99
  <field
101
100
  name="partner_id"
102
101
  context="{'res_partner_search_mode': 'customer', 'show_address': 1}"
103
- attrs="{'required': [('state', '=', 'draft')]}"
102
+ required="state == 'draft'"
104
103
  options="{&quot;always_reload&quot;: True}"
105
104
  />
106
105
  <field name="payment_term_id" />
@@ -112,20 +111,17 @@
112
111
  options="{'no_create': True}"
113
112
  />
114
113
  <field name="company_id" invisible="1" />
115
- <field
116
- name="validity_date"
117
- attrs="{'required': [('state', '=', 'draft')]}"
118
- />
114
+ <field name="validity_date" required="state == 'draft'" />
119
115
  </group>
120
116
  </group>
121
117
  <notebook>
122
118
  <page string="Order Lines" name="order_lines">
123
119
  <field
124
120
  name="line_ids"
125
- attrs="{'readonly': [('state', 'in', ('open','done','expired'))]}"
121
+ readonly="state in ['open', 'done', 'expired']"
126
122
  widget="section_and_note_one2many"
127
123
  >
128
- <tree editable="bottom">
124
+ <list editable="bottom">
129
125
  <control>
130
126
  <create
131
127
  name="add_product_control"
@@ -142,14 +138,15 @@
142
138
  context="{'default_display_type': 'line_note'}"
143
139
  />
144
140
  </control>
145
- <field name="display_type" invisible="1" />
141
+ <field
142
+ name="display_type"
143
+ column_invisible="True"
144
+ />
146
145
  <field name="sequence" widget="handle" />
147
146
  <field
148
147
  name="product_id"
149
- attrs="{
150
- 'required': [('display_type', '=', False)],
151
- 'invisible': [('display_type', '=', True)],
152
- }"
148
+ required="not display_type"
149
+ invisible="display_type"
153
150
  context="{
154
151
  'fld': 'product_id',
155
152
  'partner_id': parent.partner_id,
@@ -181,14 +178,12 @@
181
178
  'quantity': original_uom_qty,
182
179
  'company_id': parent.company_id
183
180
  }"
184
- attrs="{
185
- 'required': [('display_type', '=', False)],
186
- 'invisible': [('display_type', '=', True)],
187
- }"
181
+ required="not display_type"
182
+ invisible="display_type"
188
183
  />
189
184
  <field
190
185
  name="product_uom"
191
- invisible="1"
186
+ column_invisible="True"
192
187
  groups="!uom.group_uom"
193
188
  />
194
189
  <field
@@ -198,10 +193,8 @@
198
193
  />
199
194
  <field
200
195
  name="price_unit"
201
- attrs="{
202
- 'required': [('display_type', '=', False)],
203
- 'invisible': [('display_type', '=', True)],
204
- }"
196
+ required="not display_type"
197
+ invisible="display_type"
205
198
  />
206
199
  <field name="date_schedule" />
207
200
  <field name="ordered_uom_qty" optional="hide" />
@@ -211,22 +204,18 @@
211
204
  <field
212
205
  name="taxes_id"
213
206
  widget="many2many_tags"
214
- domain="[('type_tax_use','=','sale')]"
215
- context="{'default_type_tax_use': 'sale'}"
207
+ domain="[('type_tax_use', '=', 'sale'), ('company_id', 'parent_of', parent.company_id)]"
208
+ context="{'search_view_ref': 'account.account_tax_view_search'}"
216
209
  options="{'no_create': True}"
217
- attrs="{
218
- 'invisible': [('display_type', '=', True)],
219
- }"
210
+ invisible="display_type"
220
211
  />
221
212
  <field
222
213
  name="price_subtotal"
223
214
  widget="monetary"
224
- attrs="{
225
- 'invisible': [('display_type', '=', True)],
226
- }"
215
+ invisible="display_type"
227
216
  />
228
217
  <field name="company_id" invisible="1" />
229
- </tree>
218
+ </list>
230
219
  </field>
231
220
  <group class="oe_subtotal_footer oe_right">
232
221
  <field
@@ -265,7 +254,7 @@
265
254
  <group string="Sales Information" name="sales_person">
266
255
  <field
267
256
  name="pricelist_id"
268
- attrs="{'required': [('state', '=', 'draft')]}"
257
+ required="state == 'draft'"
269
258
  />
270
259
  <field name="user_id" />
271
260
  <field
@@ -284,25 +273,11 @@
284
273
  groups="base.group_multi_company"
285
274
  />
286
275
  </group>
287
- <group name="invoicing" string="Invoicing">
288
- <t groups="base.group_multi_company">
289
- <field
290
- name="analytic_account_id"
291
- attrs="{'readonly': [('sale_count','!=',0),('state','!=','draft')]}"
292
- groups="analytic.group_analytic_accounting"
293
- force_save="1"
294
- />
295
- </t>
296
- </group>
297
276
  </group>
298
277
  </page>
299
278
  </notebook>
300
279
  </sheet>
301
- <div class="oe_chatter">
302
- <field name="message_follower_ids" />
303
- <field name="activity_ids" />
304
- <field name="message_ids" />
305
- </div>
280
+ <chatter />
306
281
  </form>
307
282
  </field>
308
283
  </record>
@@ -358,7 +333,7 @@
358
333
  <field name="name">Blanket Orders</field>
359
334
  <field name="type">ir.actions.act_window</field>
360
335
  <field name="res_model">sale.blanket.order</field>
361
- <field name="view_mode">tree,form</field>
336
+ <field name="view_mode">list,form</field>
362
337
  <field name="search_view_id" ref="view_blanket_order_search" />
363
338
  <field name="domain">[]</field>
364
339
  <field name="context">{}</field>
@@ -383,5 +358,4 @@
383
358
  sequence="20"
384
359
  action="act_open_blanket_order_view"
385
360
  />
386
-
387
361
  </odoo>
@@ -7,25 +7,17 @@
7
7
  <field name="model">res.config.settings</field>
8
8
  <field name="inherit_id" ref="sale.res_config_settings_view_form" />
9
9
  <field name="arch" type="xml">
10
- <xpath
11
- expr="//div[hasclass('row','mt16','o_settings_container')][position() = 3]"
12
- position="after"
13
- >
14
- <h2>Blanket Orders</h2>
15
- <div class="row mt16 o_settings_container">
16
- <div class="col-xs-12 col-md-6 o_setting_box">
17
- <div class="o_setting_left_pane">
18
- <field name="group_blanket_disable_adding_lines" />
19
- </div>
20
- <div class="o_setting_right_pane">
21
- <label for="group_blanket_disable_adding_lines" />
22
- <div class="text-muted" id="sale_config_website_quote">
23
- Disable adding more lines to SOs from Blanket Orders
24
- </div>
25
- </div>
26
- </div>
27
- </div>
28
- </xpath>
10
+ <block name="quotation_order_setting_container" position="after">
11
+ <block title="Blanket Orders" name="blanket_orders_setting_container">
12
+ <setting
13
+ id="group_blanket_disable_adding_lines"
14
+ title="Disable adding more lines to SOs from Blanket Orders"
15
+ help="Disable adding more lines to SOs from Blanket Orders"
16
+ >
17
+ <field name="group_blanket_disable_adding_lines" />
18
+ </setting>
19
+ </block>
20
+ </block>
29
21
  </field>
30
22
  </record>
31
23
  </odoo>
@@ -8,19 +8,19 @@
8
8
  <field name="currency_id" position="after">
9
9
  <field name="blanket_order_id" invisible="1" />
10
10
  </field>
11
+ <xpath expr="//field[@name='order_line']" position="attributes">
12
+ <attribute name="context">{'from_sale_order': True}</attribute>
13
+ </xpath>
11
14
  <xpath
12
- expr="//field[@name='order_line']//tree/field[@name='product_id']"
15
+ expr="//field[@name='order_line']//list/field[@name='product_template_id']"
13
16
  position="after"
14
17
  >
15
18
  <field
16
19
  name="blanket_order_line"
17
20
  context="{'from_sale_order': True}"
18
- attrs="{'column_invisible': [('parent.blanket_order_id', '=', False)]}"
21
+ column_invisible="not parent.blanket_order_id"
19
22
  />
20
23
  </xpath>
21
- <xpath expr="//field[@name='order_line']" position="attributes">
22
- <attribute name="context">{'from_sale_order': True}</attribute>
23
- </xpath>
24
24
  </field>
25
25
  </record>
26
26
  <record id="view_order_form_disable_adding_lines" model="ir.ui.view">
@@ -31,9 +31,6 @@
31
31
  <xpath expr="//field[@name='order_line']" position="before">
32
32
  <field name="disable_adding_lines" invisible="1" />
33
33
  </xpath>
34
- <xpath expr="//field[@name='order_line']//tree" position="attributes">
35
- <attribute name="create">not disable_adding_lines</attribute>
36
- </xpath>
37
34
  </field>
38
35
  </record>
39
36
  </odoo>
@@ -2,7 +2,7 @@
2
2
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3
3
  from collections import defaultdict
4
4
 
5
- from odoo import _, api, fields, models
5
+ from odoo import api, fields, models
6
6
  from odoo.exceptions import UserError
7
7
  from odoo.tools import float_is_zero
8
8
 
@@ -22,7 +22,9 @@ class BlanketOrderWizard(models.TransientModel):
22
22
  )
23
23
  if blanket_order.state == "expired":
24
24
  raise UserError(
25
- _("You can't create a sale order from " "an expired blanket order!")
25
+ self.env._(
26
+ "You can't create a sale order from " "an expired blanket order!"
27
+ )
26
28
  )
27
29
  return blanket_order
28
30
 
@@ -37,16 +39,18 @@ class BlanketOrderWizard(models.TransientModel):
37
39
  float_is_zero(line.remaining_uom_qty, precision_digits=precision)
38
40
  for line in bo_lines
39
41
  ):
40
- raise UserError(_("The sale has already been completed."))
42
+ raise UserError(self.env._("The sale has already been completed."))
41
43
 
42
44
  for line in bo_lines:
43
45
  if line.order_id.state != "open":
44
46
  raise UserError(
45
- _("Sale Blanket Order %s is not open") % line.order_id.name
47
+ self.env._("Sale Blanket Order %s is not open") % line.order_id.name
46
48
  )
47
49
  line_company_id = line.company_id and line.company_id.id or False
48
50
  if company_id is not False and line_company_id != company_id:
49
- raise UserError(_("You have to select lines " "from the same company."))
51
+ raise UserError(
52
+ self.env._("You have to select lines " "from the same company.")
53
+ )
50
54
  else:
51
55
  company_id = line_company_id
52
56
 
@@ -64,22 +68,17 @@ class BlanketOrderWizard(models.TransientModel):
64
68
  self._check_valid_blanket_order_line(bo_lines)
65
69
 
66
70
  lines = [
67
- (
68
- 0,
69
- 0,
71
+ fields.Command.create(
70
72
  {
73
+ "analytic_distribution": bol.analytic_distribution,
71
74
  "blanket_line_id": bol.id,
72
- "product_id": bol.product_id.id,
73
75
  "date_schedule": bol.date_schedule,
74
- "remaining_uom_qty": bol.remaining_uom_qty,
75
- "price_unit": bol.price_unit,
76
- "product_uom": bol.product_uom,
77
76
  "qty": bol.remaining_uom_qty,
78
- "partner_id": bol.partner_id,
79
77
  },
80
78
  )
81
79
  for bol in bo_lines.filtered(
82
- lambda l: not l.display_type and l.remaining_uom_qty != 0.0
80
+ lambda bo_line: not bo_line.display_type
81
+ and bo_line.remaining_uom_qty != 0.0
83
82
  )
84
83
  ]
85
84
  return lines
@@ -101,6 +100,7 @@ class BlanketOrderWizard(models.TransientModel):
101
100
 
102
101
  def _prepare_so_line_vals(self, line):
103
102
  return {
103
+ "analytic_distribution": line.analytic_distribution,
104
104
  "product_id": line.product_id.id,
105
105
  "name": line.product_id.name,
106
106
  "product_uom": line.product_uom.id,
@@ -108,7 +108,7 @@ class BlanketOrderWizard(models.TransientModel):
108
108
  "price_unit": line.blanket_line_id.price_unit,
109
109
  "blanket_order_line": line.blanket_line_id.id,
110
110
  "product_uom_qty": line.qty,
111
- "tax_id": [(6, 0, line.taxes_id.ids)],
111
+ "tax_id": [fields.Command.set(line.taxes_id.ids)],
112
112
  }
113
113
 
114
114
  def _prepare_so_vals(
@@ -130,17 +130,12 @@ class BlanketOrderWizard(models.TransientModel):
130
130
  "pricelist_id": pricelist_id,
131
131
  "payment_term_id": payment_term_id,
132
132
  "order_line": order_lines_by_customer[customer],
133
- "analytic_account_id": self.blanket_order_id.analytic_account_id.id,
134
133
  "client_order_ref": client_order_ref,
135
134
  "tag_ids": [(6, 0, tag_ids.ids)] if tag_ids else False,
136
135
  }
137
136
 
138
137
  @api.model
139
138
  def _check_consistency(self, current_value, new_value):
140
- """Return a consistent value across updates.
141
- If the current value is unset (0), use the new value.
142
- If it matches the new value, keep it. Otherwise, return False.
143
- """
144
139
  if current_value == 0:
145
140
  return new_value
146
141
  return current_value if current_value == new_value else False
@@ -153,9 +148,11 @@ class BlanketOrderWizard(models.TransientModel):
153
148
  payment_term_id = 0
154
149
  client_order_ref = 0
155
150
  tag_ids = 0
156
- for line in self.line_ids.filtered(lambda l: l.qty != 0.0):
151
+ for line in self.line_ids.filtered(lambda line: line.qty != 0.0):
157
152
  if line.qty > line.remaining_uom_qty:
158
- raise UserError(_("You can't order more than the remaining quantities"))
153
+ raise UserError(
154
+ self.env._("You can't order more than the remaining quantities")
155
+ )
159
156
  vals = self._prepare_so_line_vals(line)
160
157
  order_lines_by_customer[line.partner_id.id].append((0, 0, vals))
161
158
 
@@ -177,11 +174,11 @@ class BlanketOrderWizard(models.TransientModel):
177
174
  )
178
175
 
179
176
  if not order_lines_by_customer:
180
- raise UserError(_("An order can't be empty"))
177
+ raise UserError(self.env._("An order can't be empty"))
181
178
 
182
179
  if not currency_id:
183
180
  raise UserError(
184
- _(
181
+ self.env._(
185
182
  "Can not create Sale Order from Blanket "
186
183
  "Order lines with different currencies"
187
184
  )
@@ -203,9 +200,9 @@ class BlanketOrderWizard(models.TransientModel):
203
200
  res.append(sale_order.id)
204
201
  return {
205
202
  "domain": [("id", "in", res)],
206
- "name": _("Sales Orders"),
203
+ "name": self.env._("Sales Orders"),
207
204
  "view_type": "form",
208
- "view_mode": "tree,form",
205
+ "view_mode": "list,form",
209
206
  "res_model": "sale.order",
210
207
  "context": {"from_sale_order": True},
211
208
  "type": "ir.actions.act_window",
@@ -213,11 +210,13 @@ class BlanketOrderWizard(models.TransientModel):
213
210
 
214
211
 
215
212
  class BlanketOrderWizardLine(models.TransientModel):
213
+ _inherit = "analytic.mixin"
216
214
  _name = "sale.blanket.order.wizard.line"
217
215
  _description = "Blanket order wizard line"
218
216
 
219
217
  wizard_id = fields.Many2one("sale.blanket.order.wizard")
220
218
  blanket_line_id = fields.Many2one("sale.blanket.order.line")
219
+ analytic_distribution = fields.Json(related="blanket_line_id.analytic_distribution")
221
220
  product_id = fields.Many2one(
222
221
  "product.product", related="blanket_line_id.product_id", string="Product"
223
222
  )
@@ -233,3 +232,6 @@ class BlanketOrderWizardLine(models.TransientModel):
233
232
  "res.partner", related="blanket_line_id.partner_id", string="Vendor"
234
233
  )
235
234
  taxes_id = fields.Many2many("account.tax", related="blanket_line_id.taxes_id")
235
+ company_id = fields.Many2one(
236
+ "res.company", related="blanket_line_id.company_id", string="Company"
237
+ )
@@ -7,7 +7,7 @@
7
7
  <form string="Create Sale Order">
8
8
  <group>
9
9
  <field name="line_ids" nolabel="1" colspan="2">
10
- <tree create="false" editable="bottom">
10
+ <list create="false" editable="bottom">
11
11
  <field
12
12
  name="blanket_line_id"
13
13
  force_save="1"
@@ -20,7 +20,17 @@
20
20
  <field name="remaining_uom_qty" />
21
21
  <field name="product_uom" groups="uom.group_uom" />
22
22
  <field name="qty" />
23
- </tree>
23
+ <field
24
+ name="analytic_distribution"
25
+ widget="analytic_distribution"
26
+ optional="hide"
27
+ groups="analytic.group_analytic_accounting"
28
+ options="{
29
+ 'product_field': 'product_id',
30
+ 'business_domain': 'sale_order'
31
+ }"
32
+ />
33
+ </list>
24
34
  </field>
25
35
  </group>
26
36
  <footer>