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
5 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
-
81pos_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_order_line |
|||
from . import barcode_rule |
@ -1,9 +1,9 @@ |
|||
from odoo import _, models, fields |
|||
from odoo import models, fields |
|||
|
|||
|
|||
class BarcodeRule(models.Model): |
|||
_inherit = 'barcode.rule' |
|||
|
|||
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): |
|||
_inherit = 'pos.config' |
|||
_inherit = "pos.config" |
|||
|
|||
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" |
|||
"* '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) |
|||
- Le Nid |
|||
- 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,60 +1,59 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates id="template" xml:space="preserve"> |
|||
|
|||
|
|||
|
|||
<t t-extend="ScaleScreenWidget"> |
|||
<t t-jquery=".js-weight" t-operation="before"> |
|||
<t t-if="widget.pos.config.iface_tare_method != 'Barcode'"> |
|||
<t t-if="widget.pos.config.iface_tare_method != 'barcode'"> |
|||
<div class="weight-label"> |
|||
Gross Weight |
|||
</div> |
|||
<div class="weight-value weight-value-fixed" id="container_weight_gross"/> |
|||
<t t-if="widget.pos.config.iface_gross_weight_method == 'scale'"> |
|||
<div class="weight-value weight-value-fixed" |
|||
id="container_weight_gross"/> |
|||
</t> |
|||
<t t-else="1"> |
|||
<div class="weight-value weight-value-alterable"> |
|||
<input type="text" class="input-weight" id="input_gross_weight" placeholder="0.000"/> |
|||
<t t-esc="widget.pos.config.iface_tare_uom_id[1]"/> |
|||
</div> |
|||
</t> |
|||
<div class="weight-label"> |
|||
Tare |
|||
</div> |
|||
<div class="weight-value weight-value-alterable"> |
|||
<input type="text" class="input-weight" id="input_weight_tare" placeholder="0.000"/> Kg |
|||
<input type="text" class="input-weight" id="input_weight_tare" placeholder="0.000"/> |
|||
<t t-esc="widget.pos.config.iface_tare_uom_id[1]"/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<t t-name="Orderline"> |
|||
<li t-attf-class="orderline #{ line.selected ? 'selected' : '' }"> |
|||
<span class="product-name"> |
|||
<t t-esc="line.get_product().display_name"/> |
|||
</span> |
|||
<span class="price"> |
|||
<t t-esc="widget.format_currency(line.get_display_price())"/> |
|||
</span> |
|||
<ul class="info-list"> |
|||
<t t-if="line.get_quantity_str() !== '1' || line.selected "> |
|||
<li class="info"> |
|||
<em> |
|||
<t t-esc="line.get_quantity_str()" /> |
|||
</em> |
|||
<t t-esc="line.get_unit().name" /> |
|||
at |
|||
<t t-esc="widget.format_currency(line.get_unit_display_price(),'Product Price')" /> |
|||
/ |
|||
<t t-esc="line.get_unit().name" /> |
|||
</li> |
|||
</t> |
|||
<t t-if="line.get_discount_str() !== '0'"> |
|||
<li class="info"> |
|||
With a |
|||
<em> |
|||
<t t-esc="line.get_discount_str()" />% |
|||
</em> |
|||
discount |
|||
</li> |
|||
</t> |
|||
<t t-if="line.get_tare_str() !== '0'"> |
|||
<li class="info"> |
|||
tare = <t t-esc="line.get_tare_str_with_unit()" /> |
|||
</li> |
|||
</t> |
|||
</ul> |
|||
</li> |
|||
|
|||
<t t-extend="Orderline"> |
|||
<t t-jquery=".info-list:last-child" t-operation="append"> |
|||
<t t-if="line.get_tare() !== 0"> |
|||
<li class="info"> |
|||
<i class="fa fa-beer"/> |
|||
Tare : <t t-esc="line.get_tare_str_with_unit()" /> |
|||
</li> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
|
|||
<t t-name="PosTicket" t-extend="PosTicket"> |
|||
<t t-jquery="tr[t-foreach='orderlines'] > td:nth-child(1)" |
|||
t-operation="append"> |
|||
<t t-if="orderline.get_tare() > 0"> |
|||
<div class="pos-disc-font"> |
|||
Gross Weight : <t t-esc="orderline.get_gross_weight_str_with_unit()" /><br/> |
|||
Tare : <t t-esc="orderline.get_tare_str_with_unit()" /><br/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
|
|||
<!-- TODO Overload XmlReceipt for Proxy usage --> |
|||
<!-- <t t-name="XmlReceipt" t-extend="XmlReceipt"> |
|||
</t> --> |
|||
|
|||
</templates> |
@ -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