diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-10-03 17:12:38 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-10-03 17:12:38 +0200 |
| commit | c43f35ee9dc7c0bb7cb6bcc06cbe9a26b80abcc1 (patch) | |
| tree | 9bda2adfda33b364ce972907c90747058d9e88f5 | |
| parent | e980af9df00ec25cbfbb07a37bc4dfe2088ed566 (diff) | |
| parent | 45922f397ff7cc4640d010ff8282aae8b2fbafb1 (diff) | |
[MERGE] forward port branch 11.0 up to 45922f397ff
| -rw-r--r-- | addons/account/report/account_report_payment_receipt_templates.xml | 2 | ||||
| -rw-r--r-- | addons/l10n_be_invoice_bba/models/account_invoice.py | 2 | ||||
| -rw-r--r-- | addons/portal/controllers/mail.py | 6 | ||||
| -rw-r--r-- | addons/sale_crm/views/crm_lead_views.xml | 2 | ||||
| -rw-r--r-- | addons/sale_crm/views/sale_order_views.xml | 1 | ||||
| -rw-r--r-- | addons/sale_mrp/models/sale_mrp.py | 5 | ||||
| -rw-r--r-- | addons/sale_mrp/tests/test_sale_mrp_flow.py | 108 |
7 files changed, 120 insertions, 6 deletions
diff --git a/addons/account/report/account_report_payment_receipt_templates.xml b/addons/account/report/account_report_payment_receipt_templates.xml index 1b37bf35656..05c7421140d 100644 --- a/addons/account/report/account_report_payment_receipt_templates.xml +++ b/addons/account/report/account_report_payment_receipt_templates.xml @@ -46,7 +46,7 @@ <td><span t-field="inv.date_invoice"/></td> <td><span t-field="inv.number"/></td> <td class="text-right"><span t-field="inv.amount_total"/></td> - <td class="text-right"><span t-esc="inv.amount_total - inv.residual" t-options="{'widget': 'monetary', 'display_currency': o.currency_id}"/></td> + <td class="text-right"><span t-esc="inv.amount_total - inv.residual" t-options="{'widget': 'monetary', 'display_currency': inv.currency_id}"/></td> <td class="text-right"><span t-field="inv.residual"/></td> </tr> </tbody> diff --git a/addons/l10n_be_invoice_bba/models/account_invoice.py b/addons/l10n_be_invoice_bba/models/account_invoice.py index d729efec3a3..49973c1c30e 100644 --- a/addons/l10n_be_invoice_bba/models/account_invoice.py +++ b/addons/l10n_be_invoice_bba/models/account_invoice.py @@ -182,4 +182,6 @@ class AccountInvoice(models.Model): default['reference_type'] = reference_type if reference_type == 'bba': default['reference'] = self.generate_bbacomm(self.type, reference_type, self.partner_id.id, '')['value']['reference'] + elif self.type in ['in_invoice']: + self.reference_type = 'none' return super(AccountInvoice, self).copy(default) diff --git a/addons/portal/controllers/mail.py b/addons/portal/controllers/mail.py index 1abf05b4e63..d40e00ba0f3 100644 --- a/addons/portal/controllers/mail.py +++ b/addons/portal/controllers/mail.py @@ -90,8 +90,10 @@ class PortalChatter(http.Controller): # Only search into website_message_ids, so apply the same domain to perform only one search # extract domain from the 'website_message_ids' field field_domain = request.env[res_model]._fields['website_message_ids'].domain - domain += field_domain(request.env[res_model]) if callable(field_domain) else field_domain - domain += [('res_id', '=', res_id)] + if callable(field_domain): + field_domain = field_domain(request.env[res_model]) + domain = expression.AND([domain, field_domain, [('res_id', '=', res_id)]]) + # Check access Message = request.env['mail.message'] if kw.get('token'): diff --git a/addons/sale_crm/views/crm_lead_views.xml b/addons/sale_crm/views/crm_lead_views.xml index f602e0d6503..6cc3eaf52ed 100644 --- a/addons/sale_crm/views/crm_lead_views.xml +++ b/addons/sale_crm/views/crm_lead_views.xml @@ -18,7 +18,7 @@ <button name="toggle_active" position="before"> <button class="oe_stat_button" type="action" name="%(sale_action_quotations)d" icon="fa-pencil-square-o" - context="{'default_partner_id': partner_id, 'search_default_draft': 1}"> + context="{'default_partner_id': partner_id, 'search_default_draft': 1, 'search_default_sent': 1}"> <div class="o_stat_info"> <field name="sale_number" class="o_stat_value"/> <span class="o_stat_text"> Quotation(s) </span> diff --git a/addons/sale_crm/views/sale_order_views.xml b/addons/sale_crm/views/sale_order_views.xml index 571614e1cae..5cb87b75312 100644 --- a/addons/sale_crm/views/sale_order_views.xml +++ b/addons/sale_crm/views/sale_order_views.xml @@ -12,6 +12,7 @@ <record id="sale_action_quotations" model="ir.actions.act_window"> <field name="name">Quotations</field> <field name="res_model">sale.order</field> + <field name="search_view_id" ref="sale.sale_order_view_search_inherit_quotation"/> <field name="domain">[('opportunity_id', '=', active_id)]</field> <field name="context">{'search_default_opportunity_id': [active_id], 'default_opportunity_id': active_id}</field> </record> diff --git a/addons/sale_mrp/models/sale_mrp.py b/addons/sale_mrp/models/sale_mrp.py index 9b20cd6b471..38a1e36b9c3 100644 --- a/addons/sale_mrp/models/sale_mrp.py +++ b/addons/sale_mrp/models/sale_mrp.py @@ -18,7 +18,8 @@ class SaleOrderLine(models.Model): # have changed, we don't compute the quantities but verify the move state. bom = self.env['mrp.bom']._bom_find(product=line.product_id) if bom and bom.type == 'phantom': - bom_delivered = all([move.state == 'done' for move in line.move_ids]) + moves = line.move_ids.filtered(lambda m: m.picking_id and m.picking_id.state != 'cancel') + bom_delivered = all([move.state == 'done' for move in moves]) if bom_delivered: line.qty_delivered = line.product_uom_qty else: @@ -26,7 +27,7 @@ class SaleOrderLine(models.Model): @api.multi def _get_bom_component_qty(self, bom): - bom_quantity = self.product_uom._compute_quantity(self.product_uom_qty, bom.product_uom_id) + bom_quantity = self.product_uom._compute_quantity(1, bom.product_uom_id) boms, lines = bom.explode(self.product_id, bom_quantity) components = {} for line, line_data in lines: diff --git a/addons/sale_mrp/tests/test_sale_mrp_flow.py b/addons/sale_mrp/tests/test_sale_mrp_flow.py index 41e4dfb97ef..db05d288dfe 100644 --- a/addons/sale_mrp/tests/test_sale_mrp_flow.py +++ b/addons/sale_mrp/tests/test_sale_mrp_flow.py @@ -18,6 +18,7 @@ class TestSaleMrpFlow(common.TransactionCase): self.Inventory = self.env['stock.inventory'] self.InventoryLine = self.env['stock.inventory.line'] self.ProductProduce = self.env['mrp.product.produce'] + self.ProductCategory = self.env['product.category'] self.categ_unit = self.env.ref('uom.product_uom_categ_unit') self.categ_kgm = self.env.ref('uom.product_uom_categ_kgm') @@ -373,3 +374,110 @@ class TestSaleMrpFlow(common.TransactionCase): del_qty = sum(sol.qty_delivered for sol in so.order_line) self.assertEqual(del_qty, 5.0, 'Sale MRP: delivered quantity should be 5.0 after complete delivery of a kit') self.assertEqual(so.invoice_status, 'to invoice', 'Sale MRP: so invoice_status should be "to invoice" after complete delivery of a kit') + + def test_02_sale_mrp_anglo_saxon(self): + """Test the price unit of a kit""" + # This test will check that the correct journal entries are created when a stockable product in real time valuation + # and in fifo cost method is sold in a company using anglo-saxon. + # For this test, let's consider a product category called Test category in real-time valuation and real price costing method + # Let's also consider a finished product with a bom with two components: component1(cost = 20) and component2(cost = 10) + # These products are in the Test category + # The bom consists of 2 component1 and 1 component2 + # The invoice policy of the finished product is based on delivered quantities + self.uom_unit = self.UoM.create({ + 'name': 'Test-Unit', + 'category_id': self.categ_unit.id, + 'factor': 1, + 'uom_type': 'bigger', + 'rounding': 1.0}) + self.company = self.env.ref('base.main_company') + self.company.anglo_saxon_accounting = True + self.partner = self.env.ref('base.res_partner_1') + self.category = self.env.ref('product.product_category_1').copy({'name': 'Test category','property_valuation': 'real_time', 'property_cost_method': 'fifo'}) + account_type = self.env['account.account.type'].create({'name': 'RCV type', 'type': 'receivable'}) + self.account_receiv = self.env['account.account'].create({'name': 'Receivable', 'code': 'RCV00' , 'user_type_id': account_type.id, 'reconcile': True}) + account_expense = self.env['account.account'].create({'name': 'Expense', 'code': 'EXP00' , 'user_type_id': account_type.id, 'reconcile': True}) + account_output = self.env['account.account'].create({'name': 'Output', 'code': 'OUT00' , 'user_type_id': account_type.id, 'reconcile': True}) + self.partner.property_account_receivable_id = self.account_receiv + self.category.property_account_income_categ_id = self.account_receiv + self.category.property_account_expense_categ_id = account_expense + self.category.property_stock_account_input_categ_id = self.account_receiv + self.category.property_stock_account_output_categ_id = account_output + self.category.property_stock_valuation_account_id = self.account_receiv + self.category.property_stock_journal = self.env['account.journal'].create({'name': 'Stock journal', 'type': 'sale', 'code': 'STK00'}) + + Product = self.env['product.product'] + self.finished_product = Product.create({ + 'name': 'Finished product', + 'type': 'product', + 'uom_id': self.uom_unit.id, + 'invoice_policy': 'delivery', + 'categ_id': self.category.id}) + self.component1 = Product.create({ + 'name': 'Component 1', + 'type': 'product', + 'uom_id': self.uom_unit.id, + 'categ_id': self.category.id, + 'standard_price': 20}) + self.component2 = Product.create({ + 'name': 'Component 2', + 'type': 'product', + 'uom_id': self.uom_unit.id, + 'categ_id': self.category.id, + 'standard_price': 10}) + self.env['stock.quant'].create({ + 'product_id': self.component1.id, + 'location_id': self.env.ref('stock.stock_location_stock').id, + 'quantity': 6.0, + }) + self.env['stock.quant'].create({ + 'product_id': self.component2.id, + 'location_id': self.env.ref('stock.stock_location_stock').id, + 'quantity': 3.0, + }) + self.bom = self.env['mrp.bom'].create({ + 'product_tmpl_id': self.finished_product.product_tmpl_id.id, + 'product_qty': 1.0, + 'type': 'phantom'}) + BomLine = self.env['mrp.bom.line'] + BomLine.create({ + 'product_id': self.component1.id, + 'product_qty': 2.0, + 'bom_id': self.bom.id}) + BomLine.create({ + 'product_id': self.component2.id, + 'product_qty': 1.0, + 'bom_id': self.bom.id}) + + # Create a SO for a specific partner for three units of the finished product + so_vals = { + 'partner_id': self.partner.id, + 'partner_invoice_id': self.partner.id, + 'partner_shipping_id': self.partner.id, + 'order_line': [(0, 0, {'name': self.finished_product.name, 'product_id': self.finished_product.id, 'product_uom_qty': 3, 'product_uom': self.finished_product.uom_id.id, 'price_unit': self.finished_product.list_price})], + 'pricelist_id': self.env.ref('product.list0').id, + 'company_id': self.company.id, + } + self.so = self.env['sale.order'].create(so_vals) + # Validate the SO + self.so.action_confirm() + # Deliver the three finished products + pick = self.so.picking_ids + # To check the products on the picking + self.assertEqual(pick.move_lines.mapped('product_id'), self.component1 | self.component2) + pick.force_assign() + wiz_act = pick.button_validate() + wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']) + wiz.process() + # Create the invoice + self.so.action_invoice_create() + self.invoice = self.so.invoice_ids + # Changed the invoiced quantity of the finished product to 2 + self.invoice.invoice_line_ids.write({'quantity': 2.0}) + self.invoice.action_invoice_open() + aml = self.invoice.move_id.line_ids + aml_expense = aml.filtered(lambda l: l.account_id.id == account_expense.id) + aml_output = aml.filtered(lambda l: l.account_id.id == account_output.id) + # Check that the cost of Good Sold entries are equal to 2* (2 * 20 + 1 * 10) = 100 + self.assertEqual(aml_expense.debit, 100, "Cost of Good Sold entry missing or mismatching") + self.assertEqual(aml_output.credit, 100, "Cost of Good Sold entry missing or mismatching") |
