diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index df2e4fa40fd..11f554eea1e 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -126,6 +126,7 @@ class pos_config(osv.osv):
'group_pos_manager_id': fields.many2one('res.groups','Point of Sale Manager Group', help='This field is there to pass the id of the pos manager group to the point of sale client'),
'group_pos_user_id': fields.many2one('res.groups','Point of Sale User Group', help='This field is there to pass the id of the pos user group to the point of sale client'),
'tip_product_id': fields.many2one('product.product','Tip Product', help="The product used to encode the customer tip. Leave empty if you do not accept tips."),
+ 'fiscal_position_ids': fields.many2many('account.fiscal.position', string='Fiscal Positions')
}
def _check_company_location(self, cr, uid, ids, context=None):
@@ -640,8 +641,10 @@ class pos_order(osv.osv):
_description = "Point of Sale"
_order = "id desc"
- def _amount_line_tax(self, cr, uid, line, context=None):
+ def _amount_line_tax(self, cr, uid, line, fiscal_position_id, context=None):
taxes = line.product_id.taxes_id.filtered(lambda t: t.company_id.id == line.order_id.company_id.id)
+ if fiscal_position_id:
+ taxes = fiscal_position_id.map_tax(taxes)
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
cur = line.order_id.pricelist_id.currency_id
taxes = taxes.compute_all(price, cur, line.qty, product=line.product_id, partner=line.order_id.partner_id or False)['taxes']
@@ -659,7 +662,8 @@ class pos_order(osv.osv):
'lines': [process_line(l) for l in ui_order['lines']] if ui_order['lines'] else False,
'pos_reference':ui_order['name'],
'partner_id': ui_order['partner_id'] or False,
- 'date_order': ui_order['creation_date']
+ 'date_order': ui_order['creation_date'],
+ 'fiscal_position_id': ui_order['fiscal_position_id']
}
def _payment_fields(self, cr, uid, ui_paymentline, context=None):
@@ -800,7 +804,7 @@ class pos_order(osv.osv):
res[order.id]['amount_paid'] += payment.amount
res[order.id]['amount_return'] += (payment.amount < 0 and payment.amount or 0)
for line in order.lines:
- val1 += self._amount_line_tax(cr, uid, line, context=context)
+ val1 += self._amount_line_tax(cr, uid, line, order.fiscal_position_id, context=context)
val2 += line.price_subtotal
res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val1)
amount_untaxed = cur_obj.round(cr, uid, cur, val2)
@@ -845,6 +849,7 @@ class pos_order(osv.osv):
'nb_print': fields.integer('Number of Print', readonly=True, copy=False),
'pos_reference': fields.char('Receipt Ref', readonly=True, copy=False),
'sale_journal': fields.related('session_id', 'config_id', 'journal_id', relation='account.journal', type='many2one', string='Sale Journal', store=True, readonly=True),
+ 'fiscal_position_id': fields.many2one('account.fiscal.position', 'Fiscal Position')
}
def _default_session(self, cr, uid, context=None):
@@ -1127,6 +1132,10 @@ class pos_order(osv.osv):
invoice_line = inv_line_ref.new(cr, SUPERUSER_ID, inv_line, context=local_context)
invoice_line._onchange_product_id()
invoice_line.invoice_line_tax_ids = [tax.id for tax in invoice_line.invoice_line_tax_ids if tax.company_id.id == company_id]
+ fiscal_position_id = line.order_id.fiscal_position_id
+ if fiscal_position_id:
+ invoice_line.invoice_line_tax_ids = fiscal_position_id.map_tax(invoice_line.invoice_line_tax_ids)
+ invoice_line.invoice_line_tax_ids = [tax.id for tax in invoice_line.invoice_line_tax_ids]
# We convert a new id object back to a dictionary to write to bridge between old and new api
inv_line = invoice_line._convert_to_write(invoice_line._cache)
inv_line.update(price_unit=line.price_unit, discount=line.discount)
@@ -1367,7 +1376,11 @@ class pos_order_line(osv.osv):
account_tax_obj = self.pool.get('account.tax')
for line in self.browse(cr, uid, ids, context=context):
cur = line.order_id.pricelist_id.currency_id
- taxes_ids = [ tax.id for tax in line.product_id.taxes_id if tax.company_id.id == line.order_id.company_id.id ]
+ taxes = [ tax for tax in line.product_id.taxes_id if tax.company_id.id == line.order_id.company_id.id ]
+ fiscal_position_id = line.order_id.fiscal_position_id
+ if fiscal_position_id:
+ taxes = fiscal_position_id.map_tax(taxes)
+ taxes_ids = [ tax.id for tax in taxes ]
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
res[line.id]['price_subtotal'] = res[line.id]['price_subtotal_incl'] = price * line.qty
if taxes_ids:
@@ -1412,6 +1425,12 @@ class pos_order_line(osv.osv):
result['price_subtotal_incl'] = taxes['total_included']
return {'value': result}
+ def _get_tax_ids_after_fiscal_position(self, cr, uid, ids, field_name, args, context=None):
+ res = dict.fromkeys(ids, False)
+ for line in self.browse(cr, uid, ids, context=context):
+ res[line.id] = line.order_id.fiscal_position_id.map_tax(line.tax_ids)
+ return res
+
_columns = {
'company_id': fields.many2one('res.company', 'Company', required=True),
'name': fields.char('Line No', required=True, copy=False),
@@ -1419,12 +1438,13 @@ class pos_order_line(osv.osv):
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True, change_default=True),
'price_unit': fields.float(string='Unit Price', digits=0),
'qty': fields.float('Quantity', digits=0),
- 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits=0, string='Subtotal w/o Tax', store=True),
- 'price_subtotal_incl': fields.function(_amount_line_all, multi='pos_order_line_amount', digits=0, string='Subtotal', store=True),
+ 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits=0, string='Subtotal w/o Tax'),
+ 'price_subtotal_incl': fields.function(_amount_line_all, multi='pos_order_line_amount', digits=0, string='Subtotal'),
'discount': fields.float('Discount (%)', digits=0),
'order_id': fields.many2one('pos.order', 'Order Ref', ondelete='cascade'),
'create_date': fields.datetime('Creation Date', readonly=True),
- 'tax_ids': fields.many2many('account.tax', string='Taxes', readonly=True),
+ 'tax_ids': fields.many2many('account.tax', string='Taxes'),
+ 'tax_ids_after_fiscal_position': fields.function(_get_tax_ids_after_fiscal_position, type='many2many', relation='account.tax', string='Taxes')
}
_defaults = {
diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml
index 8061c6517a2..8db659c0678 100644
--- a/addons/point_of_sale/point_of_sale_view.xml
+++ b/addons/point_of_sale/point_of_sale_view.xml
@@ -29,6 +29,7 @@
+
@@ -38,7 +39,7 @@
-
+
@@ -661,6 +662,7 @@
+
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index 84fc1f42634..429ed55e7c5 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -371,6 +371,40 @@ exports.PosModel = Backbone.Model.extend({
});
},
+ }, {
+ model: 'account.fiscal.position',
+ fields: [],
+ domain: function(self){ return [['id','in',self.config.fiscal_position_ids]]; },
+ loaded: function(self, fiscal_positions){
+ self.fiscal_positions = fiscal_positions;
+ }
+ }, {
+ model: 'account.fiscal.position.tax',
+ fields: [],
+ domain: function(self){
+ var fiscal_position_tax_ids = [];
+
+ self.fiscal_positions.forEach(function (fiscal_position) {
+ fiscal_position.tax_ids.forEach(function (tax_id) {
+ fiscal_position_tax_ids.push(tax_id);
+ });
+ });
+
+ return [['id','in',fiscal_position_tax_ids]];
+ },
+ loaded: function(self, fiscal_position_taxes){
+ self.fiscal_position_taxes = fiscal_position_taxes;
+ self.fiscal_positions.forEach(function (fiscal_position) {
+ fiscal_position.fiscal_position_taxes_by_id = {};
+ fiscal_position.tax_ids.forEach(function (tax_id) {
+ var fiscal_position_tax = _.find(fiscal_position_taxes, function (fiscal_position_tax) {
+ return fiscal_position_tax.id === tax_id;
+ });
+
+ fiscal_position.fiscal_position_taxes_by_id[fiscal_position_tax.id] = fiscal_position_tax;
+ });
+ });
+ }
}, {
label: 'fonts',
loaded: function(){
@@ -1269,6 +1303,22 @@ exports.Orderline = Backbone.Model.extend({
}
return taxes;
},
+ _map_tax_fiscal_position: function(tax) {
+ var current_order = this.pos.get_order();
+ var order_fiscal_position = current_order && current_order.fiscal_position;
+
+ if (order_fiscal_position) {
+ var mapped_tax = _.find(order_fiscal_position.fiscal_position_taxes_by_id, function (fiscal_position_tax) {
+ return fiscal_position_tax.tax_src_id[0] === tax.id;
+ });
+
+ if (mapped_tax) {
+ tax = this.pos.taxes_by_id[mapped_tax.tax_dest_id[0]];
+ }
+ }
+
+ return tax;
+ },
_compute_all: function(tax, base_amount, quantity) {
if (tax.amount_type === 'fixed') {
var ret = tax.amount * quantity;
@@ -1295,12 +1345,13 @@ exports.Orderline = Backbone.Model.extend({
currency_rounding = currency_rounding * 0.00001;
}
_(taxes).each(function(tax) {
+ tax = self._map_tax_fiscal_position(tax);
if (tax.amount_type === 'group'){
var ret = self.compute_all(tax.children_tax_ids, price_unit, quantity, currency_rounding);
total_excluded = ret.total_excluded;
base = ret.total_excluded;
total_included = ret.total_included;
- list_taxes.concat(ret.taxes)
+ list_taxes.concat(ret.taxes);
}
else {
var tax_amount = self._compute_all(tax, price_unit, quantity);
@@ -1321,8 +1372,8 @@ exports.Orderline = Backbone.Model.extend({
id: tax.id,
amount: tax_amount,
name: tax.name,
- }
- list_taxes.push(data)
+ };
+ list_taxes.push(data);
}
}
});
@@ -1540,6 +1591,7 @@ exports.Order = Backbone.Model.extend({
uid: this.uid,
sequence_number: this.sequence_number,
creation_date: this.creation_date,
+ fiscal_position_id: this.fiscal_position ? this.fiscal_position.id : false
};
},
export_for_printing: function(){
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index d074048dca6..c8c2fc0bcbd 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -1908,6 +1908,36 @@ var PaymentScreenWidget = ScreenWidget.extend({
});
gui.define_screen({name:'payment', widget: PaymentScreenWidget});
+var set_fiscal_position_button = ActionButtonWidget.extend({
+ template: 'SetFiscalPositionButton',
+ button_click: function () {
+ var self = this;
+ var selection_list = _.map(self.pos.fiscal_positions, function (fiscal_position) {
+ return {
+ label: fiscal_position.name,
+ item: fiscal_position
+ };
+ });
+ self.gui.show_popup('selection',{
+ title: _t('Select Fiscal Position'),
+ list: selection_list,
+ confirm: function (fiscal_position) {
+ var order = self.pos.get_order();
+ order.fiscal_position = fiscal_position;
+ order.trigger('change');
+ }
+ });
+ },
+});
+
+define_action_button({
+ 'name': 'set_fiscal_position',
+ 'widget': set_fiscal_position_button,
+ 'condition': function(){
+ return this.pos.fiscal_positions.length > 0;
+ },
+});
+
return {
ReceiptScreenWidget: ReceiptScreenWidget,
ActionButtonWidget: ActionButtonWidget,
diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml
index 319966757bb..59e8f63afce 100644
--- a/addons/point_of_sale/static/src/xml/pos.xml
+++ b/addons/point_of_sale/static/src/xml/pos.xml
@@ -100,6 +100,12 @@
+
+
+ Fiscal position
+
+
+