Browse Source
Merge pull request #1 from legalsylvain/12.0-mig-tare-fix
Merge pull request #1 from legalsylvain/12.0-mig-tare-fix
12.0 mig tare fixpull/501/head
François Kawala
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 497 additions and 385 deletions
-
30pos_tare/__manifest__.py
-
10pos_tare/demo/pos_tare_demo.xml
-
1pos_tare/models/__init__.py
-
4pos_tare/models/barcode_rule.py
-
41pos_tare/models/pos_config.py
-
15pos_tare/models/pos_order_line.py
-
8pos_tare/pos_tare.xml
-
1pos_tare/readme/CONTRIBUTORS.rst
-
1pos_tare/readme/ROADMAP.rst
-
BINpos_tare/static/description/pos_ticket.png
-
114pos_tare/static/src/js/models.js
-
269pos_tare/static/src/js/pos_tare.js
-
137pos_tare/static/src/js/screens.js
-
62pos_tare/static/src/js/tools.js
-
79pos_tare/static/src/xml/pos_tare.xml
-
28pos_tare/views/pos_config_view.xml
-
10pos_tare/views/templates.xml
-
54pos_tare/views/view_pos_config.xml
-
16pos_tare/views/view_pos_order.xml
@ -1,10 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<odoo> |
|
||||
<record id="product_uom_kgm_dbg" model="uom.uom"> |
|
||||
<field name="category_id" ref="uom.product_uom_categ_kgm"/> |
|
||||
<field name="name">Kg</field> |
|
||||
<field name="factor" eval="1"/> |
|
||||
<field name="rounding" eval="0.001"/> |
|
||||
<field name="uom_type">bigger</field> |
|
||||
</record> |
|
||||
</odoo> |
|
@ -1,2 +1,3 @@ |
|||||
from . import pos_config |
from . import pos_config |
||||
|
from . import pos_order_line |
||||
from . import barcode_rule |
from . import barcode_rule |
@ -1,9 +1,9 @@ |
|||||
from odoo import _, models, fields |
|
||||
|
from odoo import models, fields |
||||
|
|
||||
|
|
||||
class BarcodeRule(models.Model): |
class BarcodeRule(models.Model): |
||||
_inherit = 'barcode.rule' |
_inherit = 'barcode.rule' |
||||
|
|
||||
type = fields.Selection(selection_add=[ |
type = fields.Selection(selection_add=[ |
||||
('tare', _('Tare')) |
|
||||
|
('tare', 'Tare') |
||||
]) |
]) |
@ -1,18 +1,39 @@ |
|||||
from odoo import models, fields |
|
||||
|
from odoo import api, models, fields |
||||
|
|
||||
|
|
||||
class PosConfig(models.Model): |
class PosConfig(models.Model): |
||||
_inherit = 'pos.config' |
|
||||
|
_inherit = "pos.config" |
||||
|
|
||||
iface_tare_method = fields.Selection([ |
iface_tare_method = fields.Selection([ |
||||
('Manual', 'Input the tare manually'), |
|
||||
('Barcode', 'Scan a barcode to set the tare'), |
|
||||
('Both', 'Manual input and barcode'), |
|
||||
|
("manual", "Input the tare manually"), |
||||
|
("barcode", "Scan a barcode to set the tare"), |
||||
|
("both", "Manual input and barcode"), |
||||
], |
], |
||||
string='Tare input method', |
|
||||
default='Both', |
|
||||
|
string="Tare Input Method", |
||||
|
default="both", |
||||
|
required=True, |
||||
help="Select tare method:\n" |
help="Select tare method:\n" |
||||
"* 'Manual (the scale screen has an extra tare input field)';\n" |
|
||||
"* 'Barecode (scan a barcode to tare the selected order line)';\n" |
|
||||
"* 'Both manual input and barcode methods are enabled';", |
|
||||
|
"* 'manual' : the scale screen has an extra tare input field;\n" |
||||
|
"* 'barecode' : (scan a barcode to tare the selected order line;\n" |
||||
|
"* 'both' : manual input and barcode methods are enabled;", |
||||
) |
) |
||||
|
|
||||
|
iface_gross_weight_method = fields.Selection([ |
||||
|
("manual", "Input the Gross Weight manually"), |
||||
|
("scale", "Input Gross Weight via Scale") |
||||
|
], |
||||
|
string="Gross Weight Input Method", |
||||
|
default="scale", |
||||
|
required=True, |
||||
|
) |
||||
|
|
||||
|
iface_tare_uom_id = fields.Many2one( |
||||
|
string="Unit of Measure of the tare", |
||||
|
comodel_name="uom.uom", |
||||
|
default=lambda s: s._default_iface_tare_uom_id(), |
||||
|
required=True, |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _default_iface_tare_uom_id(self): |
||||
|
return self.env.ref("uom.product_uom_kgm") |
@ -0,0 +1,15 @@ |
|||||
|
# Copyright (C) 2020-Today: GRAP (<http://www.grap.coop/>) |
||||
|
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models, fields |
||||
|
from odoo.addons import decimal_precision as dp |
||||
|
|
||||
|
|
||||
|
class PosOrderLine(models.Model): |
||||
|
_inherit = "pos.order.line" |
||||
|
|
||||
|
tare = fields.Float( |
||||
|
string="Tare", |
||||
|
digits=dp.get_precision("Product Unit of Measure") |
||||
|
) |
@ -1,8 +0,0 @@ |
|||||
<odoo> |
|
||||
<template id="assets_backend" name="pos_tare" inherit_id="point_of_sale.assets"> |
|
||||
<xpath expr="." position="inside"> |
|
||||
<link rel="stylesheet" href="/pos_tare/static/src/css/pos_tare.css"/> |
|
||||
<script type="text/javascript" src="/pos_tare/static/src/js/pos_tare.js"></script> |
|
||||
</xpath> |
|
||||
</template> |
|
||||
</odoo> |
|
@ -1,4 +1,3 @@ |
|||||
- Sylvain LE GAL (https://www.twitter.com/legalsylvain) |
- Sylvain LE GAL (https://www.twitter.com/legalsylvain) |
||||
- Le Nid |
- Le Nid |
||||
- CoopITEasy |
- CoopITEasy |
||||
|
|
@ -1 +0,0 @@ |
|||||
- Print tare value on customer receipt. |
|
After Width: 500 | Height: 395 | Size: 24 KiB |
@ -0,0 +1,114 @@ |
|||||
|
odoo.define('pos_tare.models', function (require) { |
||||
|
|
||||
|
"use strict"; |
||||
|
var core = require('web.core'); |
||||
|
var models = require('point_of_sale.models'); |
||||
|
var pos_tare_tools = require('pos_tare.tools'); |
||||
|
|
||||
|
var _t = core._t; |
||||
|
|
||||
|
var _super_ = models.Orderline.prototype; |
||||
|
var OrderLineWithTare = models.Orderline.extend({ |
||||
|
|
||||
|
// /////////////////////////////
|
||||
|
// Overload Section
|
||||
|
// /////////////////////////////
|
||||
|
initialize: function (session, attributes) { |
||||
|
this.tare = 0; |
||||
|
return _super_.initialize.call(this, session, attributes); |
||||
|
}, |
||||
|
|
||||
|
init_from_JSON: function (json) { |
||||
|
_super_.init_from_JSON.call(this, json); |
||||
|
this.tare = json.tare ||0; |
||||
|
}, |
||||
|
|
||||
|
clone: function () { |
||||
|
var orderline = _super_.clone.call(this); |
||||
|
orderline.tare = this.tare; |
||||
|
return orderline; |
||||
|
}, |
||||
|
|
||||
|
export_as_JSON: function () { |
||||
|
var json = _super_.export_as_JSON.call(this); |
||||
|
json.tare = this.get_tare(); |
||||
|
return json; |
||||
|
}, |
||||
|
|
||||
|
export_for_printing: function () { |
||||
|
var result = _super_.export_for_printing.call(this); |
||||
|
result.tare_quantity = this.get_tare(); |
||||
|
return result; |
||||
|
}, |
||||
|
|
||||
|
// /////////////////////////////
|
||||
|
// Custom Section
|
||||
|
// /////////////////////////////
|
||||
|
set_tare: function (quantity, update_net_weight) { |
||||
|
this.order.assert_editable(); |
||||
|
|
||||
|
// Prevent to apply multiple times a tare to the same product.
|
||||
|
if (this.get_tare() > 0) { |
||||
|
throw new RangeError(_.str.sprintf( |
||||
|
_t("The tare (%s) is already set for the " + |
||||
|
"product \"%s\". We can not re-apply a tare to this " + |
||||
|
"product."), |
||||
|
this.get_tare_str_with_unit(), this.product.display_name)); |
||||
|
} |
||||
|
|
||||
|
// We convert the tare that is always measured in the same UoM into
|
||||
|
// the unit of measure for this order line.
|
||||
|
var tare_unit = this.pos.units_by_id[this.pos.config.iface_tare_uom_id[0]]; |
||||
|
var tare = parseFloat(quantity) || 0; |
||||
|
var line_unit = this.get_unit(); |
||||
|
var tare_in_product_uom = pos_tare_tools.convert_mass(tare, tare_unit, line_unit); |
||||
|
var tare_in_product_uom_string = pos_tare_tools.format_tare(this.pos, |
||||
|
tare_in_product_uom, line_unit); |
||||
|
if (update_net_weight) { |
||||
|
var net_quantity = this.get_quantity() - tare_in_product_uom; |
||||
|
// This method fails when the net weight is negative.
|
||||
|
if (net_quantity <= 0) { |
||||
|
throw new RangeError(_.str.sprintf( |
||||
|
_t("The tare weight is %s %s, it's greater or equal to " + |
||||
|
"the product weight %s. We can not apply this tare."), |
||||
|
tare_in_product_uom_string, line_unit.name, |
||||
|
this.get_quantity_str_with_unit())); |
||||
|
} |
||||
|
// Update the quantity with the new weight net of tare quantity.
|
||||
|
this.set_quantity(net_quantity); |
||||
|
} |
||||
|
// Update tare value.
|
||||
|
this.tare = tare_in_product_uom; |
||||
|
this.trigger('change', this); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
get_tare: function () { |
||||
|
return this.tare; |
||||
|
}, |
||||
|
|
||||
|
get_tare_str_with_unit: function () { |
||||
|
var unit = this.get_unit(); |
||||
|
var tare_str = pos_tare_tools.format_tare( |
||||
|
this.pos, |
||||
|
this.tare, |
||||
|
this.get_unit(), |
||||
|
); |
||||
|
return tare_str + ' ' + unit.name; |
||||
|
}, |
||||
|
|
||||
|
get_gross_weight_str_with_unit: function () { |
||||
|
var unit = this.get_unit(); |
||||
|
var gross_weight_str = pos_tare_tools.format_tare( |
||||
|
this.pos, |
||||
|
this.get_tare() + this.get_quantity(), |
||||
|
this.get_unit(), |
||||
|
); |
||||
|
return gross_weight_str + ' ' + unit.name; |
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
models.Orderline = OrderLineWithTare; |
||||
|
|
||||
|
}); |
@ -1,269 +0,0 @@ |
|||||
odoo.define('pos_barcode_tare.screens', function (require) { |
|
||||
|
|
||||
"use strict"; |
|
||||
var core = require('web.core'); |
|
||||
var models = require('point_of_sale.models'); |
|
||||
var screens = require('point_of_sale.screens'); |
|
||||
var utils = require('web.utils'); |
|
||||
var field_utils = require('web.field_utils'); |
|
||||
|
|
||||
var _t = core._t; |
|
||||
var round_pr = utils.round_precision; |
|
||||
var round_di = utils.round_decimals; |
|
||||
|
|
||||
// Define functions used to do unit operation.
|
|
||||
// Get unit search for unit based on unit name.
|
|
||||
var get_unit = function (pos, unit_name) { |
|
||||
return pos.units.filter( |
|
||||
function (u) { |
|
||||
return u.name === unit_name; |
|
||||
})[0]; |
|
||||
}; |
|
||||
|
|
||||
// Convert mass using the reference UOM as pivot unit.
|
|
||||
var convert_mass = function (mass, from_unit, to_unit) { |
|
||||
// There is no conversion from one category to another.
|
|
||||
if (from_unit.category_id[0] !== to_unit.category_id[0]) { |
|
||||
throw new Error(_.str.sprintf( |
|
||||
_t("We can not cast a weight in %s into %s."), |
|
||||
from_unit.name, to_unit.name)); |
|
||||
} |
|
||||
// No need to convert as weights are measured in same unit.
|
|
||||
if (from_unit.id === to_unit.id) { |
|
||||
return mass; |
|
||||
} |
|
||||
// Converts "from_unit" to reference unit of measure.
|
|
||||
var result = mass; |
|
||||
if (from_unit.uom_type === "bigger") { |
|
||||
result /= from_unit.factor; |
|
||||
} else { |
|
||||
result *= from_unit.factor_inv; |
|
||||
} |
|
||||
// Converts reference unit of measure to "to_unit".
|
|
||||
if (to_unit.uom_type === "bigger") { |
|
||||
result *= to_unit.factor; |
|
||||
} else { |
|
||||
result /= to_unit.factor_inv; |
|
||||
} |
|
||||
|
|
||||
if (to_unit.rounding) { |
|
||||
// Return the rounded result if needed.
|
|
||||
return round_pr(result || 0, to_unit.rounding); |
|
||||
} |
|
||||
|
|
||||
return result || 0; |
|
||||
}; |
|
||||
|
|
||||
// Format the tare value.
|
|
||||
var format_tare = function (pos, qty, unit) { |
|
||||
if (unit.rounding) { |
|
||||
var q = round_pr(qty, unit.rounding); |
|
||||
var decimals = pos.dp['Product Unit of Measure']; |
|
||||
return field_utils.format.float( |
|
||||
round_di(q, decimals), |
|
||||
{type: 'float', digits: [69, decimals]}); |
|
||||
} |
|
||||
return qty.toFixed(0); |
|
||||
}; |
|
||||
|
|
||||
// This configures read action for tare barcode. A tare barcode contains a
|
|
||||
// fake product ID and the weight to be subtracted from the product in the
|
|
||||
// latest order line.
|
|
||||
screens.ScreenWidget.include( |
|
||||
{ |
|
||||
barcode_tare_action: function (code) { |
|
||||
try { |
|
||||
var order = this.pos.get_order(); |
|
||||
var selected_order_line = order.get_selected_orderline(); |
|
||||
var tare_weight = code.value; |
|
||||
selected_order_line.set_tare(tare_weight); |
|
||||
} catch (error) { |
|
||||
var title = _t("We can not apply this tare barcode."); |
|
||||
var popup = {title: title, body: error.message}; |
|
||||
this.gui.show_popup('error', popup); |
|
||||
} |
|
||||
}, |
|
||||
// Setup the callback action for the "weight" barcodes.
|
|
||||
show: function () { |
|
||||
|
|
||||
console.log("okok"); |
|
||||
this._super(); |
|
||||
if (this.pos.config.iface_tare_method !== 'Manual') { |
|
||||
|
|
||||
console.log("okokokok"); |
|
||||
this.pos.barcode_reader.set_action_callback( |
|
||||
'tare', |
|
||||
_.bind(this.barcode_tare_action, this)); |
|
||||
} |
|
||||
}, |
|
||||
}); |
|
||||
|
|
||||
screens.ScaleScreenWidget.include({ |
|
||||
|
|
||||
// /////////////////////////////
|
|
||||
// Overload Section
|
|
||||
// /////////////////////////////
|
|
||||
|
|
||||
// Overload show function
|
|
||||
// add an handler on the
|
|
||||
show: function () { |
|
||||
this._super(); |
|
||||
this.tare = 0.0; |
|
||||
var self = this; |
|
||||
this.$('#input_weight_tare').keyup(function (event) { |
|
||||
self.onchange_tare(event); |
|
||||
}); |
|
||||
this.$('#input_weight_tare').focus(); |
|
||||
}, |
|
||||
|
|
||||
// Overload set_weight function
|
|
||||
// We assume that the argument is now the gross weight
|
|
||||
// we compute the net weight, depending on the tare and the gross weight
|
|
||||
// then we call super, with the net weight
|
|
||||
set_weight: function (gross_weight) { |
|
||||
this.gross_weight = gross_weight; |
|
||||
var net_weight = gross_weight - (this.tare || 0); |
|
||||
this.$('#container_weight_gross').text( |
|
||||
this.get_product_gross_weight_string()); |
|
||||
this._super(net_weight); |
|
||||
}, |
|
||||
|
|
||||
order_product: function () { |
|
||||
// TODO Set a warning, if the value is incorrect;
|
|
||||
if (this.tare === undefined) { |
|
||||
this.gui.show_popup('error', { |
|
||||
'title': _t('Incorrect Tare Value'), |
|
||||
'body': _t('Please set a numeric value' + |
|
||||
' in the tare field, or let empty.'), |
|
||||
}); |
|
||||
} else { |
|
||||
this._super(); |
|
||||
if (this.tare > 0.0) { |
|
||||
var order = this.pos.get_order(); |
|
||||
var orderline = order.get_last_orderline(); |
|
||||
orderline.set_tare(this.tare); |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// /////////////////////////////
|
|
||||
// Custom Section
|
|
||||
// /////////////////////////////
|
|
||||
get_product_gross_weight_string: function () { |
|
||||
var product = this.get_product(); |
|
||||
var defaultstr = (this.gross_weight || 0).toFixed(3) + ' Kg'; |
|
||||
if (!product || !this.pos) { |
|
||||
return defaultstr; |
|
||||
} |
|
||||
var unit_id = product.uom_id; |
|
||||
if (!unit_id) { |
|
||||
return defaultstr; |
|
||||
} |
|
||||
var unit = this.pos.units_by_id[unit_id[0]]; |
|
||||
var weight = round_pr(this.gross_weight || 0, unit.rounding); |
|
||||
var weightstr = weight.toFixed( |
|
||||
Math.ceil(Math.log(1.0/unit.rounding) / Math.log(10) )); |
|
||||
weightstr += ' ' + unit.name; |
|
||||
return weightstr; |
|
||||
}, |
|
||||
|
|
||||
onchange_tare: function () { |
|
||||
this.tare = this.check_sanitize_value('#input_weight_tare'); |
|
||||
this.set_weight(this.gross_weight); |
|
||||
}, |
|
||||
|
|
||||
check_sanitize_value: function (input_name) { |
|
||||
var res = this.$(input_name)[0].value.replace(',', '.').trim(); |
|
||||
if (isNaN(res)) { |
|
||||
this.$(input_name).css("background-color", "#F66"); |
|
||||
return undefined; |
|
||||
} |
|
||||
this.$(input_name).css("background-color", "#FFF"); |
|
||||
return parseFloat(res, 10); |
|
||||
}, |
|
||||
|
|
||||
}); |
|
||||
|
|
||||
// Update Orderline model
|
|
||||
var _super_ = models.Orderline.prototype; |
|
||||
var OrderLineWithTare = models.Orderline.extend({ |
|
||||
initialize: function (session, attributes) { |
|
||||
this.tareQuantity = 0; |
|
||||
this.tareQuantityStr = '0'; |
|
||||
return _super_.initialize.call(this, session, attributes); |
|
||||
}, |
|
||||
init_from_JSON: function (json) { |
|
||||
_super_.init_from_JSON.call(this, json); |
|
||||
this.tareQuantity = json.tareQuantity ||0; |
|
||||
this.tareQuantityStr = json.tareQuantityStr ||'0'; |
|
||||
}, |
|
||||
set_tare: function (quantity) { |
|
||||
this.order.assert_editable(); |
|
||||
|
|
||||
// Prevent to apply multiple times a tare to the same product.
|
|
||||
if (this.get_tare() > 0) { |
|
||||
throw new RangeError(_.str.sprintf( |
|
||||
_t("The tare (%s) is already set for the " + |
|
||||
"product \"%s\". We can not re-apply a tare to this " + |
|
||||
"product."), |
|
||||
this.get_tare_str_with_unit(), this.product.display_name)); |
|
||||
} |
|
||||
|
|
||||
// We convert the tare that is always measured in kilogrammes into
|
|
||||
// the unit of measure for this order line.
|
|
||||
var kg = get_unit(this.pos, "kg"); |
|
||||
var tare = parseFloat(quantity) || 0; |
|
||||
var unit = this.get_unit(); |
|
||||
var tare_in_product_uom = convert_mass(tare, kg, unit); |
|
||||
var tare_in_product_uom_string = format_tare(this.pos, |
|
||||
tare_in_product_uom, unit); |
|
||||
var net_quantity = this.get_quantity() - tare_in_product_uom; |
|
||||
// This method fails when the net weight is negative.
|
|
||||
if (net_quantity <= 0) { |
|
||||
throw new RangeError(_.str.sprintf( |
|
||||
_t("The tare weight is %s %s, it's greater or equal to " + |
|
||||
"the product weight %s. We can not apply this tare."), |
|
||||
tare_in_product_uom_string, unit.name, |
|
||||
this.get_quantity_str_with_unit())); |
|
||||
} |
|
||||
// Update tare value.
|
|
||||
this.tareQuantity = tare_in_product_uom; |
|
||||
this.tareQuantityStr = tare_in_product_uom_string; |
|
||||
// Update the quantity with the new weight net of tare quantity.
|
|
||||
this.set_quantity(net_quantity); |
|
||||
this.trigger('change', this); |
|
||||
}, |
|
||||
get_tare: function () { |
|
||||
return this.tareQuantity; |
|
||||
}, |
|
||||
get_tare_str: function () { |
|
||||
return this.tareQuantityStr; |
|
||||
}, |
|
||||
get_tare_str_with_unit: function () { |
|
||||
var unit = this.get_unit(); |
|
||||
return this.tareQuantityStr + ' ' + unit.name; |
|
||||
}, |
|
||||
export_as_JSON: function () { |
|
||||
var json = _super_.export_as_JSON.call(this); |
|
||||
json.tareQuantity = this.get_tare(); |
|
||||
json.tareQuantityStr = this.get_tare_str(); |
|
||||
return json; |
|
||||
}, |
|
||||
clone: function () { |
|
||||
var orderline = _super_.clone.call(this); |
|
||||
orderline.tareQuantity = this.tareQuantity; |
|
||||
orderline.tareQuantityStr = this.tareQuantityStr; |
|
||||
return orderline; |
|
||||
}, |
|
||||
export_for_printing: function () { |
|
||||
var result = _super_.export_for_printing.call(this); |
|
||||
result.tare_quantity = this.get_tare(); |
|
||||
return result; |
|
||||
}, |
|
||||
}); |
|
||||
|
|
||||
models.Orderline = OrderLineWithTare; |
|
||||
|
|
||||
return {OrderLineWithTare: OrderLineWithTare, |
|
||||
get_unit: get_unit}; |
|
||||
}); |
|
@ -0,0 +1,137 @@ |
|||||
|
odoo.define('pos_tare.screens', function (require) { |
||||
|
|
||||
|
"use strict"; |
||||
|
var core = require('web.core'); |
||||
|
var screens = require('point_of_sale.screens'); |
||||
|
var utils = require('web.utils'); |
||||
|
|
||||
|
var _t = core._t; |
||||
|
var round_pr = utils.round_precision; |
||||
|
|
||||
|
// This configures read action for tare barcode. A tare barcode contains a
|
||||
|
// fake product ID and the weight to be subtracted from the product in the
|
||||
|
// latest order line.
|
||||
|
screens.ScreenWidget.include( |
||||
|
{ |
||||
|
barcode_tare_action: function (code) { |
||||
|
try { |
||||
|
var order = this.pos.get_order(); |
||||
|
var selected_order_line = order.get_selected_orderline(); |
||||
|
var tare_weight = code.value; |
||||
|
selected_order_line.set_tare(tare_weight, true); |
||||
|
} catch (error) { |
||||
|
var title = _t("We can not apply this tare barcode."); |
||||
|
var popup = {title: title, body: error.message}; |
||||
|
this.gui.show_popup('error', popup); |
||||
|
} |
||||
|
}, |
||||
|
// Setup the callback action for the "weight" barcodes.
|
||||
|
show: function () { |
||||
|
this._super(); |
||||
|
if (this.pos.config.iface_tare_method !== 'manual') { |
||||
|
this.pos.barcode_reader.set_action_callback( |
||||
|
'tare', |
||||
|
_.bind(this.barcode_tare_action, this)); |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
screens.ScaleScreenWidget.include({ |
||||
|
|
||||
|
// /////////////////////////////
|
||||
|
// Overload Section
|
||||
|
// /////////////////////////////
|
||||
|
|
||||
|
show: function () { |
||||
|
this.tare = 0.0; |
||||
|
this.gross_weight = 0.0; |
||||
|
this._super(); |
||||
|
var self = this; |
||||
|
this.$('#input_weight_tare').keyup(function (event) { |
||||
|
self.onchange_tare(event); |
||||
|
}); |
||||
|
this.$('#input_gross_weight').keyup(function (event) { |
||||
|
self.onchange_gross_weight(event); |
||||
|
}); |
||||
|
if (this.pos.config.iface_gross_weight_method === 'scale') { |
||||
|
this.$('#input_weight_tare').focus(); |
||||
|
} else{ |
||||
|
this.pos.proxy_queue.clear(); |
||||
|
this.$('#input_gross_weight').focus(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// Overload set_weight function
|
||||
|
// We assume that the argument is now the gross weight
|
||||
|
// we compute the net weight, depending on the tare and the gross weight
|
||||
|
// then we call super, with the net weight
|
||||
|
set_weight: function (gross_weight) { |
||||
|
this.gross_weight = gross_weight; |
||||
|
var net_weight = gross_weight - (this.tare || 0); |
||||
|
this.$('#container_weight_gross').text( |
||||
|
this.get_product_gross_weight_string()); |
||||
|
this._super(net_weight); |
||||
|
}, |
||||
|
|
||||
|
order_product: function () { |
||||
|
// TODO Set a warning, if the value is incorrect;
|
||||
|
if (this.tare === undefined) { |
||||
|
this.gui.show_popup('error', { |
||||
|
'title': _t('Incorrect Tare Value'), |
||||
|
'body': _t('Please set a numeric value' + |
||||
|
' in the tare field, or let empty.'), |
||||
|
}); |
||||
|
} else { |
||||
|
this._super(); |
||||
|
if (this.tare > 0.0) { |
||||
|
var order = this.pos.get_order(); |
||||
|
var orderline = order.get_last_orderline(); |
||||
|
orderline.set_tare(this.tare, false); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
// /////////////////////////////
|
||||
|
// Custom Section
|
||||
|
// /////////////////////////////
|
||||
|
get_product_gross_weight_string: function () { |
||||
|
var product = this.get_product(); |
||||
|
var defaultstr = (this.gross_weight || 0).toFixed(3) + ' Kg'; |
||||
|
if (!product || !this.pos) { |
||||
|
return defaultstr; |
||||
|
} |
||||
|
var unit_id = product.uom_id; |
||||
|
if (!unit_id) { |
||||
|
return defaultstr; |
||||
|
} |
||||
|
var unit = this.pos.units_by_id[unit_id[0]]; |
||||
|
var weight = round_pr(this.gross_weight || 0, unit.rounding); |
||||
|
var weightstr = weight.toFixed( |
||||
|
Math.ceil(Math.log(1.0/unit.rounding) / Math.log(10) )); |
||||
|
weightstr += ' ' + unit.name; |
||||
|
return weightstr; |
||||
|
}, |
||||
|
|
||||
|
onchange_tare: function () { |
||||
|
this.tare = this.check_sanitize_value('#input_weight_tare'); |
||||
|
this.set_weight(this.gross_weight); |
||||
|
}, |
||||
|
|
||||
|
onchange_gross_weight: function () { |
||||
|
var gross_weight = this.check_sanitize_value('#input_gross_weight'); |
||||
|
this.set_weight(gross_weight); |
||||
|
}, |
||||
|
|
||||
|
check_sanitize_value: function (input_name) { |
||||
|
var res = this.$(input_name)[0].value.replace(',', '.').trim(); |
||||
|
if (isNaN(res)) { |
||||
|
this.$(input_name).css("background-color", "#F66"); |
||||
|
return undefined; |
||||
|
} |
||||
|
this.$(input_name).css("background-color", "#FFF"); |
||||
|
return parseFloat(res, 10); |
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,62 @@ |
|||||
|
odoo.define('pos_tare.tools', function (require) { |
||||
|
|
||||
|
"use strict"; |
||||
|
var core = require('web.core'); |
||||
|
var utils = require('web.utils'); |
||||
|
var field_utils = require('web.field_utils'); |
||||
|
|
||||
|
var _t = core._t; |
||||
|
var round_pr = utils.round_precision; |
||||
|
var round_di = utils.round_decimals; |
||||
|
|
||||
|
// Convert mass using the reference UOM as pivot unit.
|
||||
|
var convert_mass = function (mass, from_unit, to_unit) { |
||||
|
// There is no conversion from one category to another.
|
||||
|
if (from_unit.category_id[0] !== to_unit.category_id[0]) { |
||||
|
throw new Error(_.str.sprintf( |
||||
|
_t("We can not cast a weight in %s into %s."), |
||||
|
from_unit.name, to_unit.name)); |
||||
|
} |
||||
|
// No need to convert as weights are measured in same unit.
|
||||
|
if (from_unit.id === to_unit.id) { |
||||
|
return mass; |
||||
|
} |
||||
|
// Converts "from_unit" to reference unit of measure.
|
||||
|
var result = mass; |
||||
|
if (from_unit.uom_type === "bigger") { |
||||
|
result /= from_unit.factor; |
||||
|
} else { |
||||
|
result *= from_unit.factor_inv; |
||||
|
} |
||||
|
// Converts reference unit of measure to "to_unit".
|
||||
|
if (to_unit.uom_type === "bigger") { |
||||
|
result *= to_unit.factor; |
||||
|
} else { |
||||
|
result /= to_unit.factor_inv; |
||||
|
} |
||||
|
|
||||
|
if (to_unit.rounding) { |
||||
|
// Return the rounded result if needed.
|
||||
|
return round_pr(result || 0, to_unit.rounding); |
||||
|
} |
||||
|
|
||||
|
return result || 0; |
||||
|
}; |
||||
|
|
||||
|
// Format the tare value.
|
||||
|
var format_tare = function (pos, qty, unit) { |
||||
|
if (unit.rounding) { |
||||
|
var q = round_pr(qty, unit.rounding); |
||||
|
var decimals = pos.dp['Product Unit of Measure']; |
||||
|
return field_utils.format.float( |
||||
|
round_di(q, decimals), |
||||
|
{type: 'float', digits: [69, decimals]}); |
||||
|
} |
||||
|
return qty.toFixed(0); |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
convert_mass: convert_mass, |
||||
|
format_tare: format_tare, |
||||
|
}; |
||||
|
}); |
@ -1,28 +0,0 @@ |
|||||
<?xml version="1.0"?> |
|
||||
|
|
||||
|
|
||||
<odoo> |
|
||||
<record model="ir.ui.view" id="view_pos_config_form"> |
|
||||
<field name="name">view.pos.config.form</field> |
|
||||
<field name="model">pos.config</field> |
|
||||
<field name="inherit_id" ref="point_of_sale.pos_config_view_form" /> |
|
||||
<field name="priority" eval="30"/> |
|
||||
<field name="arch" type="xml"> |
|
||||
<xpath expr="//h2[@name='order']/following-sibling::*[position()=1]" position="inside"> |
|
||||
<div class="col-xs-12 col-lg-6 o_setting_box" id="iface_tare_method"> |
|
||||
<div class="o_setting_right_pane"> |
|
||||
<label for="iface_tare_method" string="Tare method"/> |
|
||||
<div class="text-muted"> |
|
||||
Configure how to tare products to weight with a scale. |
|
||||
</div> |
|
||||
<div class="content-group"> |
|
||||
<div class="mt16"> |
|
||||
<field name="iface_tare_method" class="o_light_label"/> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</xpath> |
|
||||
</field> |
|
||||
</record> |
|
||||
</odoo> |
|
@ -0,0 +1,10 @@ |
|||||
|
<odoo> |
||||
|
<template id="assets" inherit_id="point_of_sale.assets"> |
||||
|
<xpath expr="." position="inside"> |
||||
|
<link rel="stylesheet" href="/pos_tare/static/src/css/pos_tare.css"/> |
||||
|
<script type="text/javascript" src="/pos_tare/static/src/js/tools.js"></script> |
||||
|
<script type="text/javascript" src="/pos_tare/static/src/js/models.js"></script> |
||||
|
<script type="text/javascript" src="/pos_tare/static/src/js/screens.js"></script> |
||||
|
</xpath> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,54 @@ |
|||||
|
<?xml version="1.0"?> |
||||
|
|
||||
|
|
||||
|
<odoo> |
||||
|
|
||||
|
<record model="ir.ui.view" id="view_pos_config_form"> |
||||
|
<field name="model">pos.config</field> |
||||
|
<field name="inherit_id" ref="point_of_sale.pos_config_view_form" /> |
||||
|
<field name="priority" eval="30"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//h2[@name='order']/following-sibling::*[position()=1]" position="inside"> |
||||
|
<div class="col-xs-12 col-lg-6 o_setting_box" id="iface_tare_method"> |
||||
|
<div class="o_setting_right_pane"> |
||||
|
<label for="iface_tare_method" string="Tare Input Method"/> |
||||
|
<div class="text-muted"> |
||||
|
Configure how to tare products to weight with a scale. |
||||
|
</div> |
||||
|
<div class="content-group"> |
||||
|
<div class="mt16"> |
||||
|
<field name="iface_tare_method" class="o_light_label"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xs-12 col-lg-6 o_setting_box" id="iface_tare_method"> |
||||
|
<div class="o_setting_right_pane"> |
||||
|
<label for="iface_tare_uom_id" string="Tare UoM"/> |
||||
|
<div class="text-muted"> |
||||
|
Unit of Measure of the tares. |
||||
|
</div> |
||||
|
<div class="content-group"> |
||||
|
<div class="mt16"> |
||||
|
<field name="iface_tare_uom_id" class="o_light_label"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="col-xs-12 col-lg-6 o_setting_box" id="iface_gross_weight_method"> |
||||
|
<div class="o_setting_right_pane"> |
||||
|
<label for="iface_gross_weight_method" string="Gross Weight Input Method"/> |
||||
|
<div class="text-muted"> |
||||
|
Configure how to input Gross Weight. |
||||
|
</div> |
||||
|
<div class="content-group"> |
||||
|
<div class="mt16"> |
||||
|
<field name="iface_gross_weight_method" class="o_light_label"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,16 @@ |
|||||
|
<?xml version="1.0"?> |
||||
|
|
||||
|
|
||||
|
<odoo> |
||||
|
|
||||
|
<record model="ir.ui.view" id="view_pos_order_form"> |
||||
|
<field name="model">pos.order</field> |
||||
|
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="qty" position="after"> |
||||
|
<field name="tare"/> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue