# -*- coding: utf-8 -*- from openerp import api, fields, models, cli from openerp.exceptions import except_orm from datetime import datetime from dateutil.relativedelta import relativedelta as rd from dateutil.parser import parse class AccountVoucher(models.Model): _inherit = 'account.voucher' @api.model def create_from_pos(self, values): date_now = fields.Date.context_today(self) date_format = '%Y-%m-%d' # Step 1: Create Sale Order and Confirm sale_order_line_values = [ [0, False, { 'product_id': int(item['id']), 'product_uom_qty': float(item['qty']), 'price_unit': float(item['price']) , 'state': 'confirmed' }] for item in values['cart_items']] sale_order_values = { 'partner_id': int(values['customer_id']), 'order_line': sale_order_line_values, 'picking_policy': 'direct', 'state': 'manual', 'date_confirm': date_now, 'payment_term': 5 } sale_order = self.env['sale.order'].create(sale_order_values) # Step 2: Create innvoice and calculate due_date invoice_id = sale_order.action_invoice_create() invoice = self.env['account.invoice'].browse(invoice_id) due_date = parse(date_now) + rd(days=max(invoice.payment_term.line_ids.mapped(lambda x: x.days + x.days2))) invoice.write({ 'date_invoice': date_now, 'date_due': due_date.strftime(date_format) }) # Step 3: Create invoice move lines amount_paid = float(values['amount_paid']) decimal_precision = self.env['decimal.precision'].precision_get('Account') invoice_move_lines = invoice._get_analytic_lines() + self.env['account.invoice.tax'].move_line_get(invoice_id) compute_taxes = self.env['account.invoice.tax'].compute(invoice) invoice.check_tax_lines(compute_taxes) total, total_currency, invoice_move_lines = invoice.compute_invoice_totals(invoice.company_id.currency_id, invoice.reference, invoice_move_lines) percent_paid = amount_paid / total distribute_percent = -(percent_paid / len(invoice.payment_term.line_ids)) total_lines = [] for line in invoice.payment_term.line_ids: due_date = (parse(date_now) + rd(days=line.days + line.days2)).strftime(date_format) if percent_paid: total_lines.append([date_now, percent_paid]) percent_paid = amount_paid = 0 if date_format == date_now: distribute_percent = -((total_lines[0] - line.value_amount) / (len(invoice.payment_term.line_ids) - 1)) continue if line.value != 'balance': total_lines.append([due_date, line.value_amount + distribute_percent]) continue total_lines.append([due_date, line.value_amount]) for total_line in total_lines: current_price = round(total * total_line[1], decimal_precision) amount_paid += current_price invoice_move_lines.append({ 'type': 'dest', 'name': '/', 'price': current_price if total_line[1] else total - amount_paid, 'account_id': invoice.account_id.id, 'date_maturity': invoice.date_due, 'amount_currency': invoice.company_id.currency_id.compute(total_line[1], invoice.currency_id) if invoice.currency_id != invoice.company_id.currency_id else False, 'currency_id': invoice.currency_id != invoice.company_id.currency_id and invoice.currency_id.id, 'ref': invoice.reference }) total_lines = [] accounting_partner = self.env['res.partner']._find_accounting_partner(invoice.partner_id) move_line_values = [(0, 0, invoice.line_get_convert(line, accounting_partner.id, invoice.date_invoice)) for line in invoice_move_lines] move_line_values = invoice.group_lines(invoice_move_lines, move_line_values) move_line_values = invoice.finalize_invoice_move_lines(move_line_values) move_values = { 'ref': invoice.reference or invoice.name, 'line_id': move_line_values, 'journal_id': invoice.journal_id.id, 'date': invoice.date_invoice, 'narration': invoice.comment, 'company_id': invoice.company_id.id, 'period_id': invoice.period_id.find(invoice.date_invoice).id } account_move = self.env['account.move'].create(move_values) invoice.write({ 'move_id': account_move.id, 'period_id': account_move.period_id.id, 'move_name': account_move.name, }) account_move.post() # Step 4: Validate invoice invoice.action_number() invoice.write({ 'state': 'open' }) # Step 5: Pay Invoice