diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index b9543ca8453..e133f006f7c 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -158,10 +158,15 @@ class PosOrder(models.Model): '''This method is designed to be inherited in a custom module''' return False - def _create_account_move(self, dt, ref, journal_id, company_id): - date_tz_user = fields.Datetime.context_timestamp(self, fields.Datetime.from_string(dt)) + def _create_account_move(self): + self.ensure_one() + date_tz_user = fields.Datetime.context_timestamp(self, fields.Datetime.from_string(self.session_id.start_at)) date_tz_user = fields.Date.to_string(date_tz_user) - return self.env['account.move'].sudo().create({'ref': ref, 'journal_id': journal_id, 'date': date_tz_user}) + return self.env['account.move'].sudo().create({ + 'ref': self.name, + 'journal_id': self.sale_journal.id, + 'date': date_tz_user + }) def _prepare_invoice(self): """ @@ -243,7 +248,7 @@ class PosOrder(models.Model): inv_line.update(price_unit=line.price_unit, discount=line.discount, name=inv_name) return InvoiceLine.sudo().create(inv_line) - def _create_account_move_line(self, session=None, move=None): + def _prepare_account_move_line(self, line, partner_id, current_company, currency_id, rounding_method): def _flatten_tax_and_children(taxes, group_done=None): children = self.env['account.tax'] if group_done is None: @@ -253,6 +258,79 @@ class PosOrder(models.Model): group_done.add(tax.id) children |= _flatten_tax_and_children(tax.children_tax_ids, group_done) return taxes + children + res = [] + order = line.order_id + cur_company = order.company_id.currency_id + date_order = order.date_order.date() if order.date_order else fields.Date.today() + if currency_id != cur_company: + amount_subtotal = currency_id._convert(line.price_subtotal, cur_company, order.company_id, date_order) + else: + amount_subtotal = line.price_subtotal + + # Search for the income account + if line.product_id.property_account_income_id.id: + income_account = line.product_id.property_account_income_id.id + elif line.product_id.categ_id.property_account_income_categ_id.id: + income_account = line.product_id.categ_id.property_account_income_categ_id.id + else: + raise UserError(_('Please define income ' + 'account for this product: "%s" (id:%d).') + % (line.product_id.name, line.product_id.id)) + + name = line.product_id.name + if line.notice: + # add discount reason in move + name = name + ' (' + line.notice + ')' + + # Create a move for the line for the order line + # Just like for invoices, a group of taxes must be present on this base line + # As well as its children + base_line_tax_ids = _flatten_tax_and_children(line.tax_ids_after_fiscal_position).filtered(lambda tax: tax.type_tax_use in ['sale', 'none']) + data = { + 'name': name, + 'quantity': line.qty, + 'product_id': line.product_id.id, + 'account_id': income_account, + 'analytic_account_id': self._prepare_analytic_account(line), + 'credit': ((amount_subtotal > 0) and amount_subtotal) or 0.0, + 'debit': ((amount_subtotal < 0) and -amount_subtotal) or 0.0, + 'tax_ids': [(6, 0, base_line_tax_ids.ids)], + 'partner_id': partner_id + } + if currency_id != cur_company: + data['currency_id'] = currency_id.id + data['amount_currency'] = -abs(line.price_subtotal) if data.get('credit') else abs(line.price_subtotal) + res.append({'data_type': 'product', 'values': data}) + + # Create the tax lines + taxes = line.tax_ids_after_fiscal_position.filtered(lambda t: t.company_id.id == current_company.id) + if taxes: + price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) + for tax in taxes.compute_all(price, currency_id, line.qty)['taxes']: + if currency_id != cur_company: + round_tax = False if rounding_method == 'round_globally' else True + amount_tax = currency_id._convert(tax['amount'], cur_company, order.company_id, date_order, round=round_tax) + # amount_tax = currency_id.with_context(date=date_order).compute(tax['amount'], cur_company, round=round_tax) + else: + amount_tax = tax['amount'] + data = { + 'name': _('Tax') + ' ' + tax['name'], + 'product_id': line.product_id.id, + 'quantity': line.qty, + 'account_id': tax['account_id'] or income_account, + 'credit': ((amount_tax > 0) and amount_tax) or 0.0, + 'debit': ((amount_tax < 0) and -amount_tax) or 0.0, + 'tax_line_id': tax['id'], + 'partner_id': partner_id, + 'order_id': order.id + } + if currency_id != cur_company: + data['currency_id'] = currency_id.id + data['amount_currency'] = -abs(tax['amount']) if data.get('credit') else abs(tax['amount']) + res.append({'data_type': 'tax', 'values': data}) + return res + + def _create_account_move_line(self, session=None): # 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.""" @@ -300,19 +378,16 @@ class PosOrder(models.Model): 'debit': line2['debit'] or 0.0, 'partner_id': line2['partner_id'] }) - + move = False for order in self.filtered(lambda o: not o.account_move or o.state == 'paid'): current_company = order.sale_journal.company_id account_def = IrProperty.get( 'property_account_receivable_id', 'res.partner') order_account = order.partner_id.property_account_receivable_id.id or account_def and account_def.id partner_id = ResPartner._find_accounting_partner(order.partner_id).id or False - if move is None: + if not move: # Create an entry for the sale - journal_id = self.env['ir.config_parameter'].sudo().get_param( - 'pos.closing.journal_id_%s' % current_company.id, default=order.sale_journal.id) - move = self._create_account_move( - order.session_id.start_at, order.name, int(journal_id), order.company_id.id) + move = order._create_account_move() def insert_data(data_type, values): # if have_to_group_by: @@ -358,77 +433,11 @@ class PosOrder(models.Model): cur = order.pricelist_id.currency_id cur_company = order.company_id.currency_id amount_cur_company = 0.0 - date_order = order.date_order.date() if order.date_order else fields.Date.today() for line in order.lines: - if cur != cur_company: - amount_subtotal = cur._convert(line.price_subtotal, cur_company, order.company_id, date_order) - else: - amount_subtotal = line.price_subtotal - - # Search for the income account - if line.product_id.property_account_income_id.id: - income_account = line.product_id.property_account_income_id.id - elif line.product_id.categ_id.property_account_income_categ_id.id: - income_account = line.product_id.categ_id.property_account_income_categ_id.id - else: - raise UserError(_('Please define income ' - 'account for this product: "%s" (id:%d).') - % (line.product_id.name, line.product_id.id)) - - name = line.product_id.name - if line.notice: - # add discount reason in move - name = name + ' (' + line.notice + ')' - - # Create a move for the line for the order line - # Just like for invoices, a group of taxes must be present on this base line - # As well as its children - base_line_tax_ids = _flatten_tax_and_children(line.tax_ids_after_fiscal_position).filtered(lambda tax: tax.type_tax_use in ['sale', 'none']) - data = { - 'name': name, - 'quantity': line.qty, - 'product_id': line.product_id.id, - 'account_id': income_account, - 'analytic_account_id': self._prepare_analytic_account(line), - 'credit': ((amount_subtotal > 0) and amount_subtotal) or 0.0, - 'debit': ((amount_subtotal < 0) and -amount_subtotal) or 0.0, - 'tax_ids': [(6, 0, base_line_tax_ids.ids)], - 'partner_id': partner_id - } - if cur != cur_company: - data['currency_id'] = cur.id - data['amount_currency'] = -abs(line.price_subtotal) if data.get('credit') else abs(line.price_subtotal) - amount_cur_company += data['credit'] - data['debit'] - insert_data('product', data) - - # Create the tax lines - taxes = line.tax_ids_after_fiscal_position.filtered(lambda t: t.company_id.id == current_company.id) - if not taxes: - continue - price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) - for tax in taxes.compute_all(price, cur, line.qty)['taxes']: + for move_line in self._prepare_account_move_line(line, partner_id, current_company, cur, rounding_method): if cur != cur_company: - round_tax = False if rounding_method == 'round_globally' else True - amount_tax = cur._convert(tax['amount'], cur_company, order.company_id, date_order, round=round_tax) - # amount_tax = cur.with_context(date=date_order).compute(tax['amount'], cur_company, round=round_tax) - else: - amount_tax = tax['amount'] - data = { - 'name': _('Tax') + ' ' + tax['name'], - 'product_id': line.product_id.id, - 'quantity': line.qty, - 'account_id': tax['account_id'] or income_account, - 'credit': ((amount_tax > 0) and amount_tax) or 0.0, - 'debit': ((amount_tax < 0) and -amount_tax) or 0.0, - 'tax_line_id': tax['id'], - 'partner_id': partner_id, - 'order_id': order.id - } - if cur != cur_company: - data['currency_id'] = cur.id - data['amount_currency'] = -abs(tax['amount']) if data.get('credit') else abs(tax['amount']) - amount_cur_company += data['credit'] - data['debit'] - insert_data('tax', data) + amount_cur_company += move_line['values']['credit'] - move_line['values']['debit'] + insert_data(move_line['data_type'], move_line['values']) # round tax lines per order if rounding_method == 'round_globally': diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index aabcb4307d4..f1034572ecc 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -19,15 +19,11 @@ class PosSession(models.Model): def _confirm_orders(self): for session in self: - company_id = session.config_id.journal_id.company_id.id - orders = session.order_ids.filtered(lambda order: order.state == 'paid') - journal_id = self.env['ir.config_parameter'].sudo().get_param( - 'pos.closing.journal_id_%s' % company_id, default=session.config_id.journal_id.id) - if not journal_id: + journal = session.config_id.journal_id + if not journal: raise UserError(_("You have to set a Sale Journal for the POS:%s") % (session.config_id.name,)) - - move = self.env['pos.order'].with_context(force_company=company_id)._create_account_move(session.start_at, session.name, int(journal_id), company_id) - orders.with_context(force_company=company_id)._create_account_move_line(session, move) + orders = session.order_ids.filtered(lambda order: order.state == 'paid') + orders.with_context(force_company=journal.company_id.id)._create_account_move_line(session) for order in session.order_ids.filtered(lambda o: o.state not in ['done', 'invoiced']): if order.state not in ('paid'): raise UserError(