summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
Diffstat (limited to 'addons')
-rw-r--r--addons/account/models/account_invoice.py7
-rw-r--r--addons/account/views/report_agedpartnerbalance.xml2
-rw-r--r--addons/account_asset/models/account_invoice.py4
-rw-r--r--addons/calendar/models/calendar.py6
-rw-r--r--addons/event/models/event_mail.py3
-rw-r--r--addons/hr_expense/models/hr_expense.py2
-rw-r--r--addons/l10n_de_skr03/data/l10n_de_skr03_chart_data.xml30
-rw-r--r--addons/l10n_de_skr04/data/l10n_de_skr04_chart_data.xml24
-rw-r--r--addons/l10n_fr/data/account_fiscal_position_template_data.xml50
-rw-r--r--addons/l10n_fr/data/account_tax_data.xml96
-rw-r--r--addons/mail/models/mail_template.py2
-rw-r--r--addons/mail/models/mail_thread.py13
-rw-r--r--addons/mail/wizard/mail_compose_message.py23
-rw-r--r--addons/mrp/models/mrp_bom.py11
-rw-r--r--addons/mrp/models/mrp_production.py41
-rw-r--r--addons/mrp/models/mrp_routing.py1
-rw-r--r--addons/mrp/models/mrp_unbuild.py4
-rw-r--r--addons/mrp/models/mrp_workcenter.py20
-rw-r--r--addons/mrp/models/mrp_workorder.py6
-rw-r--r--addons/mrp/models/product.py7
-rw-r--r--addons/mrp/models/stock_move.py57
-rw-r--r--addons/mrp/models/stock_scrap.py1
-rw-r--r--addons/mrp/views/mrp_bom_views.xml3
-rw-r--r--addons/mrp/views/mrp_production_views.xml18
-rw-r--r--addons/mrp/views/mrp_workcenter_views.xml2
-rw-r--r--addons/mrp/views/mrp_workorder_views.xml3
-rw-r--r--addons/mrp/wizard/change_production_qty.py49
-rw-r--r--addons/mrp/wizard/change_production_qty_views.xml4
-rw-r--r--addons/mrp/wizard/mrp_product_produce.py4
-rw-r--r--addons/mrp/wizard/mrp_product_produce_views.xml4
-rw-r--r--addons/mrp_byproduct/models/mrp_production.py48
-rw-r--r--addons/mrp_byproduct/models/stock_move.py2
-rw-r--r--addons/mrp_byproduct/wizard/change_production_qty.py21
-rw-r--r--addons/project_issue/models/project_issue.py5
-rw-r--r--addons/purchase_mrp/models/purchase_mrp.py2
-rw-r--r--addons/purchase_requisition/views/purchase_requisition_views.xml2
-rw-r--r--addons/rating_project/models/project.py5
-rw-r--r--addons/sale_mrp/sale_mrp.py2
-rw-r--r--addons/sale_mrp/tests/test_sale_mrp_flow.py4
-rw-r--r--addons/stock/models/product.py4
-rw-r--r--addons/stock/models/stock_move.py6
-rw-r--r--addons/stock/models/stock_scrap.py2
-rw-r--r--addons/stock/views/stock_pack_operation_views.xml4
-rw-r--r--addons/web/static/src/js/views/form_relational_widgets.js2
-rw-r--r--addons/web/static/src/less/webclient_layout.less1
-rw-r--r--addons/web_editor/static/src/js/snippets.options.js2
-rw-r--r--addons/web_editor/static/src/js/widgets.js22
-rw-r--r--addons/website/static/src/js/website.contentMenu.js4
-rw-r--r--addons/website/static/src/js/website.js5
-rw-r--r--addons/website/static/src/js/website.seo.js4
-rw-r--r--addons/website/static/src/js/website.snippets.gallery.js4
-rw-r--r--addons/website_blog/static/src/js/website_blog.editor.js2
-rw-r--r--addons/website_blog/views/website_blog_templates.xml10
-rw-r--r--addons/website_sale/models/sale_order.py8
-rw-r--r--addons/website_sale/static/src/css/website_sale.css6
-rw-r--r--addons/website_sale/static/src/css/website_sale.sass6
-rw-r--r--addons/website_sale/views/templates.xml3
-rw-r--r--addons/website_slides/static/src/img/channel-default.jpgbin0 -> 42327 bytes
-rw-r--r--addons/website_slides/view/website_slides.xml2
59 files changed, 447 insertions, 238 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 23b1a849809..db16d61e24e 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -39,7 +39,7 @@ class AccountInvoice(models.Model):
_order = "date_invoice desc, number desc, id desc"
@api.one
- @api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id')
+ @api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id', 'date_invoice')
def _compute_amount(self):
self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line_ids)
self.amount_tax = sum(line.amount for line in self.tax_line_ids)
@@ -47,8 +47,9 @@ class AccountInvoice(models.Model):
amount_total_company_signed = self.amount_total
amount_untaxed_signed = self.amount_untaxed
if self.currency_id and self.currency_id != self.company_id.currency_id:
- amount_total_company_signed = self.currency_id.compute(self.amount_total, self.company_id.currency_id)
- amount_untaxed_signed = self.currency_id.compute(self.amount_untaxed, self.company_id.currency_id)
+ currency_id = self.currency_id.with_context(date=self.date_invoice)
+ amount_total_company_signed = currency_id.compute(self.amount_total, self.company_id.currency_id)
+ amount_untaxed_signed = currency_id.compute(self.amount_untaxed, self.company_id.currency_id)
sign = self.type in ['in_refund', 'out_refund'] and -1 or 1
self.amount_total_company_signed = amount_total_company_signed * sign
self.amount_total_signed = self.amount_total * sign
diff --git a/addons/account/views/report_agedpartnerbalance.xml b/addons/account/views/report_agedpartnerbalance.xml
index 8681931febb..8fa10c8df90 100644
--- a/addons/account/views/report_agedpartnerbalance.xml
+++ b/addons/account/views/report_agedpartnerbalance.xml
@@ -4,7 +4,7 @@
<t t-call="report.html_container">
<t t-call="report.internal_layout">
<div class="page">
- <h2>Aged Trial Balance</h2>
+ <h2>Aged Partner Balance</h2>
<div class="row mt32">
<div class="col-xs-3">
diff --git a/addons/account_asset/models/account_invoice.py b/addons/account_asset/models/account_invoice.py
index 9eb4cca484b..91e6336d23c 100644
--- a/addons/account_asset/models/account_invoice.py
+++ b/addons/account_asset/models/account_invoice.py
@@ -28,8 +28,8 @@ class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
asset_category_id = fields.Many2one('account.asset.category', string='Asset Category')
- asset_start_date = fields.Date(string='Asset End Date', compute='_get_asset_date', readonly=True, store=True)
- asset_end_date = fields.Date(string='Asset Start Date', compute='_get_asset_date', readonly=True, store=True)
+ asset_start_date = fields.Date(string='Asset Start Date', compute='_get_asset_date', readonly=True, store=True)
+ asset_end_date = fields.Date(string='Asset End Date', compute='_get_asset_date', readonly=True, store=True)
asset_mrr = fields.Float(string='Monthly Recurring Revenue', compute='_get_asset_date', readonly=True, digits=dp.get_precision('Account'), store=True)
@api.one
diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py
index bd65166fd65..d3e1a71555b 100644
--- a/addons/calendar/models/calendar.py
+++ b/addons/calendar/models/calendar.py
@@ -916,10 +916,10 @@ class Meeting(models.Model):
meeting_attendees |= attendee
meeting_partners |= partner
- if current_user.email != partner.email:
- attendee._send_mail_to_attendees('calendar.calendar_template_meeting_invitation')
-
if meeting_attendees:
+ to_notify = meeting_attendees.filtered(lambda a: a.email != current_user.email)
+ to_notify._send_mail_to_attendees('calendar.calendar_template_meeting_invitation')
+
meeting.write({'attendee_ids': [(4, meeting_attendee.id) for meeting_attendee in meeting_attendees]})
if meeting_partners:
meeting.message_subscribe(partner_ids=meeting_partners.ids)
diff --git a/addons/event/models/event_mail.py b/addons/event/models/event_mail.py
index a17635efd7d..6a5edd12854 100644
--- a/addons/event/models/event_mail.py
+++ b/addons/event/models/event_mail.py
@@ -71,7 +71,8 @@ class EventMailScheduler(models.Model):
if self.interval_type == 'after_sub':
# update registration lines
lines = []
- for registration in filter(lambda item: item not in [mail_reg.registration_id for mail_reg in self.mail_registration_ids], self.event_id.registration_ids):
+ reg_ids = [mail_reg.registration_id for mail_reg in self.mail_registration_ids]
+ for registration in filter(lambda item: item not in reg_ids, self.event_id.registration_ids):
lines.append((0, 0, {'registration_id': registration.id}))
if lines:
self.write({'mail_registration_ids': lines})
diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py
index 84886443a37..a6b1364308d 100644
--- a/addons/hr_expense/models/hr_expense.py
+++ b/addons/hr_expense/models/hr_expense.py
@@ -254,7 +254,7 @@ class HrExpense(models.Model):
# Calculate tax lines and adjust base line
taxes = expense.tax_ids.compute_all(expense.unit_amount, expense.currency_id, expense.quantity, expense.product_id)
account_move[-1]['price'] = taxes['total_excluded']
- account_move[-1]['tax_ids'] = expense.tax_ids.id
+ account_move[-1]['tax_ids'] = expense.tax_ids.ids
for tax in taxes['taxes']:
account_move.append({
'type': 'tax',
diff --git a/addons/l10n_de_skr03/data/l10n_de_skr03_chart_data.xml b/addons/l10n_de_skr03/data/l10n_de_skr03_chart_data.xml
index 368cd9a5937..d725d573070 100644
--- a/addons/l10n_de_skr03/data/l10n_de_skr03_chart_data.xml
+++ b/addons/l10n_de_skr03/data/l10n_de_skr03_chart_data.xml
@@ -484,7 +484,7 @@
<record model="account.account.template" id="account_1120">
<field name="name">Postbank 2</field>
<field name="code">1120</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -708,7 +708,7 @@
<record model="account.account.template" id="account_1010">
<field name="name">Nebenkasse 1</field>
<field name="code">1010</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -750,14 +750,14 @@
<record model="account.account.template" id="account_1130">
<field name="name">Postbank 3</field>
<field name="code">1130</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
<record model="account.account.template" id="account_1230">
<field name="name">Bank 3</field>
<field name="code">1230</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -806,7 +806,7 @@
<record model="account.account.template" id="account_1330">
<field name="name">Schecks</field>
<field name="code">1330</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -925,7 +925,7 @@
<record model="account.account.template" id="account_1240">
<field name="name">Bank 4</field>
<field name="code">1240</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -1492,7 +1492,7 @@
<record model="account.account.template" id="account_1190">
<field name="name">LZB-Guthaben</field>
<field name="code">1190</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -2850,7 +2850,7 @@
<record model="account.account.template" id="account_1220">
<field name="name">Bank 2</field>
<field name="code">1220</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -3116,7 +3116,7 @@
<record model="account.account.template" id="account_1110">
<field name="name">Postbank 1</field>
<field name="code">1110</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -4019,7 +4019,7 @@
<record model="account.account.template" id="account_1020">
<field name="name">Nebenkasse 2</field>
<field name="code">1020</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -4796,7 +4796,7 @@
<record model="account.account.template" id="account_1210">
<field name="name">Bank 1</field>
<field name="code">1210</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -5020,7 +5020,7 @@
<record model="account.account.template" id="account_1100">
<field name="name">Postbank</field>
<field name="code">1100</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -6161,7 +6161,7 @@
<record model="account.account.template" id="account_1250">
<field name="name">Bank 5</field>
<field name="code">1250</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -6511,7 +6511,7 @@
<record model="account.account.template" id="account_1195">
<field name="name">Bundesbankguthaben</field>
<field name="code">1195</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
@@ -7218,7 +7218,7 @@
<record model="account.account.template" id="account_1360">
<field name="name">Geldtransit</field>
<field name="code">1360</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_de_chart_template"/>
</record>
diff --git a/addons/l10n_de_skr04/data/l10n_de_skr04_chart_data.xml b/addons/l10n_de_skr04/data/l10n_de_skr04_chart_data.xml
index 81b0d42574f..fb9f9bf758d 100644
--- a/addons/l10n_de_skr04/data/l10n_de_skr04_chart_data.xml
+++ b/addons/l10n_de_skr04/data/l10n_de_skr04_chart_data.xml
@@ -3463,7 +3463,7 @@
<record id="chart_skr04_1460" model="account.account.template">
<field name="code">1460</field>
<field name="name">Geldtransit</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3615,7 +3615,7 @@
<record id="chart_skr04_1610" model="account.account.template">
<field name="code">1610</field>
<field name="name">Nebenkasse 1</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3623,7 +3623,7 @@
<record id="chart_skr04_1620" model="account.account.template">
<field name="code">1620</field>
<field name="name">Nebenkasse 2</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3631,7 +3631,7 @@
<record id="chart_skr04_1700" model="account.account.template">
<field name="code">1700</field>
<field name="name">Postbank</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3639,7 +3639,7 @@
<record id="chart_skr04_1710" model="account.account.template">
<field name="code">1710</field>
<field name="name">Postbank 1</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3647,7 +3647,7 @@
<record id="chart_skr04_1720" model="account.account.template">
<field name="code">1720</field>
<field name="name">Postbank 2</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3655,7 +3655,7 @@
<record id="chart_skr04_1730" model="account.account.template">
<field name="code">1730</field>
<field name="name">Postbank 3</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3679,7 +3679,7 @@
<record id="chart_skr04_1810" model="account.account.template">
<field name="code">1810</field>
<field name="name">Bank 1</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3687,7 +3687,7 @@
<record id="chart_skr04_1820" model="account.account.template">
<field name="code">1820</field>
<field name="name">Bank 2</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3695,7 +3695,7 @@
<record id="chart_skr04_1830" model="account.account.template">
<field name="code">1830</field>
<field name="name">Bank 3</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3703,7 +3703,7 @@
<record id="chart_skr04_1840" model="account.account.template">
<field name="code">1840</field>
<field name="name">Bank 4</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
@@ -3711,7 +3711,7 @@
<record id="chart_skr04_1850" model="account.account.template">
<field name="code">1850</field>
<field name="name">Bank 5</field>
- <field name="reconcile" eval="True"/>
+ <field name="reconcile" eval="False"/>
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
<field name="chart_template_id" ref="l10n_chart_de_skr04"/>
</record>
diff --git a/addons/l10n_fr/data/account_fiscal_position_template_data.xml b/addons/l10n_fr/data/account_fiscal_position_template_data.xml
index 68be1323c2c..51108bb0be8 100644
--- a/addons/l10n_fr/data/account_fiscal_position_template_data.xml
+++ b/addons/l10n_fr/data/account_fiscal_position_template_data.xml
@@ -38,30 +38,55 @@
<field name="tax_src_id" ref="tva_normale" />
<field name="tax_dest_id" ref="tva_intra_0" />
</record>
+ <record id="fp_tax_template_intraeub2b_vt_normale_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_intraeub2b" />
+ <field name="tax_src_id" ref="tva_normale_ttc" />
+ <field name="tax_dest_id" ref="tva_intra_0" />
+ </record>
<!-- Taux DOM-TOM -->
<record id="fp_tax_template_intraeub2b_vt_specifique" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_intraeub2b" />
<field name="tax_src_id" ref="tva_specifique" />
<field name="tax_dest_id" ref="tva_intra_0" />
</record>
+ <record id="fp_tax_template_intraeub2b_vt_specifique_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_intraeub2b" />
+ <field name="tax_src_id" ref="tva_specifique_ttc" />
+ <field name="tax_dest_id" ref="tva_intra_0" />
+ </record>
<!-- Taux Intermédiaire -->
<record id="fp_tax_template_intraeub2b_vt_intermediaire" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_intraeub2b" />
<field name="tax_src_id" ref="tva_intermediaire" />
<field name="tax_dest_id" ref="tva_intra_0" />
</record>
+ <record id="fp_tax_template_intraeub2b_vt_intermediaire_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_intraeub2b" />
+ <field name="tax_src_id" ref="tva_intermediaire_ttc" />
+ <field name="tax_dest_id" ref="tva_intra_0" />
+ </record>
<!-- Taux réduit -->
<record id="fp_tax_template_intraeub2b_vt_reduite" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_intraeub2b" />
<field name="tax_src_id" ref="tva_reduite" />
<field name="tax_dest_id" ref="tva_intra_0" />
</record>
+ <record id="fp_tax_template_intraeub2b_vt_reduite_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_intraeub2b" />
+ <field name="tax_src_id" ref="tva_reduite_ttc" />
+ <field name="tax_dest_id" ref="tva_intra_0" />
+ </record>
<!-- Taux super réduit -->
<record id="fp_tax_template_intraeub2b_vt_super_reduite" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_intraeub2b" />
<field name="tax_src_id" ref="tva_super_reduite" />
<field name="tax_dest_id" ref="tva_intra_0" />
</record>
+ <record id="fp_tax_template_intraeub2b_vt_super_reduite_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_intraeub2b" />
+ <field name="tax_src_id" ref="tva_super_reduite_ttc" />
+ <field name="tax_dest_id" ref="tva_intra_0" />
+ </record>
<!-- achats -->
<!-- Taux Normal -->
<record id="fp_tax_template_intraeub2b_ha_normale_deduc" model="account.fiscal.position.tax.template">
@@ -127,30 +152,55 @@
<field name="tax_src_id" ref="tva_normale" />
<field name="tax_dest_id" ref="tva_export_0" />
</record>
+ <record id="fp_tax_template_impexp_vt_normale_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_import_export" />
+ <field name="tax_src_id" ref="tva_normale_ttc" />
+ <field name="tax_dest_id" ref="tva_export_0" />
+ </record>
<!-- Taux DOM-TOM -->
<record id="fp_tax_template_impexp_vt_specifique" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import_export" />
<field name="tax_src_id" ref="tva_specifique" />
<field name="tax_dest_id" ref="tva_export_0" />
</record>
+ <record id="fp_tax_template_impexp_vt_specifique_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_import_export" />
+ <field name="tax_src_id" ref="tva_specifique_ttc" />
+ <field name="tax_dest_id" ref="tva_export_0" />
+ </record>
<!-- Taux Intermédiare -->
<record id="fp_tax_template_impexp_vt_intermediaire" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import_export" />
<field name="tax_src_id" ref="tva_intermediaire" />
<field name="tax_dest_id" ref="tva_export_0" />
</record>
+ <record id="fp_tax_template_impexp_vt_intermediaire_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_import_export" />
+ <field name="tax_src_id" ref="tva_intermediaire_ttc" />
+ <field name="tax_dest_id" ref="tva_export_0" />
+ </record>
<!-- Taux Réduit -->
<record id="fp_tax_template_impexp_vt_reduite" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import_export" />
<field name="tax_src_id" ref="tva_reduite" />
<field name="tax_dest_id" ref="tva_export_0" />
</record>
+ <record id="fp_tax_template_impexp_vt_reduite_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_import_export" />
+ <field name="tax_src_id" ref="tva_reduite_ttc" />
+ <field name="tax_dest_id" ref="tva_export_0" />
+ </record>
<!-- Taux super réduit -->
<record id="fp_tax_template_impexp_vt_super_reduite" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import_export" />
<field name="tax_src_id" ref="tva_super_reduite" />
<field name="tax_dest_id" ref="tva_export_0" />
</record>
+ <record id="fp_tax_template_impexp_vt_super_reduite_ttc" model="account.fiscal.position.tax.template">
+ <field name="position_id" ref="fiscal_position_template_import_export" />
+ <field name="tax_src_id" ref="tva_super_reduite_ttc" />
+ <field name="tax_dest_id" ref="tva_export_0" />
+ </record>
<!-- achats -->
<!-- Taux Normal -->
diff --git a/addons/l10n_fr/data/account_tax_data.xml b/addons/l10n_fr/data/account_tax_data.xml
index 7778e6ef82d..1d14f61cae1 100644
--- a/addons/l10n_fr/data/account_tax_data.xml
+++ b/addons/l10n_fr/data/account_tax_data.xml
@@ -32,6 +32,31 @@
<field name="applicability">taxes</field>
</record>
+ <record id="tax_20_0_TTC" model="account.account.tag">
+ <field name="name">20.0-TTC</field>
+ <field name="applicability">taxes</field>
+ </record>
+
+ <record id="tax_10_0_TTC" model="account.account.tag">
+ <field name="name">10.0-TTC</field>
+ <field name="applicability">taxes</field>
+ </record>
+
+ <record id="tax_8_5_TTC" model="account.account.tag">
+ <field name="name">8.5-TTC</field>
+ <field name="applicability">taxes</field>
+ </record>
+
+ <record id="tax_5_5_TTC" model="account.account.tag">
+ <field name="name">5.5-TTC</field>
+ <field name="applicability">taxes</field>
+ </record>
+
+ <record id="tax_2_1_TTC" model="account.account.tag">
+ <field name="name">2.1-TTC</field>
+ <field name="applicability">taxes</field>
+ </record>
+
<record id="tax_ACH-8_5" model="account.account.tag">
<field name="name">ACH-8_5</field>
<field name="applicability">taxes</field>
@@ -249,6 +274,77 @@
</record>
+<!-- VENTES Tax INCLUDE (TTC) -->
+ <record model="account.tax.template" id="tva_normale_ttc">
+ <field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
+ <field name="name">TVA collectée (vente) 20,0% TTC</field>
+ <field name="description">20.0-TTC</field>
+ <field name="price_include" eval="1"/>
+ <field name="amount" eval="20.0"/>
+ <field name="amount_type">percent</field>
+ <field name="refund_account_id" ref="pcg_445711"/>
+ <field name="account_id" ref="pcg_445711"/>
+ <field name="sequence" eval="10"/>
+ <field name="type_tax_use">sale</field>
+ <field name="tag_ids" eval="[(6,0,[ref('l10n_fr.tax_20_0_TTC')])]"/>
+ </record>
+
+ <record model="account.tax.template" id="tva_specifique_ttc">
+ <field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
+ <field name="name">TVA collectée (vente) 8,5% TTC</field>
+ <field name="description">8.5-TTC</field>
+ <field name="price_include" eval="1"/>
+ <field name="amount" eval="8.5"/>
+ <field name="amount_type">percent</field>
+ <field name="refund_account_id" ref="pcg_445713"/>
+ <field name="account_id" ref="pcg_445713"/>
+ <field name="sequence" eval="10"/>
+ <field name="type_tax_use">sale</field>
+ <field name="tag_ids" eval="[(6,0,[ref('l10n_fr.tax_8_5_TTC')])]"/>
+ </record>
+
+ <record model="account.tax.template" id="tva_intermediaire_ttc">
+ <field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
+ <field name="name">TVA collectée (vente) 10,0% TTC</field>
+ <field name="description">10.0-TTC</field>
+ <field name="price_include" eval="1"/>
+ <field name="amount" eval="10.0"/>
+ <field name="amount_type">percent</field>
+ <field name="refund_account_id" ref="pcg_445712"/>
+ <field name="account_id" ref="pcg_445712"/>
+ <field name="sequence" eval="10"/>
+ <field name="type_tax_use">sale</field>
+ <field name="tag_ids" eval="[(6,0,[ref('l10n_fr.tax_10_0_TTC')])]"/>
+ </record>
+
+ <record model="account.tax.template" id="tva_reduite_ttc">
+ <field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
+ <field name="name">TVA collectée (vente) 5,5% TTC</field>
+ <field name="description">5.5-TTC</field>
+ <field name="price_include" eval="1"/>
+ <field name="amount" eval="5.5"/>
+ <field name="amount_type">percent</field>
+ <field name="refund_account_id" ref="pcg_445713"/>
+ <field name="account_id" ref="pcg_445713"/>
+ <field name="sequence" eval="10"/>
+ <field name="type_tax_use">sale</field>
+ <field name="tag_ids" eval="[(6,0,[ref('l10n_fr.tax_5_5_TTC')])]"/>
+ </record>
+
+ <record model="account.tax.template" id="tva_super_reduite_ttc">
+ <field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
+ <field name="name">TVA collectée (vente) 2,1% TTC</field>
+ <field name="description">2.1-TTC</field>
+ <field name="price_include" eval="1"/>
+ <field name="amount" eval="2.1"/>
+ <field name="amount_type">percent</field>
+ <field name="refund_account_id" ref="pcg_445713"/>
+ <field name="account_id" ref="pcg_445713"/>
+ <field name="sequence" eval="10"/>
+ <field name="type_tax_use">sale</field>
+ <field name="tag_ids" eval="[(6,0,[ref('l10n_fr.tax_2_1_TTC')])]"/>
+ </record>
+
<!-- ACHATS Tax excluded from price -->
<record model="account.tax.template" id="tva_acq_normale">
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
diff --git a/addons/mail/models/mail_template.py b/addons/mail/models/mail_template.py
index 8508fa9f250..d87cad5fec7 100644
--- a/addons/mail/models/mail_template.py
+++ b/addons/mail/models/mail_template.py
@@ -488,7 +488,7 @@ class MailTemplate(models.Model):
)
# Add report in attachments: generate once for all template_res_ids
- if template.report_template and not 'report_template_in_attachment' in self.env.context:
+ if template.report_template:
for res_id in template_res_ids:
attachments = []
report_name = self.render_template(template.report_name, template.model, res_id)
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 7363bf6510b..6af6a2206f4 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -1692,12 +1692,14 @@ class MailThread(models.AbstractModel):
m2m_attachment_ids += [(4, id) for id in attachment_ids]
# Handle attachments parameter, that is a dictionary of attachments
for attachment in attachments:
+ cid = False
if len(attachment) == 2:
name, content = attachment
elif len(attachment) == 3:
name, content, info = attachment
if info and info.get('cid'):
- cid_mapping[info['cid']] = name
+ cid = info['cid']
+ cid_mapping[cid] = name
else:
continue
if isinstance(content, unicode):
@@ -1705,7 +1707,7 @@ class MailThread(models.AbstractModel):
data_attach = {
'name': name,
'datas': base64.b64encode(str(content)),
- 'datas_fname': name,
+ 'datas_fname': cid or name,
'description': name,
'res_model': message_data['model'],
'res_id': message_data['res_id'],
@@ -1718,8 +1720,11 @@ class MailThread(models.AbstractModel):
postprocessed = False
for node in root.iter('img'):
if node.get('src', '').startswith('cid:'):
- fname = cid_mapping.get(node.get('src').split('cid:')[1], node.get('data-filename', ''))
- attachment = parameter_attachments.filtered(lambda attachment: attachment.name == fname)
+ cid = node.get('src').split('cid:')[1]
+ fname = cid_mapping.get(cid, node.get('data-filename', ''))
+ attachment = parameter_attachments.filtered(lambda attachment: attachment.datas_fname == cid)
+ if not attachment:
+ attachment = parameter_attachments.filtered(lambda attachment: attachment.datas_fname == fname)
if attachment:
node.set('src', '/web/image/%s' % attachment.ids[0])
postprocessed = True
diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index acaf1825348..9cf1c22e482 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -192,7 +192,7 @@ class MailComposer(models.TransientModel):
@api.multi
def send_mail_action(self):
# TDE/ ???
- return self.with_context(report_template_in_attachment=True).send_mail()
+ return self.send_mail()
@api.multi
def send_mail(self, auto_commit=False):
@@ -358,20 +358,6 @@ class MailComposer(models.TransientModel):
if template.user_signature and 'body_html' in values:
signature = self.env.user.signature
values['body_html'] = tools.append_content_to_html(values['body_html'], signature, plaintext=False)
- if template.report_template:
- attachment = self.env['ir.attachment']
- attach = self.generate_attachment_from_report(template_id, res_id)
- for attach_fname, attach_datas in attach[res_id].pop('attachments', []):
- data_attach = {
- 'name': attach_fname,
- 'datas': attach_datas,
- 'datas_fname': attach_fname,
- 'res_model': 'mail.compose.message',
- 'res_id': 0,
- 'type': 'binary',
- }
- values.setdefault('attachment_ids', list()).append(attachment.create(data_attach).id)
-
elif template_id:
values = self.generate_email_for_composer(template_id, [res_id])[res_id]
# transform attachments into attachment_ids; not attached to the document because this will
@@ -403,13 +389,6 @@ class MailComposer(models.TransientModel):
return {'value': values}
@api.multi
- def generate_attachment_from_report(self, template_id, res_id):
- fields = ['attachment_ids']
- result = self.env['mail.template'].with_context(tpl_partners_only=True).browse(template_id).generate_email([res_id], fields=fields)
- return result
-
-
- @api.multi
def save_as_template(self):
""" hit save as template button: current form value will be a new
template attached to the current document. """
diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py
index 0fbc3c030e1..3feb7b498be 100644
--- a/addons/mrp/models/mrp_bom.py
+++ b/addons/mrp/models/mrp_bom.py
@@ -111,6 +111,11 @@ class MrpBom(models.Model):
return self.search(domain, order='sequence, product_id', limit=1)
def explode(self, product, quantity, picking_type=False):
+ """
+ Explodes the BoM and creates two lists with all the information you need: bom_done and line_done
+ Quantity describes the number of times you need the BoM: so the quantity divided by the number created by the BoM
+ and converted into its UoM
+ """
boms_done = [(self, {'qty': quantity, 'product': product, 'original_qty': quantity, 'parent_line': False})]
lines_done = []
templates_done = product.product_tmpl_id
@@ -125,11 +130,11 @@ class MrpBom(models.Model):
if current_line.product_id.product_tmpl_id in templates_done:
raise UserError(_('Recursion error! A product with a Bill of Material should not have itself in its BoM or child BoMs!'))
- line_quantity = current_qty * current_line.product_qty / current_line.bom_id.product_qty
+ line_quantity = current_qty * current_line.product_qty
bom = self._bom_find(product=current_line.product_id, picking_type=picking_type or self.picking_type_id, company_id=self.company_id.id)
if bom.type == 'phantom':
- converted_line_quantity = current_line.product_uom_id._compute_quantity(line_quantity, bom.product_uom_id)
- bom_lines = [(line, current_line.product_id, line_quantity, current_line) for line in bom.bom_line_ids] + bom_lines
+ converted_line_quantity = current_line.product_uom_id._compute_quantity(line_quantity / bom.product_qty, bom.product_uom_id)
+ bom_lines = [(line, current_line.product_id, converted_line_quantity, current_line) for line in bom.bom_line_ids] + bom_lines
templates_done |= current_line.product_id.product_tmpl_id
boms_done.append((bom, {'qty': converted_line_quantity, 'product': current_product, 'original_qty': quantity, 'parent_line': current_line}))
else:
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index 7d6bc5d881b..d0f5a2f00f4 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -55,7 +55,7 @@ class MrpProduction(models.Model):
states={'confirmed': [('readonly', False)]})
product_tmpl_id = fields.Many2one('product.template', 'Product Template', related='product_id.product_tmpl_id')
product_qty = fields.Float(
- 'Quantity to Produce',
+ 'Quantity To Produce',
default=1.0, digits=dp.get_precision('Product Unit of Measure'),
readonly=True, required=True,
states={'confirmed': [('readonly', False)]})
@@ -79,12 +79,12 @@ class MrpProduction(models.Model):
states={'confirmed': [('readonly', False)]},
help="Location where the system will stock the finished products.")
date_planned_start = fields.Datetime(
- 'Expected Start Date', copy=False, default=fields.Datetime.now,
- index=True, required=True, readonly=True,
+ 'Deadline Start', copy=False, default=fields.Datetime.now,
+ index=True, required=True,
states={'confirmed': [('readonly', False)]}, oldname="date_planned")
date_planned_finished = fields.Datetime(
- 'Expected End Date', copy=False, default=fields.Datetime.now,
- index=True, readonly=True,
+ 'Deadline End', copy=False, default=fields.Datetime.now,
+ index=True,
states={'confirmed': [('readonly', False)]})
date_start = fields.Datetime('Start Date', copy=False, index=True, readonly=True)
date_finished = fields.Datetime('End Date', copy=False, index=True, readonly=True)
@@ -264,7 +264,7 @@ class MrpProduction(models.Model):
def _generate_moves(self):
for production in self:
production._generate_finished_moves()
- factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id)
+ factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) / production.bom_id.product_qty
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
production._generate_raw_moves(lines)
# Check for all draft moves whether they are mto or not
@@ -311,8 +311,7 @@ class MrpProduction(models.Model):
source_location = self.bom_id.routing_id.location_id
else:
source_location = self.location_src_id
- original_quantity = self.product_uom_id._compute_quantity(self.product_qty, self.bom_id.product_uom_id)
-
+ original_quantity = self.product_qty - self.qty_produced
data = {
'name': self.name,
'date': self.date_planned_start,
@@ -354,14 +353,21 @@ class MrpProduction(models.Model):
move.procure_method = 'make_to_order'
@api.multi
- def _update_raw_move(self, bom_line, quantity, **kw):
+ def _update_raw_move(self, bom_line, line_data):
+ quantity = line_data['qty']
self.ensure_one()
move = self.move_raw_ids.filtered(lambda x: x.bom_line_id.id == bom_line.id and x.state not in ('done', 'cancel'))
if move:
- move.write({'product_uom_qty': quantity})
+ if quantity > 0:
+ move[0].write({'product_uom_qty': quantity})
+ else:
+ if move[0].quantity_done > 0:
+ raise UserError(_('Lines need to be deleted, but can not as you still have some quantities to consume in them. '))
+ move[0].action_cancel()
+ move[0].unlink()
return move
else:
- self._generate_raw_move(bom_line, quantity)
+ self._generate_raw_move(bom_line, line_data)
@api.multi
def action_assign(self):
@@ -381,7 +387,7 @@ class MrpProduction(models.Model):
""" Create work orders. And probably do stuff, like things. """
orders_to_plan = self.filtered(lambda order: order.routing_id and order.state == 'confirmed')
for order in orders_to_plan:
- quantity = order.product_uom_id._compute_quantity(order.product_qty, order.bom_id.product_uom_id)
+ quantity = order.product_uom_id._compute_quantity(order.product_qty, order.bom_id.product_uom_id) / order.bom_id.product_qty
boms, lines = order.bom_id.explode(order.product_id, quantity, picking_type=order.bom_id.picking_type_id)
order._generate_workorders(boms)
orders_to_plan.write({'state': 'planned'})
@@ -401,19 +407,18 @@ class MrpProduction(models.Model):
BoMs
"""
workorders = self.env['mrp.workorder']
- qty = bom_data['qty']
+ bom_qty = bom_data['qty']
- use_serial = any(product.tracking == 'serial' for product in self.mapped('move_finished_ids.product_id'))
- if use_serial:
+ # Initial qty producing
+ if self.product_id.tracking == 'serial':
quantity = 1.0
else:
quantity = self.product_qty - sum(self.move_finished_ids.mapped('quantity_done'))
quantity = quantity if (quantity > 0) else 0
- # TDE FIXME: what is qty compared to quantity ??
for operation in bom.routing_id.operation_ids:
# create workorder
- cycle_number = math.ceil(qty / bom.product_qty / operation.workcenter_id.capacity) # TODO: float_round UP
+ cycle_number = math.ceil(bom_qty / operation.workcenter_id.capacity) # TODO: float_round UP
duration_expected = (operation.workcenter_id.time_start +
operation.workcenter_id.time_stop +
cycle_number * operation.time_cycle * 100.0 / operation.workcenter_id.time_efficiency)
@@ -513,7 +518,7 @@ class MrpProduction(models.Model):
self.post_inventory()
moves_to_cancel = (self.move_raw_ids | self.move_finished_ids).filtered(lambda x: x.state not in ('done', 'cancel'))
moves_to_cancel.action_cancel()
- self.write({'state': 'done', 'date_finished': fields.datetime.now()})
+ self.write({'state': 'done', 'date_finished': fields.Datetime.now()})
self.env["procurement.order"].search([('production_id', 'in', self.ids)]).check()
self.write({'state': 'done'})
diff --git a/addons/mrp/models/mrp_routing.py b/addons/mrp/models/mrp_routing.py
index b9effeadd8d..832b0328e89 100644
--- a/addons/mrp/models/mrp_routing.py
+++ b/addons/mrp/models/mrp_routing.py
@@ -69,6 +69,7 @@ class MrpRoutingWorkcenter(models.Model):
batch = fields.Selection([
('no', 'Once all products are processed'),
('yes', 'Once a minimum number of products is processed')], string='Next Operation',
+ help="""Will determine if the next work order will be planned after the previous one or after the first Quantity To Process of the previous one.""",
default='no', required=True)
batch_size = fields.Float('Quantity to Process', default=1.0)
workorder_ids = fields.One2many('mrp.workorder', 'operation_id', string="Work Orders")
diff --git a/addons/mrp/models/mrp_unbuild.py b/addons/mrp/models/mrp_unbuild.py
index 0abd787fbf0..7254101505e 100644
--- a/addons/mrp/models/mrp_unbuild.py
+++ b/addons/mrp/models/mrp_unbuild.py
@@ -154,8 +154,8 @@ class MrpUnbuild(models.Model):
def _generate_produce_moves(self):
moves = self.env['stock.move']
for unbuild in self:
- factor = unbuild.product_uom_id._compute_quantity(unbuild.product_qty, unbuild.bom_id.product_uom_id)
- boms, lines = unbuild.bom_id.explode(unbuild.product_id, factor / unbuild.bom_id.product_qty, picking_type=unbuild.bom_id.picking_type_id)
+ factor = unbuild.product_uom_id._compute_quantity(unbuild.product_qty, unbuild.bom_id.product_uom_id) / unbuild.bom_id.product_qty
+ boms, lines = unbuild.bom_id.explode(unbuild.product_id, factor, picking_type=unbuild.bom_id.picking_type_id)
for line, line_data in lines:
moves += unbuild._generate_move_from_bom_line(line, line_data['qty'])
return moves
diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py
index 161c18e6473..b47294465ce 100644
--- a/addons/mrp/models/mrp_workcenter.py
+++ b/addons/mrp/models/mrp_workcenter.py
@@ -42,10 +42,10 @@ class MrpWorkcenter(models.Model):
('done', 'In Progress')], 'Status', compute="_compute_working_state", store=True)
blocked_time = fields.Float(
'Blocked Time', compute='_compute_blocked_time',
- help='Blocked hours over the last month')
+ help='Blocked hour(s) over the last month', digits=(16, 2))
productive_time = fields.Float(
'Productive Time', compute='_compute_productive_time',
- help='Productive hours over the last month')
+ help='Productive hour(s) over the last month', digits=(16, 2))
oee = fields.Float(compute='_compute_oee', help='Overall Equipment Effectiveness, based on the last month')
oee_target = fields.Float(string='OEE Target', help="OEE Target in percentage", default=90)
performance = fields.Integer('Performance', compute='_compute_performance', help='Performance over the last month')
@@ -99,7 +99,7 @@ class MrpWorkcenter(models.Model):
['duration', 'workcenter_id'], ['workcenter_id'], lazy=False)
count_data = dict((item['workcenter_id'][0], item['duration']) for item in data)
for workcenter in self:
- workcenter.blocked_time = count_data.get(workcenter.id, 0.0)
+ workcenter.blocked_time = count_data.get(workcenter.id, 0.0) / 60.0
@api.multi
def _compute_productive_time(self):
@@ -112,15 +112,15 @@ class MrpWorkcenter(models.Model):
['duration', 'workcenter_id'], ['workcenter_id'], lazy=False)
count_data = dict((item['workcenter_id'][0], item['duration']) for item in data)
for workcenter in self:
- workcenter.productive_time = count_data.get(workcenter.id, 0.0)
+ workcenter.productive_time = count_data.get(workcenter.id, 0.0) / 60.0
@api.depends('blocked_time', 'productive_time')
- @api.one
def _compute_oee(self):
- if self.productive_time:
- self.oee = round(self.productive_time * 100.0 / (self.productive_time + self.blocked_time), 2)
- else:
- self.oee = 0.0
+ for order in self:
+ if order.productive_time:
+ order.oee = round(order.productive_time * 100.0 / (order.productive_time + order.blocked_time), 2)
+ else:
+ order.oee = 0.0
@api.multi
def _compute_performance(self):
@@ -185,7 +185,7 @@ class MrpWorkcenterProductivity(models.Model):
loss_type = fields.Selection(
"Effectiveness", related='loss_id.loss_type', store=True)
description = fields.Text('Description')
- date_start = fields.Datetime('Start Date', default=fields.Datetime.now(), required=True)
+ date_start = fields.Datetime('Start Date', default=fields.Datetime.now, required=True)
date_end = fields.Datetime('End Date')
duration = fields.Float('Duration', compute='_compute_duration', store=True)
diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py
index 61a4ccbf21e..920d8b0bc4c 100644
--- a/addons/mrp/models/mrp_workorder.py
+++ b/addons/mrp/models/mrp_workorder.py
@@ -214,11 +214,15 @@ class MrpWorkorder(models.Model):
for move_lot in move_lots:
if qty_todo <= 0:
break
- if move_lot.quantity_done == 0 and qty_todo > move_lot.quantity:
+ if not move_lot.lot_id and qty_todo >= move_lot.quantity:
qty_todo = qty_todo - move_lot.quantity
self.active_move_lot_ids -= move_lot # Difference operator
else:
move_lot.quantity = move_lot.quantity - qty_todo
+ if move_lot.quantity_done - qty_todo > 0:
+ move_lot.quantity_done = move_lot.quantity_done - qty_todo
+ else:
+ move_lot.quantity_done = 0
qty_todo = 0
@api.multi
diff --git a/addons/mrp/models/product.py b/addons/mrp/models/product.py
index b4e46fda938..c3f457adb56 100644
--- a/addons/mrp/models/product.py
+++ b/addons/mrp/models/product.py
@@ -29,11 +29,8 @@ class ProductTemplate(models.Model):
def action_view_mos(self):
product_ids = self.mapped('product_variant_ids').ids
action = self.env.ref('mrp.act_product_mrp_production').read()[0]
- if len(self) == 1 and len(product_ids) == 1:
- action['context'] = {'default_product_id': product_ids[0], 'search_default_product_id': product_ids[0]}
- else:
- action['domain'] = [('product_id', 'in', product_ids)]
- action['context'] = {}
+ action['domain'] = [('product_id', 'in', product_ids)]
+ action['context'] = {}
return action
diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index e3dd9e07994..5c539195444 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -165,31 +165,70 @@ class StockMove(models.Model):
return True
@api.multi
+ def _create_extra_move(self):
+ ''' Creates an extra move if necessary depending on extra quantities than foreseen or extra moves'''
+ self.ensure_one()
+ quantity_to_split = 0
+ extra_move = self.env['stock.move']
+ rounding = self.product_uom.rounding
+ link_procurement = False
+ if self.procurement_id and self.production_id and float_compare(self.production_id.qty_produced, self.procurement_id.product_qty, precision_rounding=rounding) > 0:
+ done_moves_total = sum(self.production_id.move_finished_ids.filtered(lambda x: x.product_id == self.product_id and x.state == 'done').mapped('product_uom_qty'))
+ if float_compare(done_moves_total, self.procurement_id.product_qty, precision_rounding=rounding) >= 0:
+ quantity_to_split = 0
+ self.product_uom_qty = self.quantity_done #TODO: could change qty on move_dest_id also (in case of 2-step in/out)
+ else:
+ quantity_to_split = done_moves_total + self.quantity_done - self.procurement_id.product_qty
+ elif float_compare(self.quantity_done, self.product_uom_qty, precision_rounding=rounding) > 0:
+ quantity_to_split = self.quantity_done - self.product_uom_qty
+ link_procurement = True
+ if quantity_to_split:
+ extra_move = self.copy(default={'quantity_done': quantity_to_split, 'product_uom_qty': quantity_to_split, 'production_id': self.production_id.id,
+ 'raw_material_production_id': self.raw_material_production_id.id,
+ 'procurement_id': link_procurement and self.procurement_id.id or False})
+ extra_move.action_confirm()
+ if self.has_tracking != 'none':
+ qty_todo = self.quantity_done - quantity_to_split
+ for movelot in self.move_lot_ids.filtered(lambda x: x.done_wo):
+ if movelot.quantity_done and movelot.done_wo:
+ if float_compare(qty_todo, movelot.quantity_done, precision_rounding=rounding) >= 0:
+ qty_todo -= movelot.quantity_done
+ elif float_compare(qty_todo, 0, precision_rounding=rounding) > 0:
+ #split
+ remaining = movelot.quantity_done - qty_todo
+ movelot.quantity_done = qty_todo
+ movelot.copy(default={'move_id': extra_move.id, 'quantity_done': remaining})
+ qty_todo = 0
+ else:
+ movelot.move_id = extra_move.id
+ else:
+ self.quantity_done = self.product_uom_qty
+ self.product_uom_qty = self.quantity_done - quantity_to_split
+ return extra_move
+
+ @api.multi
def move_validate(self):
''' Validate moves based on a production order. '''
moves = self._filter_closed_moves()
quant_obj = self.env['stock.quant']
moves_todo = self.env['stock.move']
moves_to_unreserve = self.env['stock.move']
+ # Create extra moves where necessary
for move in moves:
rounding = move.product_uom.rounding
if float_compare(move.quantity_done, 0.0, precision_rounding=rounding) <= 0:
continue
moves_todo |= move
- if float_compare(move.quantity_done, move.product_uom_qty, precision_rounding=rounding) > 0:
- remaining_qty = move.quantity_done - move.product_uom_qty # In UoM of move
- extra_move = move.copy(default={'quantity_done': remaining_qty, 'product_uom_qty': remaining_qty, 'production_id': move.production_id.id,
- 'raw_material_production_id': move.raw_material_production_id.id})
- move.quantity_done = move.product_uom_qty
- extra_move.action_confirm()
- moves_todo |= extra_move
+ moves_todo |= move._create_extra_move()
+ # Split moves where necessary and move quants
for move in moves_todo:
- if float_compare(move.quantity_done, move.product_uom_qty, precision_rounding=rounding):
+ rounding = move.product_uom.rounding
+ if float_compare(move.quantity_done, move.product_uom_qty, precision_rounding=rounding) < 0:
# Need to do some kind of conversion here
qty_split = move.product_uom._compute_quantity(move.product_uom_qty - move.quantity_done, move.product_id.uom_id)
new_move = move.split(qty_split)
# If you were already putting stock.move.lots on the next one in the work order, transfer those to the new move
- move.move_lot_ids.filtered(lambda x: not x.done_wo).write({'move_id': new_move})
+ move.move_lot_ids.filtered(lambda x: not x.done_wo or x.quantity_done == 0.0).write({'move_id': new_move})
self.browse(new_move).quantity_done = 0.0
main_domain = [('qty', '>', 0)]
preferred_domain = [('reservation_id', '=', move.id)]
diff --git a/addons/mrp/models/stock_scrap.py b/addons/mrp/models/stock_scrap.py
index b78b896c8f0..b672176636b 100644
--- a/addons/mrp/models/stock_scrap.py
+++ b/addons/mrp/models/stock_scrap.py
@@ -41,6 +41,7 @@ class StockScrap(models.Model):
def _prepare_move_values(self):
vals = super(StockScrap, self)._prepare_move_values()
if self.production_id:
+ vals['origin'] = vals['origin'] or self.production_id.name
if self.product_id in self.production_id.move_finished_ids.mapped('product_id'):
vals.update({'production_id': self.production_id.id})
else:
diff --git a/addons/mrp/views/mrp_bom_views.xml b/addons/mrp/views/mrp_bom_views.xml
index 07b851d168d..45e7d7cc842 100644
--- a/addons/mrp/views/mrp_bom_views.xml
+++ b/addons/mrp/views/mrp_bom_views.xml
@@ -48,7 +48,7 @@
<field name="product_qty"/>
<field name="product_uom_id" options="{'no_open':True,'no_create':True}" groups="product.group_uom"/>
<field name="attribute_value_ids" widget="many2many_tags" domain="[('product_ids.product_tmpl_id', '=', parent.product_tmpl_id)]" groups="product.group_product_variant"/>
- <field name="operation_id" groups="mrp.group_mrp_routings" domain="[('routing_id', '=', parent.routing_id)]"/>
+ <field name="operation_id" groups="mrp.group_mrp_routings" domain="[('routing_id', '=', parent.routing_id)]" options="{'no_quick_create':True,'no_create_edit':True}"/>
</tree>
</field>
</page>
@@ -78,6 +78,7 @@
<field name="arch" type="xml">
<tree string="Bill of Materials" default_order="product_tmpl_id">
<field name="active" invisible="1"/>
+ <field name="sequence" invisible="1"/>
<field name="product_tmpl_id"/>
<field name="code"/>
<field name="product_id" groups="product.group_product_variant"/>
diff --git a/addons/mrp/views/mrp_production_views.xml b/addons/mrp/views/mrp_production_views.xml
index ed1284cf2c8..003e703818a 100644
--- a/addons/mrp/views/mrp_production_views.xml
+++ b/addons/mrp/views/mrp_production_views.xml
@@ -48,8 +48,8 @@
<button name="button_mark_done" attrs="{'invisible': [('check_to_done', '=', False)]}" string="Mark as Done" type="object" class="oe_highlight"/>
<button name="action_assign" attrs="{'invisible': [('availability', 'in', ('assigned', 'none'))]}" string="Check availability" type="object" class="oe_highlight"/>
<button name="button_plan" attrs="{'invisible': ['|', ('state', '!=', 'confirmed'), ('routing_id', '=', False)]}" type="object" string="Create Workorders" class="oe_highlight"/>
- <button name="open_produce_product" attrs="{'invisible': ['|', '|', ('availability', 'not in', ['partially_available', 'assigned']), ('state', 'not in', ('confirmed','progress')), ('routing_id', '!=', False)]}" string="Produce" type="object" class="oe_highlight"/>
- <button name="open_produce_product" attrs="{'invisible': ['|', '|', ('availability', '!=', 'waiting'), ('state', 'not in', ('confirmed','progress')), ('routing_id', '!=', False)]}" string="Produce" type="object"/>
+ <button name="open_produce_product" attrs="{'invisible': ['|', '|', '|', ('check_to_done', '=', True), ('availability', 'not in', ['partially_available', 'assigned']), ('state', 'not in', ('confirmed','progress')), ('routing_id', '!=', False)]}" string="Produce" type="object" class="oe_highlight"/>
+ <button name="open_produce_product" attrs="{'invisible': ['|', '|', '|', ('check_to_done', '=', True), ('availability', '!=', 'waiting'), ('state', 'not in', ('confirmed','progress')), ('routing_id', '!=', False)]}" string="Produce" type="object"/>
<button name="post_inventory" string="Post Inventory" type="object" class="oe_highlight" attrs="{'invisible': [('post_visible', '=', False)]}"/>
<button name="action_cancel" type="object" string="Cancel" attrs="{'invisible': ['|', ('state', 'in', ('done','cancel')), ('check_to_done', '=', True)]}"/>
<button name="button_scrap" type="object" string="Scrap" attrs="{'invisible': ['|', ('availability', '=', 'none'), ('state', 'in', ('cancel'))]}"/>
@@ -66,7 +66,7 @@
<span class="o_stat_text">Work Orders</span>
</div>
</button>
- <button name="%(action_mrp_production_moves)d" type="action" string="Inventory Moves" class="oe_stat_button" icon="fa-arrows-v" attrs="{'invisible': [('state', 'not in', ('progress', 'done'))]}"/>
+ <button name="%(action_mrp_production_moves)d" type="action" string="Inventory Moves" class="oe_stat_button" icon="fa-arrows-v" attrs="{'invisible': [('state', 'not in', ('progress', 'cancel', 'done'))]}"/>
<button class="oe_stat_button" name="action_see_move_scrap" type="object" icon="fa-arrows-v" attrs="{'invisible': [('scrap_count', '=', 0)]}">
<div class="o_form_field o_stat_info">
<span class="o_stat_value"><field name="scrap_count"/></span>
@@ -103,14 +103,10 @@
<field name="routing_id" groups="mrp.group_mrp_routings"/>
</group>
<group>
- <label for="date_planned_start_wo" string="Expected Date"/>
- <div name="date_planned" class="o_row">
- <field name="date_planned_start" attrs="{'readonly': [('move_raw_ids', '!=', False)]}"/>
- <label string="to" attrs="{'invisible': [('date_planned_finished', '=', False)]}"/>
- <field name="date_planned_finished" attrs="{'readonly': [('move_raw_ids', '!=', False)]}"/>
- </div>
- <field name="user_id" attrs="{'readonly': [('has_moves', '=', True)]}"/>
- <field name="origin" attrs="{'readonly': [('has_moves', '=', True)]}"/>
+ <field name="date_planned_start"/>
+ <field name="date_planned_finished" invisible="1"/>
+ <field name="user_id"/>
+ <field name="origin"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}" attrs="{'readonly': [('has_moves', '=', True)]}"/>
</group>
</group>
diff --git a/addons/mrp/views/mrp_workcenter_views.xml b/addons/mrp/views/mrp_workcenter_views.xml
index a73a03fbdce..e990d94d21c 100644
--- a/addons/mrp/views/mrp_workcenter_views.xml
+++ b/addons/mrp/views/mrp_workcenter_views.xml
@@ -517,7 +517,7 @@
<field name="workcenter_id"/>
<field name="user_id"/>
<field name="loss_id"/>
- <field name="duration" string="Duration (hours)" sum="Duration"/>
+ <field name="duration" string="Duration (minutes)" sum="Duration"/>
</tree>
</field>
</record>
diff --git a/addons/mrp/views/mrp_workorder_views.xml b/addons/mrp/views/mrp_workorder_views.xml
index 99b6d974baa..437a9608160 100644
--- a/addons/mrp/views/mrp_workorder_views.xml
+++ b/addons/mrp/views/mrp_workorder_views.xml
@@ -100,7 +100,7 @@
<button name="button_finish" type="object" string="Finish Order" attrs="{'invisible': ['|', ('state', '!=', 'progress'), ('is_produced', '=', False)]}" class="btn-info"/>
<button name="button_start" type="object" string="Start Working" attrs="{'invisible': ['|', ('working_state', '=', 'blocked'), ('state', '!=', 'pending')]}"/>
<button name="button_start" type="object" string="Start Working" attrs="{'invisible': ['|', ('working_state', '=', 'blocked'), ('state', '!=', 'ready')]}" class="btn-success"/>
- <button name="record_production" type="object" string="Done" class="btn-success" attrs="{'invisible': ['|', '|', ('working_state', '=', 'blocked'), ('state', '!=', 'progress'), ('is_user_working', '=', False)]}"/>
+ <button name="record_production" type="object" string="Done" class="btn-success" attrs="{'invisible': ['|', '|', '|', ('is_produced', '=', True), ('working_state', '=', 'blocked'), ('state', '!=', 'progress'), ('is_user_working', '=', False)]}"/>
<button name="button_pending" type="object" string="Pause" class="btn-warning" attrs="{'invisible': ['|', '|', ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'pending', 'ready', 'cancel')), ('is_user_working', '=', False)]}"/>
<button name="%(act_mrp_block_workcenter_wo)d" type="action" context="{'default_workcenter_id': workcenter_id}" string="Block" class="btn-danger" attrs="{'invisible': ['|', '|', ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'pending', 'ready', 'cancel')), ('is_user_working', '=', False)]}"/>
<button name="button_unblock" type="object" string="Unblock" class="btn-danger" attrs="{'invisible': [('working_state', '!=', 'blocked')]}"/>
@@ -157,6 +157,7 @@
<field name="quantity" readonly="1"/>
<field name="lot_id" context="{'default_product_id': product_id}"/>
<field name="quantity_done"/>
+ <field name="move_id" invisible="1"/>
<field name="done_wo" invisible="1"/>
</tree>
</field>
diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py
index 254a13813f0..de98b052a81 100644
--- a/addons/mrp/wizard/change_production_qty.py
+++ b/addons/mrp/wizard/change_production_qty.py
@@ -13,7 +13,7 @@ class ChangeProductionQty(models.TransientModel):
# TDE FIXME: add production_id field
mo_id = fields.Many2one('mrp.production', 'Manufacturing Order', required=True)
product_qty = fields.Float(
- 'Product Qty',
+ 'Quantity To Produce',
digits=dp.get_precision('Product Unit of Measure'), required=True)
@api.model
@@ -37,32 +37,41 @@ class ChangeProductionQty(models.TransientModel):
@api.multi
def change_prod_qty(self):
- MrpBom = self.env['mrp.bom']
for wizard in self:
production = wizard.mo_id
produced = sum(production.move_finished_ids.mapped('quantity_done'))
if wizard.product_qty < produced:
- raise UserError(_("You have already produced %d qty , Please give update quantity more then %d ")%(produced, produced))
+ raise UserError(_("You have already processed %d. Please input a quantity higher than %d ")%(produced, produced))
production.write({'product_qty': wizard.product_qty})
- #production.action_compute()
- #TODO: Do we still need to change the quantity of a production order?
- production_move = production.move_finished_ids.filtered(lambda x : x.state not in ('done', 'cancel') and production.product_id.id == x.product_id.id)
- for move in production.move_raw_ids:
- bom_point = production.bom_id
- # TDE FIXME: this is not the place to do that kind of computation, please
- if not bom_point:
- bom_point = MrpBom._bom_find(product=production.product_id, picking_type=production.picking_type_id)
- if not bom_point:
- raise UserError(_("Cannot find bill of material for this production."))
- production.write({'bom_id': bom_point.id})
- if not bom_point:
- raise UserError(_("Cannot find bill of material for this production."))
- factor = (production.product_qty - production.qty_produced) * production.product_uom_id.factor / bom_point.product_uom_id.factor
- boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
- for line, line_data in lines:
- production._update_raw_move(line, line_data['qty'])
+ bom_point = production.bom_id
+ factor = self.env['product.uom']._compute_qty(production.product_uom_id.id, production.product_qty - production.qty_produced, production.bom_id.product_uom_id.id) / production.bom_id.product_qty
+ boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
+ for line, line_data in lines:
+ production._update_raw_move(line, line_data)
self._update_product_to_produce(production, production.product_qty - production.qty_produced)
moves = production.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
moves.do_unreserve()
moves.action_assign()
+ for wo in production.workorder_ids:
+ if production.product_id.tracking == 'serial':
+ quantity = 1.0
+ else:
+ quantity = wo.qty_production - wo.qty_produced
+ quantity = quantity if (quantity > 0) else 0
+ wo.qty_producing = quantity
+ if wo.qty_produced < wo.qty_production and wo.state == 'done':
+ wo.state = 'progress'
+ # assign moves; last operation receive all unassigned moves
+ operation = wo.operation_id
+
+ # TODO: following could be put in a function as it is similar as code in _workorders_create
+ # TODO: only needed when creating new moves
+ moves_raw = production.move_raw_ids.filtered(lambda move: move.operation_id == operation and move.state not in ('done', 'cancel'))
+ if wo == production.workorder_ids[-1]:
+ moves_raw |= production.move_raw_ids.filtered(lambda move: not move.operation_id)
+ moves_finished = production.move_finished_ids.filtered(lambda move: move.operation_id == operation) #TODO: code does nothing, unless maybe by_products?
+ moves_raw.mapped('move_lot_ids').write({'workorder_id': wo.id})
+ (moves_finished + moves_raw).write({'workorder_id': wo.id})
+ if wo.move_raw_ids.filtered(lambda x: x.product_id.tracking != 'none') and not wo.active_move_lot_ids:
+ wo._generate_lot_ids()
return {}
diff --git a/addons/mrp/wizard/change_production_qty_views.xml b/addons/mrp/wizard/change_production_qty_views.xml
index 205ecb5010f..0ba2fc8488e 100644
--- a/addons/mrp/wizard/change_production_qty_views.xml
+++ b/addons/mrp/wizard/change_production_qty_views.xml
@@ -4,7 +4,7 @@
<!-- Change Product Quantity -->
<record id="view_change_production_qty_wizard" model="ir.ui.view">
- <field name="name">Change Product Qty</field>
+ <field name="name">Change Quantity To Produce</field>
<field name="model">change.production.qty</field>
<field name="arch" type="xml">
<form string="Change Product Qty">
@@ -21,7 +21,7 @@
</record>
<record id="action_change_production_qty" model="ir.actions.act_window">
- <field name="name">Change Product Qty</field>
+ <field name="name">Change Quantity To Produce</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">change.production.qty</field>
<field name="view_type">form</field>
diff --git a/addons/mrp/wizard/mrp_product_produce.py b/addons/mrp/wizard/mrp_product_produce.py
index 2571c83b848..428cb627404 100644
--- a/addons/mrp/wizard/mrp_product_produce.py
+++ b/addons/mrp/wizard/mrp_product_produce.py
@@ -74,6 +74,8 @@ class MrpProductProduce(models.TransientModel):
# Nothing to do for lots since values are created using default data (stock.move.lots)
moves = self.production_id.move_raw_ids
quantity = self.product_qty
+ if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0:
+ raise UserError(_('You should at least produce some quantity'))
for move in moves.filtered(lambda x: x.product_id.tracking == 'none' and x.state not in ('done', 'cancel')):
if move.unit_factor:
move.quantity_done_store += quantity * move.unit_factor
@@ -84,6 +86,8 @@ class MrpProductProduce(models.TransientModel):
elif move.unit_factor:
move.quantity_done_store += quantity * move.unit_factor
self.check_finished_move_lots()
+ if self.production_id.state == 'confirmed':
+ self.production_id.state = 'progress'
return {'type': 'ir.actions.act_window_close'}
@api.multi
diff --git a/addons/mrp/wizard/mrp_product_produce_views.xml b/addons/mrp/wizard/mrp_product_produce_views.xml
index b129c8be74c..9a22d279766 100644
--- a/addons/mrp/wizard/mrp_product_produce_views.xml
+++ b/addons/mrp/wizard/mrp_product_produce_views.xml
@@ -10,7 +10,7 @@
<group>
<field name="serial" invisible="1"/>
<field name="production_id" invisible="1"/>
- <field name="product_id"/>
+ <field name="product_id" readonly="1"/>
<label for="product_qty"/>
<div class="o_row">
<field name="product_qty" attrs="{'readonly': [('serial', '=', True)]}"/>
@@ -27,7 +27,7 @@
<field name="quantity" readonly="1"/>
<field name="plus_visible" invisible="1"/>
<field name="quantity_done"/>
- <field name="lot_id"/>
+ <field name="lot_id" context="{'default_product_id': product_id}"/>
<field name="move_id" invisible="1"/>
<button name="do_minus" type="object" icon="fa-minus-square" attrs="{'invisible': [('quantity_done', '&lt;=', 0.99)]}" invisible="context.get('state_done')"/>
<button name="do_plus" type="object" icon="fa-plus-square" attrs="{'invisible': [('plus_visible', '=', False)]}" invisible="context.get('state_done')"/>
diff --git a/addons/mrp_byproduct/models/mrp_production.py b/addons/mrp_byproduct/models/mrp_production.py
index 142775818af..924c13fc2e8 100644
--- a/addons/mrp_byproduct/models/mrp_production.py
+++ b/addons/mrp_byproduct/models/mrp_production.py
@@ -4,38 +4,40 @@
from odoo import api, models
-class Production(models.Model):
+class MrpProduction(models.Model):
_description = 'Production'
_inherit = 'mrp.production'
+ def _create_byproduct_move(self, sub_product):
+ Move = self.env['stock.move']
+ for production in self:
+ source = production.product_id.property_stock_production.id
+ product_uom_factor = production.product_uom_id._compute_quantity(production.product_qty - production.qty_produced, production.bom_id.product_uom_id)
+ qty1 = sub_product.product_qty
+ qty1 *= product_uom_factor / production.bom_id.product_qty
+ data = {
+ 'name': 'PROD:%s' % production.name,
+ 'date': production.date_planned_start,
+ 'product_id': sub_product.product_id.id,
+ 'product_uom_qty': qty1,
+ 'product_uom': sub_product.product_uom_id.id,
+ 'location_id': source,
+ 'location_dest_id': production.location_dest_id.id,
+ 'production_id': production.id,
+ 'origin': production.name,
+ 'unit_factor': qty1 / (production.product_qty - production.qty_produced),
+ 'subproduct_id': sub_product.id
+ }
+ move = Move.create(data)
+ move.action_confirm()
@api.multi
def _generate_moves(self):
""" Generates moves and work orders
@return: Newly generated picking Id.
"""
- # TDE FIXME: was action_confirm ?? -> refactored
- Move = self.env['stock.move']
- res = super(Production, self)._generate_moves()
+ res = super(MrpProduction, self)._generate_moves()
for production in self.filtered(lambda production: production.bom_id):
- source = production.product_id.property_stock_production.id
for sub_product in production.bom_id.sub_products:
- product_uom_factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id)
- qty1 = sub_product.product_qty
- qty1 *= product_uom_factor / production.bom_id.product_qty
- data = {
- 'name': 'PROD:%s' % production.name,
- 'date': production.date_planned_start,
- 'product_id': sub_product.product_id.id,
- 'product_uom_qty': qty1,
- 'product_uom': sub_product.product_uom_id.id,
- 'location_id': source,
- 'location_dest_id': production.location_dest_id.id,
- 'production_id': production.id,
- 'origin': production.name,
- 'unit_factor': qty1 / production.product_qty,
- 'subproduct_id': sub_product.id
- }
- move = Move.create(data)
- move.action_confirm()
+ production._create_byproduct_move(sub_product)
return res
diff --git a/addons/mrp_byproduct/models/stock_move.py b/addons/mrp_byproduct/models/stock_move.py
index e75c2f8351c..119cc8fda94 100644
--- a/addons/mrp_byproduct/models/stock_move.py
+++ b/addons/mrp_byproduct/models/stock_move.py
@@ -4,7 +4,7 @@
from odoo import fields, models
-class Stok_Move(models.Model):
+class StockMove(models.Model):
_inherit = 'stock.move'
subproduct_id = fields.Many2one(
diff --git a/addons/mrp_byproduct/wizard/change_production_qty.py b/addons/mrp_byproduct/wizard/change_production_qty.py
index ac553ced65c..1ac4b74f867 100644
--- a/addons/mrp_byproduct/wizard/change_production_qty.py
+++ b/addons/mrp_byproduct/wizard/change_production_qty.py
@@ -4,19 +4,20 @@
from odoo import api, models
-class change_production_qty(models.TransientModel):
+class ChangeProductionQty(models.TransientModel):
_inherit = 'change.production.qty'
@api.model
def _update_product_to_produce(self, prod, qty):
- # U
+ super(ChangeProductionQty, self)._update_product_to_produce(prod, qty)
Production = self.env['mrp.production']
- for move in prod.move_finished_ids:
- if move.product_id == prod.product_id:
- move.write({'product_uom_qty': qty})
+ UoM = self.env['product.uom']
+ for sub_product_line in prod.bom_id.sub_products:
+ move = prod.move_finished_ids.filtered(lambda x: x.sub_product_id == sub_product_line and x.state not in ('done', 'cancel'))
+ if move:
+ product_uom_factor = UoM._compute_qty_obj(prod.product_uom_id, prod.product_qty - prod.qty_produced, prod.bom_id.product_uom_id)
+ qty1 = sub_product_line.product_qty
+ qty1 *= product_uom_factor / prod.bom_id.product_qty
+ move[0].write({'product_uom_qty': qty1})
else:
- for sub_product_line in prod.bom_id.sub_products:
- if sub_product_line.product_id == move.product_id:
- factor = Production._get_subproduct_factor(move)
- subproduct_qty = qty * factor
- move.write({'product_uom_qty': subproduct_qty})
+ prod._create_byproduct_move(sub_product_line) \ No newline at end of file
diff --git a/addons/project_issue/models/project_issue.py b/addons/project_issue/models/project_issue.py
index 535fe6dd1da..ce310dedb9a 100644
--- a/addons/project_issue/models/project_issue.py
+++ b/addons/project_issue/models/project_issue.py
@@ -121,8 +121,9 @@ class ProjectIssue(models.Model):
@api.onchange('project_id')
def _onchange_project_id(self):
if self.project_id:
- self.partner_id = self.project_id.partner_id.id
- self.email_from = self.project_id.partner_id.email
+ if not self.partner_id and not self.email_from:
+ self.partner_id = self.project_id.partner_id.id
+ self.email_from = self.project_id.partner_id.email
self.stage_id = self.stage_find(self.project_id.id, [('fold', '=', False)])
else:
self.partner_id = False
diff --git a/addons/purchase_mrp/models/purchase_mrp.py b/addons/purchase_mrp/models/purchase_mrp.py
index 2bdf19c2006..4c22ee1a58c 100644
--- a/addons/purchase_mrp/models/purchase_mrp.py
+++ b/addons/purchase_mrp/models/purchase_mrp.py
@@ -27,7 +27,7 @@ class PurchaseOrderLine(models.Model):
bom_delivered = {}
if bom:
bom_delivered[bom.id] = False
- product_uom_qty_bom = self.product_uom._compute_quantity(self.product_qty, bom.product_uom_id)
+ product_uom_qty_bom = self.product_uom._compute_quantity(self.product_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
for bom_line, data in lines:
qty = 0.0
diff --git a/addons/purchase_requisition/views/purchase_requisition_views.xml b/addons/purchase_requisition/views/purchase_requisition_views.xml
index 1b7d34aa6e2..d5177adf924 100644
--- a/addons/purchase_requisition/views/purchase_requisition_views.xml
+++ b/addons/purchase_requisition/views/purchase_requisition_views.xml
@@ -131,7 +131,7 @@
<group>
<field name="user_id" attrs="{'readonly': [('state','not in',('draft','in_progress','open'))]}"/>
<field name="type_id" attrs="{'readonly': [('state','not in',('draft','in_progress','open'))]}" widget="selection"/>
- <field name="vendor_id"/>
+ <field name="vendor_id" context="{'search_default_supplier':1, 'default_supplier':1, 'default_customer':0}" domain="[('supplier','=',True)]"/>
<field name="account_analytic_id" colspan="2" groups="purchase.group_analytic_accounting" attrs="{'readonly': [('state','not in',('draft'))]}"/>
</group>
<group>
diff --git a/addons/rating_project/models/project.py b/addons/rating_project/models/project.py
index 3a981885686..a82ca8cc1b9 100644
--- a/addons/rating_project/models/project.py
+++ b/addons/rating_project/models/project.py
@@ -36,7 +36,8 @@ class Task(models.Model):
for task in self:
rating_template = task.stage_id.rating_template_id
if rating_template:
- task.rating_send_request(rating_template, reuse_rating=False)
+ force_send = self.env.context.get('force_send', True)
+ task.rating_send_request(rating_template, reuse_rating=False, force_send=force_send)
def _rating_get_partner_id(self):
res = super(Task, self)._rating_get_partner_id()
@@ -56,7 +57,7 @@ class Project(models.Model):
@api.model
def _send_rating_all(self):
projects = self.search([('rating_status', '=', 'periodic'), ('rating_request_deadline', '<=', fields.Datetime.now())])
- projects._send_rating_mail()
+ projects.with_context(force_send=False)._send_rating_mail()
projects._compute_rating_request_deadline()
def _send_rating_mail(self):
diff --git a/addons/sale_mrp/sale_mrp.py b/addons/sale_mrp/sale_mrp.py
index 2247c8f7604..fce9f550395 100644
--- a/addons/sale_mrp/sale_mrp.py
+++ b/addons/sale_mrp/sale_mrp.py
@@ -38,7 +38,7 @@ class SaleOrderLine(models.Model):
bom = self.env['mrp.bom']._bom_find(product=self.product_id)
if bom and bom.type == 'phantom':
bom_delivered[bom.id] = False
- product_uom_qty_bom = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id)
+ product_uom_qty_bom = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id) / bom.product_qty
boms, lines = bom.explode(self.product_id, product_uom_qty_bom)
for bom_line, data in lines:
qty = 0.0
diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py
index 1cd94fcccab..9aaa21ed16e 100644
--- a/addons/sale_mrp/tests/test_sale_mrp_flow.py
+++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py
@@ -282,7 +282,7 @@ class TestSaleMrpFlow(common.TransactionCase):
mnf_product_d.post_inventory()
# Check state of manufacturing order.
- self.assertEqual(mnf_product_d.state, 'confirmed', 'Manufacturing order should still be in confirmed state.')
+ self.assertEqual(mnf_product_d.state, 'progress', 'Manufacturing order should still be in progress state.')
# Check available quantity of product D.
self.assertEqual(product_d.qty_available, 20, 'Wrong quantity available of product D.')
@@ -334,7 +334,7 @@ class TestSaleMrpFlow(common.TransactionCase):
mnf_product_a.post_inventory()
# Check state of manufacturing order product A.
- self.assertEqual(mnf_product_a.state, 'confirmed', 'Manufacturing order should still be in confirmed state.')
+ self.assertEqual(mnf_product_a.state, 'progress', 'Manufacturing order should still be in the progress state.')
# Check product A avaialble quantity should be 120.
self.assertEqual(product_a.qty_available, 120, 'Wrong quantity available of product A.')
diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py
index 2b3192dc0cf..dc4b52bdf14 100644
--- a/addons/stock/models/product.py
+++ b/addons/stock/models/product.py
@@ -234,8 +234,8 @@ class Product(models.Model):
dest_loc_domain = dest_loc_domain + [('location_dest_id', operator, [location.id for location in other_locations])]
return (
domain + loc_domain,
- domain + ['&'] + dest_loc_domain + ['!'] + loc_domain,
- domain + ['&'] + loc_domain + ['!'] + dest_loc_domain
+ domain + dest_loc_domain + ['!'] + loc_domain if loc_domain else domain + dest_loc_domain,
+ domain + loc_domain + ['!'] + dest_loc_domain if dest_loc_domain else domain + loc_domain
)
def _search_virtual_available(self, operator, value):
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index 34d98ba27ef..7cb80c8b360 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -264,11 +264,6 @@ class StockMove(models.Model):
raise UserError(_('Quantities, Units of Measure, Products and Locations cannot be modified on stock moves that have already been processed (except by the Administrator).'))
propagated_changes_dict = {}
- #propagation of quantity change
- if vals.get('product_uom_qty'):
- propagated_changes_dict['product_uom_qty'] = vals['product_uom_qty']
- if vals.get('product_uom_id'):
- propagated_changes_dict['product_uom_id'] = vals['product_uom_id']
#propagation of expected date:
propagated_date_field = False
if vals.get('date_expected'):
@@ -634,6 +629,7 @@ class StockMove(models.Model):
if move.state != 'assigned' and not self.env.context.get('reserve_only_ops'):
qty_already_assigned = move.reserved_availability
qty = move.product_qty - qty_already_assigned
+
quants = Quant.quants_get_preferred_domain(qty, move, domain=main_domain[move.id], preferred_domain_list=[])
Quant.quants_reserve(quants, move)
diff --git a/addons/stock/models/stock_scrap.py b/addons/stock/models/stock_scrap.py
index a0465d5e3f8..355f0139d04 100644
--- a/addons/stock/models/stock_scrap.py
+++ b/addons/stock/models/stock_scrap.py
@@ -93,7 +93,7 @@ class StockScrap(models.Model):
self.ensure_one()
return {
'name': self.name,
- 'origin': self.origin,
+ 'origin': self.origin or self.picking_id.name,
'product_id': self.product_id.id,
'product_uom': self.product_uom_id.id,
'product_uom_qty': self.scrap_qty,
diff --git a/addons/stock/views/stock_pack_operation_views.xml b/addons/stock/views/stock_pack_operation_views.xml
index 5f7e46850e6..e982fac90bf 100644
--- a/addons/stock/views/stock_pack_operation_views.xml
+++ b/addons/stock/views/stock_pack_operation_views.xml
@@ -21,8 +21,8 @@
</div>
</group>
<group string="Locations" groups="stock.group_stock_multi_locations">
- <field name="location_id"/>
- <field name="location_dest_id"/>
+ <field name="location_id" domain="[('id', 'child_of', picking_source_location_id)]"/>
+ <field name="location_dest_id" domain="[('id', 'child_of', picking_destination_location_id)]"/>
</group>
<group string="Packages" groups="stock.group_tracking_lot">
<field name="package_id" attrs="{'required': [('product_id', '=', False)]}" domain="[('location_id', '=', location_id)]" context="{'location_id': location_id}"/>
diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js
index 4ce7ed6dbf3..dd4c4fb0fb6 100644
--- a/addons/web/static/src/js/views/form_relational_widgets.js
+++ b/addons/web/static/src/js/views/form_relational_widgets.js
@@ -955,7 +955,7 @@ var X2ManyListView = ListView.extend({
field.no_rerender = true;
current_values[field.name] = field.get('value');
});
- var cached_records = _.filter(this.dataset.cache, function(item){return !_.isEmpty(item.values);});
+ var cached_records = _.filter(this.dataset.cache, function(item){return !_.isEmpty(item.values) && !item.to_delete;});
var valid = _.every(cached_records, function(record){
_.each(fields, function(field){
var value = record.values[field.name];
diff --git a/addons/web/static/src/less/webclient_layout.less b/addons/web/static/src/less/webclient_layout.less
index 3355f4f791f..034f00ad3d9 100644
--- a/addons/web/static/src/less/webclient_layout.less
+++ b/addons/web/static/src/less/webclient_layout.less
@@ -34,6 +34,7 @@
.o-flex(1, 1, auto);
.o-flex-display();
min-height: 0; // Allow flex to shrink this element as much as it wants
+ height: 100%;
.o_sub_menu {
.o-flex(0, 0, @odoo-submenu-width);
diff --git a/addons/web_editor/static/src/js/snippets.options.js b/addons/web_editor/static/src/js/snippets.options.js
index 6d4800cd0db..4d533cadd00 100644
--- a/addons/web_editor/static/src/js/snippets.options.js
+++ b/addons/web_editor/static/src/js/snippets.options.js
@@ -609,7 +609,7 @@ odoo.define('web_editor.snippets.options', function (require) {
var _editor = new widget.MediaDialog(null, {}, null, $image[0]).open();
_editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
- _editor.on('saved', this, function () {
+ _editor.on('save', this, function () {
var value = $image.attr("src");
this.background(type, value, $li);
this.$target.addClass("oe_custom_bg");
diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js
index 00a693d40f2..7a3ab09dd76 100644
--- a/addons/web_editor/static/src/js/widgets.js
+++ b/addons/web_editor/static/src/js/widgets.js
@@ -34,11 +34,11 @@ Dialog = Dialog.extend({
self.$('input:first').focus();
});
this.on("closed", this, function () {
- this.trigger(this.destroyAction);
+ this.trigger(this.destroyAction, this.final_data || null);
});
},
save: function () {
- this.destroyAction = "saved";
+ this.destroyAction = "save";
this.close();
},
});
@@ -164,8 +164,8 @@ var MediaDialog = Dialog.extend({
},
save: function () {
if (this.options.select_images) {
- this.trigger("saved", this.active.save());
- this.close();
+ this.final_data = this.active.save();
+ this._super.apply(this, arguments);
return;
}
if(this.rte) {
@@ -198,8 +198,8 @@ var MediaDialog = Dialog.extend({
}
var media = this.active.media;
- $(document.body).trigger("media-saved", [media, self.old_media]);
- self.trigger("saved", [media, self.old_media]);
+ this.final_data = [media, self.old_media];
+ $(document.body).trigger("media-saved", this.final_data);
// Update editor bar after image edition (in case the image change to icon or other)
_.defer(function () {
@@ -312,10 +312,8 @@ var ImageDialog = Widget.extend({
},
save: function () {
if (this.options.select_images) {
- this.parent.trigger("save", this.images);
return this.images;
}
- this.parent.trigger("save", this.media);
var img = this.images[0];
if (!img) {
@@ -668,7 +666,6 @@ var fontIconsDialog = Widget.extend({
*/
save: function () {
var self = this;
- this.parent.trigger("save", this.media);
var style = this.media.attributes.style ? this.media.attributes.style.value : '';
var classes = (this.media.className||"").split(/\s+/);
var custom_classes = /^fa(-[1-5]x|spin|rotate-(9|18|27)0|flip-(horizont|vertic)al|fw|border)?$/;
@@ -684,6 +681,8 @@ var fontIconsDialog = Widget.extend({
style = style.replace(/\s*width:[^;]+/, '');
}
$(this.media).attr("class", _.compact(final_classes).join(' ')).attr("style", style);
+
+ return this.media;
},
/**
* return the data font object (with base, parser and icons) or null
@@ -907,7 +906,6 @@ var VideoDialog = Widget.extend({
return false;
},
save: function () {
- this.parent.trigger("save", this.media);
var video_id = this.$("#video_id").val();
if (!video_id) {
this.$("button.btn-primary").click();
@@ -921,6 +919,8 @@ var VideoDialog = Widget.extend({
'</div>');
$(this.media).replaceWith($iframe);
this.media = $iframe[0];
+
+ return this.media;
},
clear: function () {
if (this.media.dataset.src) {
@@ -1095,7 +1095,7 @@ var LinkDialog = Dialog.extend({
if (classes.replace(/(^|[ ])(btn-default|btn-success|btn-primary|btn-info|btn-warning|btn-danger)([ ]|$)/gi, ' ')) {
self.data.style = {'background-color': '', 'color': ''};
}
- self.trigger("save", self.data);
+ self.final_data = self.data;
}).then(_super);
},
bind_data: function () {
diff --git a/addons/website/static/src/js/website.contentMenu.js b/addons/website/static/src/js/website.contentMenu.js
index 82bbefcf8c2..aa695857746 100644
--- a/addons/website/static/src/js/website.contentMenu.js
+++ b/addons/website/static/src/js/website.contentMenu.js
@@ -186,8 +186,8 @@ var SelectEditMenuDialog = widget.Dialog.extend({
}, options || {}));
},
save: function () {
- this.trigger("save", parseInt(this.$el.find("select").val() || null));
- this._super();
+ this.final_data = parseInt(this.$el.find("select").val() || null);
+ this._super.apply(this, arguments);
}
});
diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js
index 046da64ccf7..c765e335f7c 100644
--- a/addons/website/static/src/js/website.js
+++ b/addons/website/static/src/js/website.js
@@ -175,9 +175,10 @@ odoo.define('website.website', function (require) {
});
/* ----- PUBLISHING STUFF ---- */
- $(document).on('click', '.js_publish_management .js_publish_btn', function () {
+ $(document).on('click', '.js_publish_management .js_publish_btn', function (e) {
+ e.preventDefault();
+
var $data = $(this).parents(".js_publish_management:first");
- var self=this;
ajax.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
.then(function (result) {
$data.toggleClass("css_unpublished css_published");
diff --git a/addons/website/static/src/js/website.seo.js b/addons/website/static/src/js/website.seo.js
index 4b5acc8090a..09e6c00a701 100644
--- a/addons/website/static/src/js/website.seo.js
+++ b/addons/website/static/src/js/website.seo.js
@@ -343,8 +343,8 @@ var Configurator = Dialog.extend({
template: 'website.seo_configuration',
events: {
'keyup input[name=seo_page_keywords]': 'confirmKeyword',
- 'keyup input[name=seo_page_title]': 'titleChanged',
- 'keyup textarea[name=seo_page_description]': 'descriptionChanged',
+ 'blur input[name=seo_page_title]': 'titleChanged',
+ 'blur textarea[name=seo_page_description]': 'descriptionChanged',
'click button[data-action=add]': 'addKeyword',
},
canEditTitle: false,
diff --git a/addons/website/static/src/js/website.snippets.gallery.js b/addons/website/static/src/js/website.snippets.gallery.js
index 481ba06e6f3..cde906ca764 100644
--- a/addons/website/static/src/js/website.snippets.gallery.js
+++ b/addons/website/static/src/js/website.snippets.gallery.js
@@ -67,7 +67,7 @@ options.registry.gallery = options.Class.extend({
},
bind_change: function () {
var self = this;
- return this.$target.find("img").off('saved').on('saved', function (event, img) {
+ return this.$target.find("img").off('save').on('save', function (event, img) {
var $parent = $(img).parent();
$parent.addClass("saved_active");
var index = self.$target.find(".item.saved_active").index();
@@ -228,7 +228,7 @@ options.registry.gallery = options.Class.extend({
var $container = this.$target.find(".container:first");
var editor = new widget.MediaDialog(null, {select_images: true}, this.$target.closest('.o_editable'), null).open();
var index = Math.max(0, _.max(_.map(this.$target.find("img").get(), function (img) { return img.dataset.index | 0; })) + 1);
- editor.on('saved', this, function (attachments) {
+ editor.on('save', this, function (attachments) {
for (var i = 0 ; i < attachments.length; i++) {
$('<img class="img img-responsive mb8 mt8"/>')
.attr("src", attachments[i].src)
diff --git a/addons/website_blog/static/src/js/website_blog.editor.js b/addons/website_blog/static/src/js/website_blog.editor.js
index c49ed85548b..85a2d2d7901 100644
--- a/addons/website_blog/static/src/js/website_blog.editor.js
+++ b/addons/website_blog/static/src/js/website_blog.editor.js
@@ -110,7 +110,7 @@ odoo.define('website_blog.editor', function (require) {
var $image = $("<img/>", {src: this.$image.css("background-image")});
var editor = new widget.MediaDialog(null, {only_images: true}, $image, $image[0]).open();
- editor.on("saved", this, function (event, img) {
+ editor.on("save", this, function (event, img) {
var src = $image.attr("src");
this.$image.css("background-image", src ? ("url(" + src + ")") : "");
if (!this.$target.hasClass("cover")) {
diff --git a/addons/website_blog/views/website_blog_templates.xml b/addons/website_blog/views/website_blog_templates.xml
index 93c97a9c8ac..f6a4ac3a185 100644
--- a/addons/website_blog/views/website_blog_templates.xml
+++ b/addons/website_blog/views/website_blog_templates.xml
@@ -124,12 +124,12 @@
<div class="col-md-8 col-md-offset-2" t-ignore="True" id="main_column">
<div t-if="not blog_posts" class="container mb64">
- <p class="css_editable_hidden">
- <h1>No blog post yet.</h1>
- </p>
+ <p class="css_editable_hidden">
+ <h1>No blog post yet.</h1>
+ </p>
<p groups="website.group_website_designer">
- Click on "Content" on the top menu to write your first blog post.
- </p>
+ Click on "New Page" in the top-right corner to write your first blog post.
+ </p>
</div>
<div t-foreach="blog_posts" t-as="blog_post" class="mb32" name="blog_post">
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index 9052e9a5dc3..a8a25ee3bdb 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -295,6 +295,11 @@ class Website(models.Model):
def sale_product_domain(self):
return [("sale_ok", "=", True)]
+ @api.model
+ def sale_get_payment_term(self, partner):
+ DEFAULT_PAYMENT_TERM = 'account.account_payment_term_immediate'
+ return self.env.ref(DEFAULT_PAYMENT_TERM, False).id or partner.property_payment_term_id.id
+
@api.multi
def sale_get_order(self, force_create=False, code=None, update_pricelist=False, force_pricelist=False):
""" Return the current sale order after mofications specified by params.
@@ -339,7 +344,7 @@ class Website(models.Model):
sale_order = self.env['sale.order'].sudo().create({
'partner_id': partner.id,
'pricelist_id': pricelist_id,
- 'payment_term_id': partner.property_payment_term_id.id,
+ 'payment_term_id': self.sale_get_payment_term(partner),
'team_id': self.salesteam_id.id,
'partner_invoice_id': addr['invoice'],
'partner_shipping_id': addr['delivery'],
@@ -380,6 +385,7 @@ class Website(models.Model):
sale_order.write({'partner_id': partner.id})
sale_order.onchange_partner_id()
sale_order.onchange_partner_shipping_id() # fiscal position
+ sale_order['payment_term_id'] = self.sale_get_payment_term(partner)
# check the pricelist : update it if the pricelist is not the 'forced' one
values = {}
diff --git a/addons/website_sale/static/src/css/website_sale.css b/addons/website_sale/static/src/css/website_sale.css
index d5c3d999e47..f1def903329 100644
--- a/addons/website_sale/static/src/css/website_sale.css
+++ b/addons/website_sale/static/src/css/website_sale.css
@@ -366,6 +366,7 @@ div#payment_method .list-group-item {
min-height: 100px;
position: relative;
padding-bottom: 5px;
+ padding-left: 180px;
}
.oe_product.oe_list .oe_product_image {
top: 0;
@@ -377,9 +378,10 @@ div#payment_method .list-group-item {
.oe_product.oe_list section {
position: relative;
border: 0;
- top: 0;
+ top: auto;
bottom: auto;
- left: 180px;
+ left: auto;
+ right: auto;
background: transparent;
}
}
diff --git a/addons/website_sale/static/src/css/website_sale.sass b/addons/website_sale/static/src/css/website_sale.sass
index e6dc2a037ad..7cc6cfc0341 100644
--- a/addons/website_sale/static/src/css/website_sale.sass
+++ b/addons/website_sale/static/src/css/website_sale.sass
@@ -314,6 +314,7 @@ div#payment_method
min-height: 100px
position: relative
padding-bottom: 5px
+ padding-left: 180px
.oe_product_image
top: 0
bottom: 0
@@ -323,9 +324,10 @@ div#payment_method
section
position: relative
border: 0
- top: 0
+ top: auto
bottom: auto
- left: 180px
+ left: auto
+ right: auto
background: transparent
.oe_website_sale .row .row .col-md-12
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index ce62fbf6af4..be19877fb82 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -1139,7 +1139,8 @@
<t t-if="mode == ('new', 'billing')">
<h3 class="page-header mt16">Your Address
<small> or </small>
- <a href='/web/signup?redirect=/shop/checkout' class='btn btn-primary' style="margin-top: -11px">Sign Up</a>
+ <t t-set='connect' t-value="request.env['ir.config_parameter'].sudo().get_param('auth_signup.allow_uninvited') == 'True' and ('signup', 'Sign Up') or ('login', 'Log In')"/>
+ <a t-attf-href='/web/{{connect[0]}}?redirect=/shop/checkout' class='btn btn-primary' style="margin-top: -11px"><t t-esc='connect[1]'/></a>
</h3>
</t>
<t t-if="mode == ('edit', 'billing')">
diff --git a/addons/website_slides/static/src/img/channel-default.jpg b/addons/website_slides/static/src/img/channel-default.jpg
new file mode 100644
index 00000000000..dce2a23b9b2
--- /dev/null
+++ b/addons/website_slides/static/src/img/channel-default.jpg
Binary files differ
diff --git a/addons/website_slides/view/website_slides.xml b/addons/website_slides/view/website_slides.xml
index d5d0826889c..0441b030ed9 100644
--- a/addons/website_slides/view/website_slides.xml
+++ b/addons/website_slides/view/website_slides.xml
@@ -44,7 +44,7 @@
<div>
<a t-attf-href="/slides/#{slug(channel)}">
<img t-if="channel.promoted_slide_id" t-attf-src="/web/image/slide.slide/#{channel.promoted_slide_id.id}/image_medium" class="img-responsive oe_slides_channel_thumbnail"/>
- <img t-if="not channel.promoted_slide_id" src="/website_slides/static/description/channel-default.jpg" class="img-responsive oe_slides_opacity"/>
+ <img t-if="not channel.promoted_slide_id" src="/website_slides/static/src/img/channel-default.jpg" class="img-responsive oe_slides_opacity"/>
</a>
</div>
<div>