You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
12 KiB
236 lines
12 KiB
# coding: utf-8
|
|
# Copyright: Odoo S.A.
|
|
# License: AGPL-3
|
|
# flake8: noqa
|
|
# pylint: skip-file
|
|
from openerp.tools.translate import _
|
|
from openerp import api
|
|
|
|
|
|
@api.cr_uid_ids_context
|
|
def _create_account_move_line(self, cr, uid, ids, session=None, move_id=None, context=None):
|
|
""" Monkeypatch for this method's version on pos.order in the point_of_sale
|
|
module. Only change is to refer to the line's taxes instead of the
|
|
product's taxes (change below is marked with 'pos_pricelist'). Keep in a
|
|
separate file so that it can be excluded from flake8 inspection. """
|
|
if True: # Keep indentation level for reference purposes
|
|
# Tricky, via the workflow, we only have one id in the ids variable
|
|
"""Create a account move line of order grouped by products or not."""
|
|
account_move_obj = self.pool.get('account.move')
|
|
account_period_obj = self.pool.get('account.period')
|
|
account_tax_obj = self.pool.get('account.tax')
|
|
property_obj = self.pool.get('ir.property')
|
|
cur_obj = self.pool.get('res.currency')
|
|
|
|
#session_ids = set(order.session_id for order in self.browse(cr, uid, ids, context=context))
|
|
|
|
if session and not all(session.id == order.session_id.id for order in self.browse(cr, uid, ids, context=context)):
|
|
raise osv.except_osv(_('Error!'), _('Selected orders do not have the same session!'))
|
|
|
|
grouped_data = {}
|
|
have_to_group_by = session and session.config_id.group_by or False
|
|
|
|
def compute_tax(amount, tax, line):
|
|
if amount > 0:
|
|
tax_code_id = tax['base_code_id']
|
|
tax_amount = line.price_subtotal * tax['base_sign']
|
|
else:
|
|
tax_code_id = tax['ref_base_code_id']
|
|
tax_amount = abs(line.price_subtotal) * tax['ref_base_sign']
|
|
|
|
return (tax_code_id, tax_amount,)
|
|
|
|
for order in self.browse(cr, uid, ids, context=context):
|
|
if order.account_move:
|
|
continue
|
|
if order.state != 'paid':
|
|
continue
|
|
|
|
current_company = order.sale_journal.company_id
|
|
|
|
group_tax = {}
|
|
account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
|
|
|
|
order_account = order.partner_id and \
|
|
order.partner_id.property_account_receivable and \
|
|
order.partner_id.property_account_receivable.id or \
|
|
account_def and account_def.id
|
|
|
|
if move_id is None:
|
|
# Create an entry for the sale
|
|
move_id = self._create_account_move(cr, uid, order.session_id.start_at, order.name, order.sale_journal.id, order.company_id.id, context=context)
|
|
|
|
move = account_move_obj.browse(cr, uid, move_id, context=context)
|
|
|
|
def insert_data(data_type, values):
|
|
# if have_to_group_by:
|
|
|
|
sale_journal_id = order.sale_journal.id
|
|
|
|
# 'quantity': line.qty,
|
|
# 'product_id': line.product_id.id,
|
|
values.update({
|
|
'date': order.date_order[:10],
|
|
'ref': order.name,
|
|
'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False,
|
|
'journal_id' : sale_journal_id,
|
|
'period_id': move.period_id.id,
|
|
'move_id' : move_id,
|
|
'company_id': current_company.id,
|
|
})
|
|
|
|
if data_type == 'product':
|
|
key = ('product', values['partner_id'], values['product_id'], values['analytic_account_id'], values['debit'] > 0)
|
|
elif data_type == 'tax':
|
|
key = ('tax', values['partner_id'], values['tax_code_id'], values['debit'] > 0)
|
|
elif data_type == 'counter_part':
|
|
key = ('counter_part', values['partner_id'], values['account_id'], values['debit'] > 0)
|
|
else:
|
|
return
|
|
|
|
grouped_data.setdefault(key, [])
|
|
|
|
# if not have_to_group_by or (not grouped_data[key]):
|
|
# grouped_data[key].append(values)
|
|
# else:
|
|
# pass
|
|
|
|
if have_to_group_by:
|
|
if not grouped_data[key]:
|
|
grouped_data[key].append(values)
|
|
else:
|
|
for line in grouped_data[key]:
|
|
if line.get('tax_code_id') == values.get('tax_code_id'):
|
|
current_value = line
|
|
current_value['quantity'] = current_value.get('quantity', 0.0) + values.get('quantity', 0.0)
|
|
current_value['credit'] = current_value.get('credit', 0.0) + values.get('credit', 0.0)
|
|
current_value['debit'] = current_value.get('debit', 0.0) + values.get('debit', 0.0)
|
|
current_value['tax_amount'] = current_value.get('tax_amount', 0.0) + values.get('tax_amount', 0.0)
|
|
break
|
|
else:
|
|
grouped_data[key].append(values)
|
|
else:
|
|
grouped_data[key].append(values)
|
|
|
|
#because of the weird way the pos order is written, we need to make sure there is at least one line,
|
|
#because just after the 'for' loop there are references to 'line' and 'income_account' variables (that
|
|
#are set inside the for loop)
|
|
#TOFIX: a deep refactoring of this method (and class!) is needed in order to get rid of this stupid hack
|
|
assert order.lines, _('The POS order must have lines when calling this method')
|
|
# Create an move for each order line
|
|
|
|
cur = order.pricelist_id.currency_id
|
|
round_per_line = True
|
|
if order.company_id.tax_calculation_rounding_method == 'round_globally':
|
|
round_per_line = False
|
|
for line in order.lines:
|
|
tax_amount = 0
|
|
taxes = []
|
|
# [pos_pricelist] Only change in the next line:
|
|
# for t in line.product_id.taxes_id:
|
|
for t in line.tax_ids if 'tax_ids' in line._fields else line.product_id.taxes_id:
|
|
if t.company_id.id == current_company.id:
|
|
taxes.append(t)
|
|
computed_taxes = account_tax_obj.compute_all(cr, uid, taxes, line.price_unit * (100.0-line.discount) / 100.0, line.qty)['taxes']
|
|
|
|
for tax in computed_taxes:
|
|
tax_amount += cur_obj.round(cr, uid, cur, tax['amount']) if round_per_line else tax['amount']
|
|
if tax_amount < 0:
|
|
group_key = (tax['ref_tax_code_id'], tax['base_code_id'], tax['account_collected_id'], tax['id'])
|
|
else:
|
|
group_key = (tax['tax_code_id'], tax['base_code_id'], tax['account_collected_id'], tax['id'])
|
|
|
|
group_tax.setdefault(group_key, 0)
|
|
group_tax[group_key] += cur_obj.round(cr, uid, cur, tax['amount']) if round_per_line else tax['amount']
|
|
|
|
amount = line.price_subtotal
|
|
|
|
# Search for the income account
|
|
if line.product_id.property_account_income.id:
|
|
income_account = line.product_id.property_account_income.id
|
|
elif line.product_id.categ_id.property_account_income_categ.id:
|
|
income_account = line.product_id.categ_id.property_account_income_categ.id
|
|
else:
|
|
raise osv.except_osv(_('Error!'), _('Please define income '\
|
|
'account for this product: "%s" (id:%d).') \
|
|
% (line.product_id.name, line.product_id.id, ))
|
|
|
|
# Empty the tax list as long as there is no tax code:
|
|
tax_code_id = False
|
|
tax_amount = 0
|
|
while computed_taxes:
|
|
tax = computed_taxes.pop(0)
|
|
tax_code_id, tax_amount = compute_tax(amount, tax, line)
|
|
|
|
# If there is one we stop
|
|
if tax_code_id:
|
|
break
|
|
|
|
# Create a move for the line
|
|
insert_data('product', {
|
|
'name': line.product_id.name,
|
|
'quantity': line.qty,
|
|
'product_id': line.product_id.id,
|
|
'account_id': income_account,
|
|
'analytic_account_id': self._prepare_analytic_account(cr, uid, line, context=context),
|
|
'credit': ((amount>0) and amount) or 0.0,
|
|
'debit': ((amount<0) and -amount) or 0.0,
|
|
'tax_code_id': tax_code_id,
|
|
'tax_amount': tax_amount,
|
|
'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False
|
|
})
|
|
|
|
# For each remaining tax with a code, whe create a move line
|
|
for tax in computed_taxes:
|
|
tax_code_id, tax_amount = compute_tax(amount, tax, line)
|
|
if not tax_code_id:
|
|
continue
|
|
|
|
insert_data('tax', {
|
|
'name': _('Tax'),
|
|
'product_id':line.product_id.id,
|
|
'quantity': line.qty,
|
|
'account_id': income_account,
|
|
'credit': 0.0,
|
|
'debit': 0.0,
|
|
'tax_code_id': tax_code_id,
|
|
'tax_amount': tax_amount,
|
|
'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False
|
|
})
|
|
|
|
# Create a move for each tax group
|
|
(tax_code_pos, base_code_pos, account_pos, tax_id)= (0, 1, 2, 3)
|
|
|
|
for key, tax_amount in group_tax.items():
|
|
tax = self.pool.get('account.tax').browse(cr, uid, key[tax_id], context=context)
|
|
insert_data('tax', {
|
|
'name': _('Tax') + ' ' + tax.name,
|
|
'quantity': line.qty,
|
|
'product_id': line.product_id.id,
|
|
'account_id': key[account_pos] or income_account,
|
|
'credit': ((tax_amount>0) and tax_amount) or 0.0,
|
|
'debit': ((tax_amount<0) and -tax_amount) or 0.0,
|
|
'tax_code_id': key[tax_code_pos],
|
|
'tax_amount': abs(tax_amount) * tax.tax_sign if tax_amount>=0 else abs(tax_amount) * tax.ref_tax_sign,
|
|
'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False
|
|
})
|
|
|
|
# counterpart
|
|
insert_data('counter_part', {
|
|
'name': _("Trade Receivables"), #order.name,
|
|
'account_id': order_account,
|
|
'credit': ((order.amount_total < 0) and -order.amount_total) or 0.0,
|
|
'debit': ((order.amount_total > 0) and order.amount_total) or 0.0,
|
|
'partner_id': order.partner_id and self.pool.get("res.partner")._find_accounting_partner(order.partner_id).id or False
|
|
})
|
|
|
|
order.write({'state':'done', 'account_move': move_id})
|
|
|
|
all_lines = []
|
|
for group_key, group_data in grouped_data.iteritems():
|
|
for value in group_data:
|
|
all_lines.append((0, 0, value),)
|
|
if move_id: #In case no order was changed
|
|
self.pool.get("account.move").write(cr, uid, [move_id], {'line_id':all_lines}, context=context)
|
|
|
|
return True
|