Stefan Rijnhart
9 years ago
4 changed files with 245 additions and 1 deletions
-
1pos_pricelist/README.rst
-
1pos_pricelist/models/__init__.py
-
11pos_pricelist/models/point_of_sale.py
-
233pos_pricelist/models/pos_order_patch.py
@ -0,0 +1,233 @@ |
|||
# coding: utf-8 |
|||
# Copyright: Odoo S.A. |
|||
# License: AGPL-3 |
|||
# flake8: noqa |
|||
from openerp.tools.translate import _ |
|||
|
|||
|
|||
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 |
Write
Preview
Loading…
Cancel
Save
Reference in new issue