summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2017-10-24 14:01:58 +0200
committerChristophe Simonis <chs@odoo.com>2017-10-24 14:01:58 +0200
commit2130478cda874cbe2e425e4b4bb0e61df977b656 (patch)
treeefb2ddf33c14312553ba4d807bb4dc10e48aa780
parent9bf4b70287bd9fbd73b047637253a012866b4ef8 (diff)
parent71f6e9c6ab575d1b016ce59ff8c83fa54a21b3ee (diff)
[MERGE] forward port branch saas-15 up to 71f6e9c6ab5
-rw-r--r--addons/account/models/account_invoice.py3
-rw-r--r--addons/mrp/models/stock_move.py2
-rw-r--r--addons/mrp/tests/test_workorder_operation.py114
-rw-r--r--addons/mrp/wizard/change_production_qty.py11
-rw-r--r--addons/point_of_sale/static/src/js/models.js6
-rw-r--r--addons/web_editor/static/src/js/summernote.js11
-rw-r--r--addons/website_sale_delivery/static/src/js/website_sale_delivery.js1
-rw-r--r--doc/cla/individual/IOAyman.md11
-rw-r--r--odoo/addons/base/res/res_partner_view.xml7
9 files changed, 151 insertions, 15 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index f3c9dba7135..9b7e6c7c903 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -43,8 +43,9 @@ class AccountInvoice(models.Model):
@api.one
@api.depends('invoice_line_ids.price_subtotal', 'tax_line_ids.amount', 'currency_id', 'company_id', 'date_invoice', 'type')
def _compute_amount(self):
+ round_curr = self.currency_id.round
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)
+ self.amount_tax = sum(round_curr(line.amount) for line in self.tax_line_ids)
self.amount_total = self.amount_untaxed + self.amount_tax
amount_total_company_signed = self.amount_total
amount_untaxed_signed = self.amount_untaxed
diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index bc5c440e35e..516fc2b6293 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -284,7 +284,7 @@ class StockMove(models.Model):
quants = quant_obj.quants_get_preferred_domain(move.product_qty, move, domain=main_domain, preferred_domain_list=preferred_domain_list)
self.env['stock.quant'].quants_move(quants, move, move.location_dest_id)
else:
- for movelot in move.move_lot_ids:
+ for movelot in move.active_move_lot_ids:
if float_compare(movelot.quantity_done, 0, precision_rounding=rounding) > 0:
if not movelot.lot_id:
raise UserError(_('You need to supply a lot/serial number.'))
diff --git a/addons/mrp/tests/test_workorder_operation.py b/addons/mrp/tests/test_workorder_operation.py
index 14eb7a65b31..eed76496be8 100644
--- a/addons/mrp/tests/test_workorder_operation.py
+++ b/addons/mrp/tests/test_workorder_operation.py
@@ -80,7 +80,6 @@ class TestWorkOrderProcess(common.TransactionCase):
# --------------------------------------------------------------
# Process cutting operation...
# ---------------------------------------------------------
-
finished_lot =self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
workorders[0].write({'final_lot_id': finished_lot.id})
workorders[0].button_start()
@@ -148,6 +147,119 @@ class TestWorkOrderProcess(common.TransactionCase):
self.assertEqual(finished_quant.consumed_quant_ids, consume_quants)
+ def test_00b_workorder_process(self):
+ """ Testing consume quants and produced quants with workorder """
+ dining_table = self.env.ref("mrp.product_product_computer_desk")
+ product_table_sheet = self.env.ref('mrp.product_product_computer_desk_head')
+ product_table_leg = self.env.ref('mrp.product_product_computer_desk_leg')
+ product_bolt = self.env.ref('mrp.product_product_computer_desk_bolt')
+
+ production_table = self.env['mrp.production'].create({
+ 'product_id': dining_table.id,
+ 'product_qty': 2.0,
+ 'product_uom_id': dining_table.uom_id.id,
+ 'bom_id': self.ref("mrp.mrp_bom_desk")
+ })
+
+ # Set tracking lot on finish and consume products.
+ dining_table.tracking = 'lot'
+ product_table_sheet.tracking = 'lot'
+ product_table_leg.tracking = 'lot'
+ product_bolt.tracking = "lot"
+
+ # Initial inventory of product sheet, lags and bolt
+ lot_sheet = self.env['stock.production.lot'].create({'product_id': product_table_sheet.id})
+ lot_leg = self.env['stock.production.lot'].create({'product_id': product_table_leg.id})
+ lot_bolt = self.env['stock.production.lot'].create({'product_id': product_bolt.id})
+
+ # Initialize inventory
+ # --------------------
+ inventory = self.env['stock.inventory'].create({
+ 'name': 'Inventory Product Table',
+ 'filter': 'partial',
+ 'line_ids': [(0, 0, {
+ 'product_id': product_table_sheet.id,
+ 'product_uom_id': product_table_sheet.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_sheet.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_table_leg.id,
+ 'product_uom_id': product_table_leg.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_leg.id,
+ 'location_id': self.source_location_id
+ }), (0, 0, {
+ 'product_id': product_bolt.id,
+ 'product_uom_id': product_bolt.uom_id.id,
+ 'product_qty': 20,
+ 'prod_lot_id': lot_bolt.id,
+ 'location_id': self.source_location_id
+ })]
+ })
+ inventory.action_done()
+
+ # Create work order
+ production_table.button_plan()
+ # Check Work order created or not
+ self.assertEqual(len(production_table.workorder_ids), 3)
+
+ # ---------------------------------------------------------
+ # Process all workorder and check it state.
+ # ----------------------------------------------------------
+
+ workorders = production_table.workorder_ids
+ self.assertEqual(workorders[0].state, 'ready', "First workorder state should be ready.")
+ self.assertEqual(workorders[1].state, 'pending')
+ self.assertEqual(workorders[2].state, 'pending')
+
+ # --------------------------------------------------------------
+ # Process cutting operation...
+ # ---------------------------------------------------------
+ finished_lot = self.env['stock.production.lot'].create({'product_id': production_table.product_id.id})
+ workorders[0].write({'final_lot_id': finished_lot.id, 'qty_producing': 1.0})
+ workorders[0].button_start()
+ workorders[0].active_move_lot_ids[0].write({'lot_id': lot_sheet.id, 'quantity_done': 1})
+ self.assertEqual(workorders[0].state, 'progress')
+ workorders[0].record_production()
+
+ move_table_sheet = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_sheet)
+ self.assertEqual(move_table_sheet.quantity_done, 1)
+
+ # --------------------------------------------------------------
+ # Process drilling operation ...
+ # ---------------------------------------------------------
+ workorders[1].button_start()
+ workorders[1].qty_producing = 1.0
+ workorders[1].active_move_lot_ids[0].write({'lot_id': lot_leg.id, 'quantity_done': 4})
+ workorders[1].record_production()
+ move_leg = production_table.move_raw_ids.filtered(lambda x : x.product_id == product_table_leg)
+ #self.assertEqual(workorders[1].state, 'done')
+ self.assertEqual(move_leg.quantity_done, 4)
+
+ # --------------------------------------------------------------
+ # Process fitting operation ...
+ # ---------------------------------------------------------
+ workorders[2].button_start()
+ workorders[2].qty_producing = 1.0
+ move_lot = workorders[2].active_move_lot_ids[0]
+ move_lot.write({'lot_id': lot_bolt.id, 'quantity_done': 4})
+ move_table_bolt = production_table.move_raw_ids.filtered(lambda x : x.product_id.id == product_bolt.id)
+ workorders[2].record_production()
+ self.assertEqual(move_table_bolt.quantity_done, 4)
+
+ # Change the quantity of the production order to 1
+ wiz = self.env['change.production.qty'].create({'mo_id': production_table.id ,
+ 'product_qty': 1.0})
+ wiz.change_prod_qty()
+ # ---------------------------------------------------------------
+ # Check consume quants and produce quants after posting inventory
+ # ---------------------------------------------------------------
+ production_table.post_inventory()
+ self.assertEqual(sum(move_table_sheet.quant_ids.mapped('qty')), 1, "Wrong quantity of consumed product %s" % move_table_sheet.product_id.name)
+ self.assertEqual(sum(move_leg.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s" % move_leg.product_id.name)
+ self.assertEqual(sum(move_table_bolt.quant_ids.mapped('qty')), 4, "Wrong quantity of consumed product %s" % move_table_bolt.product_id.name)
+
def test_01_without_workorder(self):
""" Testing consume quants and produced quants without workorder """
unit = self.ref("product.product_uom_unit")
diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py
index 463c30c0a7c..e9588516a0c 100644
--- a/addons/mrp/wizard/change_production_qty.py
+++ b/addons/mrp/wizard/change_production_qty.py
@@ -4,6 +4,7 @@
from odoo import api, fields, models, _
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError
+from odoo.tools import float_is_zero
import math
class ChangeProductionQty(models.TransientModel):
@@ -37,6 +38,7 @@ class ChangeProductionQty(models.TransientModel):
@api.multi
def change_prod_qty(self):
+ precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
for wizard in self:
production = wizard.mo_id
produced = sum(production.move_finished_ids.mapped('quantity_done'))
@@ -64,11 +66,14 @@ class ChangeProductionQty(models.TransientModel):
wo.duration_expected = (operation.workcenter_id.time_start +
operation.workcenter_id.time_stop +
cycle_number * operation.time_cycle * 100.0 / operation.workcenter_id.time_efficiency)
+ quantity = wo.qty_production - wo.qty_produced
if production.product_id.tracking == 'serial':
- quantity = 1.0
+ quantity = 1.0 if float_is_zero(quantity, precision_digits=precision) else 0.0
else:
- quantity = wo.qty_production - wo.qty_produced
quantity = quantity if (quantity > 0) else 0
+ if float_is_zero(quantity, precision_digits=precision):
+ wo.final_lot_id = False
+ wo.active_move_lot_ids.unlink()
wo.qty_producing = quantity
if wo.qty_produced < wo.qty_production and wo.state == 'done':
wo.state = 'progress'
@@ -81,6 +86,6 @@ class ChangeProductionQty(models.TransientModel):
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:
+ if quantity > 0 and 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/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index d45766d0ff5..7e7b108fd91 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -1606,7 +1606,7 @@ exports.Orderline = Backbone.Model.extend({
var sign = 1;
if(base < 0){
base = -base;
- var sign = -1;
+ sign = -1;
}
var incl_fixed_amount = 0.0;
@@ -1653,8 +1653,8 @@ exports.Orderline = Backbone.Model.extend({
});
return {
taxes: taxes_vals,
- total_excluded: round_pr(total_excluded, currency_rounding_bak),
- total_included: round_pr(total_included, currency_rounding_bak)
+ total_excluded: sign * round_pr(total_excluded, currency_rounding_bak),
+ total_included: sign * round_pr(total_included, currency_rounding_bak)
};
},
get_all_prices: function(){
diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js
index d28279d57ed..fe2ff837142 100644
--- a/addons/web_editor/static/src/js/summernote.js
+++ b/addons/web_editor/static/src/js/summernote.js
@@ -550,6 +550,13 @@ dom.removeBetween = function (sc, so, ec, eo, towrite) {
so = 0;
eo = 1;
}
+
+ var parentNode = sc && sc.parentNode;
+ if (parentNode && sc.tagName === 'BR') {
+ sc = parentNode;
+ ec = parentNode;
+ }
+
return {
sc: sc,
so: so,
@@ -1169,9 +1176,9 @@ $.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
if (!r) return;
if (!r.isCollapsed()) {
- if (dom.isCell(dom.node(r.sc)) || dom.isCell(dom.node(r.ec))) {
+ if ((dom.isCell(dom.node(r.sc)) || dom.isCell(dom.node(r.ec))) && dom.node(r.sc) !== dom.node(r.ec)) {
remove_table_content(r);
- r = range.create(r.ec, 0).select();
+ r = range.create(r.ec, 0);
}
r.select();
}
diff --git a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js
index 0775b7657cc..12710db3b4c 100644
--- a/addons/website_sale_delivery/static/src/js/website_sale_delivery.js
+++ b/addons/website_sale_delivery/static/src/js/website_sale_delivery.js
@@ -1,7 +1,6 @@
$(document).ready(function () {
var $pay_button = $('.oe_sale_acquirer_button button');
- $pay_button.prop('disabled', false);
// When choosing an delivery carrier, update the quotation and the acquirers. Disable the 'Pay
// Now' button to avoid being redirected to payment acquier if the delivery carrier update is
diff --git a/doc/cla/individual/IOAyman.md b/doc/cla/individual/IOAyman.md
new file mode 100644
index 00000000000..96a37ff862c
--- /dev/null
+++ b/doc/cla/individual/IOAyman.md
@@ -0,0 +1,11 @@
+Algeria, 10-19-2017
+
+I hereby agree to the terms of the Odoo Individual Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Ayman Nedjmeddine theycallmethedr@gmail.com https://github.com/IOAyman
diff --git a/odoo/addons/base/res/res_partner_view.xml b/odoo/addons/base/res/res_partner_view.xml
index fbfbf8823fa..25bc06a34ba 100644
--- a/odoo/addons/base/res/res_partner_view.xml
+++ b/odoo/addons/base/res/res_partner_view.xml
@@ -335,7 +335,8 @@
<search string="Search Partner">
<field name="name"
filter_domain="['|','|',('display_name','ilike',self),('ref','=',self),('email','ilike',self)]"/>
- <filter help="My Partners" domain="[('user_id','=',uid)]"/>
+ <filter name="filter_my_partners" help="My Partners"
+ domain="[('user_id','=',uid)]"/>
<separator/>
<filter string="Persons" name="type_person" domain="[('is_company','=',0)]"/>
<filter string="Companies" name="type_company" domain="[('is_company','=',1)]"/>
@@ -349,8 +350,8 @@
<field name="parent_id" domain="[('is_company','=',1)]" operator="child_of"/>
<group expand="0" name="group_by" string="Group By">
<filter name="salesperson" string="Salesperson" domain="[]" context="{'group_by' : 'user_id'}" />
- <filter string="Company" context="{'group_by': 'parent_id'}"/>
- <filter string="Country" context="{'group_by': 'country_id'}"/>
+ <filter name="group_company" string="Company" context="{'group_by': 'parent_id'}"/>
+ <filter name="group_country" string="Country" context="{'group_by': 'country_id'}"/>
</group>
</search>
</field>