|
@@ -1,237 +0,0 @@
|
|
|
-# -*- coding: utf-8 -*-
|
|
|
-
|
|
|
-from openerp import api, fields, models
|
|
|
-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: Select currency based on selected journal
|
|
|
- journal = self.env['account.journal'].browse(int(values['journal_id']))
|
|
|
- currency_id = journal.default_credit_account_id.currency_id.id or journal.default_credit_account_id.company_currency_id.id
|
|
|
-
|
|
|
- # Step 2: Check product pricelist
|
|
|
- pricelist_model = self.env['product.pricelist']
|
|
|
- pricelist = pricelist_model.search([('active', '=', True), ('type', '=', 'sale')])
|
|
|
-
|
|
|
- if not len([p.id for p in pricelist if p.currency_id.id == currency_id]):
|
|
|
- pricelist = pricelist[0].copy()
|
|
|
- pricelist.write({
|
|
|
- 'currency_id': currency_id
|
|
|
- })
|
|
|
- else:
|
|
|
- pricelist = pricelist[0]
|
|
|
-
|
|
|
- # Step 3: Create sale order and confirm
|
|
|
- sale_order = self.env['sale.order'].create({
|
|
|
- 'partner_id': values.get('customer_id'),
|
|
|
- 'order_line': [[0, False, {
|
|
|
- 'product_id': int(v.get('id')),
|
|
|
- 'product_uom_qty': float(v.get('qty')),
|
|
|
- 'price_unit': float(v.get('price')),
|
|
|
- 'discount': (1.0 - float(v.get('discount'))) * 100,
|
|
|
- }] for v in values.get('cart_items', [])],
|
|
|
- 'picking_policy': 'direct',
|
|
|
- 'state': 'manual',
|
|
|
- 'date_confirm': date_now,
|
|
|
- 'currency_id': currency_id,
|
|
|
- 'pricelist_id': pricelist.id,
|
|
|
- 'payment_term': values.get('payment_term_id')
|
|
|
- })
|
|
|
-
|
|
|
- sale_order.action_button_confirm()
|
|
|
-
|
|
|
- # Step 4: Create invoice and calculate due date
|
|
|
- invoice = self.env['account.invoice'].browse(sale_order.action_invoice_create())
|
|
|
-
|
|
|
-
|
|
|
- due_date = parse(date_now) + rd(days=max(invoice.payment_term.line_ids.mapped(lambda x: x.days + x.days2)))
|
|
|
-
|
|
|
- invoice.write({
|
|
|
- 'currency_id': currency_id,
|
|
|
- 'date_invoice': date_now,
|
|
|
- 'date_due': due_date.strftime(date_format),
|
|
|
- 'state': 'open'
|
|
|
- })
|
|
|
-
|
|
|
- # Step 5: 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()
|
|
|
-
|
|
|
- compute_taxes = self.env['account.invoice.tax'].compute(invoice)
|
|
|
- invoice.check_tax_lines(compute_taxes)
|
|
|
- invoice._recompute_tax_amount()
|
|
|
-
|
|
|
- invoice_move_lines += self.env['account.invoice.tax'].move_line_get(invoice.id)
|
|
|
-
|
|
|
- total, total_currency, invoice_move_lines = invoice.compute_invoice_totals(invoice.company_id.currency_id, invoice.reference, invoice_move_lines)
|
|
|
-
|
|
|
- percent_paid = amount_paid / round(total, decimal_precision)
|
|
|
- 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 and percent_paid < 1:
|
|
|
- total_lines.append([date_now, percent_paid])
|
|
|
- percent_paid = amount_paid = 0
|
|
|
-
|
|
|
- if due_date == date_now and line.value_amount:
|
|
|
- distribute_percent = -((total_lines[0][1] - 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)
|
|
|
-
|
|
|
- if current_price < 0.0:
|
|
|
- continue
|
|
|
-
|
|
|
- amount_paid += current_price
|
|
|
-
|
|
|
- invoice_move_lines.append({
|
|
|
- 'type': 'dest',
|
|
|
- 'name': '/',
|
|
|
- 'price': current_price if total_line[1] else round(total - amount_paid, decimal_precision) or total,
|
|
|
- 'account_id': invoice.account_id.id,
|
|
|
- 'date_maturity': total_line[0],
|
|
|
- '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 = []
|
|
|
-
|
|
|
- # Step 6: Create account move
|
|
|
- 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)
|
|
|
-
|
|
|
- ctx = dict(self._context, lang=invoice.partner_id.lang, company_id=invoice.company_id.id)
|
|
|
- period = invoice.period_id
|
|
|
-
|
|
|
- if not period:
|
|
|
- period = period.with_context(ctx).find(invoice.date_invoice)[:1]
|
|
|
-
|
|
|
- if period:
|
|
|
- for line in move_line_values:
|
|
|
- line[2]['period_id'] = period.id
|
|
|
-
|
|
|
- ctx['invoice'] = invoice
|
|
|
- ctx_nolang = ctx.copy()
|
|
|
- ctx_nolang.pop('lang', None)
|
|
|
-
|
|
|
- account_move = self.env['account.move'].with_context(ctx_nolang).create({
|
|
|
- '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': period.id
|
|
|
- })
|
|
|
-
|
|
|
- invoice.with_context(ctx).write({
|
|
|
- 'move_id': account_move.id,
|
|
|
- 'period_id': account_move.period_id.id,
|
|
|
- 'move_name': account_move.name,
|
|
|
- })
|
|
|
-
|
|
|
- account_move.post()
|
|
|
-
|
|
|
- # Step 7: Write a number for invoice
|
|
|
- invoice.action_number()
|
|
|
-
|
|
|
- # Step 8: Create voucher
|
|
|
- account_voucher = self.create({
|
|
|
- 'reference': account_move.name,
|
|
|
- 'type': 'receipt',
|
|
|
- 'journal_id': int(values['journal_id']),
|
|
|
- 'company_id': account_move.company_id.id,
|
|
|
- 'pre_line': True,
|
|
|
- 'amount': float(values['amount_paid']),
|
|
|
- 'period_id': account_move.period_id.id,
|
|
|
- 'date': account_move.date,
|
|
|
- 'partner_id': account_move.partner_id.id,
|
|
|
- 'account_id': int(values['account_id']),
|
|
|
- 'currency_id': currency_id,
|
|
|
- 'line_cr_ids': [[0, False, {
|
|
|
- 'date_due': l.date_maturity,
|
|
|
- 'account_id': l.account_id.id,
|
|
|
- 'date_original': l.invoice.date_invoice,
|
|
|
- 'move_line_id': l.id,
|
|
|
- 'amount_original': abs(l.credit or l.debit or 0.0),
|
|
|
- 'amount_unreconciled': abs(l.amount_residual),
|
|
|
- 'amount': abs(l.debit) if account_move.date == l.date_maturity else 0.0,
|
|
|
- 'reconcile': account_move.date == l.date_maturity,
|
|
|
- 'currency_id': currency_id
|
|
|
- }] for l in account_move.line_id]
|
|
|
- })
|
|
|
-
|
|
|
- account_voucher.action_move_line_create()
|
|
|
-
|
|
|
- # Step 9: Close a invoice
|
|
|
- if invoice.residual == 0:
|
|
|
- invoice.write({
|
|
|
- 'state': 'paid'
|
|
|
- })
|
|
|
-
|
|
|
-
|
|
|
- # Step 10: Save bank statement
|
|
|
- bank_statement_lines = [[0, False, {
|
|
|
- 'name': account_voucher.reference,
|
|
|
- 'amount': account_voucher.amount,
|
|
|
- 'partner_id': account_voucher.partner_id.id,
|
|
|
- 'voucher_id': account_voucher.id,
|
|
|
- 'journal_id': account_voucher.journal_id.id,
|
|
|
- 'account_id': account_voucher.account_id.id,
|
|
|
- 'journal_entry_id': account_voucher.move_id.id,
|
|
|
- 'currency_id': account_voucher.currency_id.id,
|
|
|
- 'ref': 'POS/' + values.get('payment_reference') or ''
|
|
|
- }]]
|
|
|
-
|
|
|
- account_bank_statement = self.env['account.bank.statement'].search([('journal_id', '=', account_voucher.journal_id.id), ('date', '=', date_now)])
|
|
|
-
|
|
|
- account_bank_statement_values = {
|
|
|
- 'date': date_now,
|
|
|
- 'user_id': self.env.user.id,
|
|
|
- 'journal_id': account_voucher.journal_id.id,
|
|
|
- 'period_id': account_voucher.period_id.id,
|
|
|
- 'line_ids': bank_statement_lines,
|
|
|
- 'state': 'open' if account_voucher.journal_id.type == 'cash' else 'draft'
|
|
|
- }
|
|
|
-
|
|
|
- if account_bank_statement:
|
|
|
- if len(account_bank_statement) == 1:
|
|
|
- account_bank_statement.write(account_bank_statement_values)
|
|
|
- else:
|
|
|
- account_bank_statement[len(account_bank_statement) - 1].write(account_bank_statement_values)
|
|
|
- else:
|
|
|
- account_bank_statement.create(account_bank_statement_values)
|
|
|
-
|
|
|
- # Step 11: Return values
|
|
|
- return {
|
|
|
- 'action_id': self.env['ir.actions.report.xml'].search([('report_name', '=', 'account.report_invoice')]).id,
|
|
|
- 'invoice_id': invoice.id
|
|
|
- }
|
|
|
-
|