account_voucher.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # -*- coding: utf-8 -*-
  2. from openerp import api, fields, models
  3. from openerp.exceptions import except_orm
  4. from datetime import datetime
  5. from dateutil.relativedelta import relativedelta as rd
  6. from dateutil.parser import parse
  7. class AccountVoucher(models.Model):
  8. _inherit = 'account.voucher'
  9. @api.model
  10. def create_from_pos(self, values):
  11. date_now = fields.Date.context_today(self)
  12. date_format = '%Y-%m-%d'
  13. # Step 1: Select currency based on selected journal
  14. journal = self.env['account.journal'].browse(int(values['journal_id']))
  15. currency_id = journal.default_credit_account_id.currency_id.id or journal.default_credit_account_id.company_currency_id.id
  16. # Step 2: Check product pricelist
  17. pricelist_model = self.env['product.pricelist']
  18. pricelist = pricelist_model.search([('active', '=', True), ('type', '=', 'sale')])
  19. if not len([p.id for p in pricelist if p.currency_id.id == currency_id]):
  20. pricelist = pricelist[0].copy()
  21. pricelist.write({
  22. 'currency_id': currency_id
  23. })
  24. else:
  25. pricelist = pricelist[0]
  26. # Step 3: Create sale order and confirm
  27. sale_order = self.env['sale.order'].create({
  28. 'partner_id': int(values['customer_id']),
  29. 'order_line': [[0, False, {
  30. 'product_id': int(v['id']),
  31. 'product_uom_qty': float(v['qty']),
  32. 'price_unit': float(v['price']),
  33. 'state': 'confirmed'
  34. }] for v in values['cart_items']],
  35. 'picking_policy': 'direct',
  36. 'state': 'manual',
  37. 'date_confirm': date_now,
  38. 'currency_id': currency_id,
  39. 'pricelist_id': pricelist.id,
  40. 'payment_term': int(values['payment_term_id'])
  41. })
  42. # Step 4: Create invoice and calculate due date
  43. invoice = self.env['account.invoice'].browse(sale_order.action_invoice_create())
  44. due_date = parse(date_now) + rd(days=max(invoice.payment_term.line_ids.mapped(lambda x: x.days + x.days2)))
  45. invoice.write({
  46. 'currency_id': currency_id,
  47. 'date_invoice': date_now,
  48. 'date_due': due_date.strftime(date_format)
  49. })
  50. # Step 5: Create invoice move lines
  51. amount_paid = float(values['amount_paid'])
  52. decimal_precision = self.env['decimal.precision'].precision_get('Account')
  53. invoice_move_lines = invoice._get_analytic_lines()
  54. compute_taxes = self.env['account.invoice.tax'].compute(invoice)
  55. invoice.check_tax_lines(compute_taxes)
  56. invoice._recompute_tax_amount()
  57. invoice_move_lines += self.env['account.invoice.tax'].move_line_get(invoice.id)
  58. total, total_currency, invoice_move_lines = invoice.compute_invoice_totals(invoice.company_id.currency_id, invoice.reference, invoice_move_lines)
  59. percent_paid = amount_paid / round(total, decimal_precision)
  60. distribute_percent = -(percent_paid / len(invoice.payment_term.line_ids))
  61. total_lines = []
  62. for line in invoice.payment_term.line_ids:
  63. due_date = (parse(date_now) + rd(days=line.days + line.days2)).strftime(date_format)
  64. if percent_paid and percent_paid < 1:
  65. total_lines.append([date_now, percent_paid])
  66. percent_paid = amount_paid = 0
  67. if due_date == date_now and line.value_amount:
  68. distribute_percent = -((total_lines[0][1] - line.value_amount) / (len(invoice.payment_term.line_ids) - 1))
  69. continue
  70. if line.value != 'balance':
  71. total_lines.append([due_date, line.value_amount + distribute_percent])
  72. continue
  73. total_lines.append([due_date, line.value_amount])
  74. for total_line in total_lines:
  75. current_price = round(total * total_line[1], decimal_precision)
  76. if current_price < 0.0:
  77. continue
  78. amount_paid += current_price
  79. invoice_move_lines.append({
  80. 'type': 'dest',
  81. 'name': '/',
  82. 'price': current_price if total_line[1] else round(total - amount_paid, decimal_precision) or total,
  83. 'account_id': invoice.account_id.id,
  84. 'date_maturity': total_line[0],
  85. '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,
  86. 'currency_id': invoice.currency_id != invoice.company_id.currency_id and invoice.currency_id.id,
  87. 'ref': invoice.reference
  88. })
  89. total_lines = []
  90. # Step 6: Create account move
  91. accounting_partner = self.env['res.partner']._find_accounting_partner(invoice.partner_id)
  92. move_line_values = [(0, 0, invoice.line_get_convert(line, accounting_partner.id, invoice.date_invoice)) for line in invoice_move_lines]
  93. move_line_values = invoice.group_lines(invoice_move_lines, move_line_values)
  94. move_line_values = invoice.finalize_invoice_move_lines(move_line_values)
  95. account_move = self.env['account.move'].create({
  96. 'ref': invoice.reference or invoice.name,
  97. 'line_id': move_line_values,
  98. 'journal_id': invoice.journal_id.id,
  99. 'date': invoice.date_invoice,
  100. 'narration': invoice.comment,
  101. 'company_id': invoice.company_id.id,
  102. 'period_id': invoice.period_id.find(invoice.date_invoice).id
  103. })
  104. invoice.write({
  105. 'move_id': account_move.id,
  106. 'period_id': account_move.period_id.id,
  107. 'move_name': account_move.name,
  108. })
  109. account_move.post()
  110. # Step 7: Validate invoice
  111. invoice.action_number()
  112. invoice.write({
  113. 'state': 'open'
  114. })
  115. # Step 8: Create voucher
  116. account_voucher = self.create({
  117. 'reference': account_move.name,
  118. 'type': 'receipt',
  119. 'journal_id': int(values['journal_id']),
  120. 'company_id': account_move.company_id.id,
  121. 'pre_line': True,
  122. 'amount': float(values['amount_paid']),
  123. 'period_id': account_move.period_id.id,
  124. 'date': account_move.date,
  125. 'partner_id': account_move.partner_id.id,
  126. 'account_id': int(values['account_id']),
  127. 'currency_id': currency_id,
  128. 'line_cr_ids': [[0, False, {
  129. 'date_due': l.date_maturity,
  130. 'account_id': l.account_id.id,
  131. 'date_original': l.invoice.date_invoice,
  132. 'move_line_id': l.id,
  133. 'amount_original': abs(l.credit or l.debit or 0.0),
  134. 'amount_unreconciled': abs(l.amount_residual),
  135. 'amount': abs(l.debit) if account_move.date == l.date_maturity else 0.0,
  136. 'reconcile': account_move.date == l.date_maturity,
  137. 'currency_id': currency_id
  138. }] for l in account_move.line_id]
  139. })
  140. account_voucher.action_move_line_create()
  141. return {
  142. 'action_id': self.env['ir.actions.report.xml'].search([('report_name', '=', 'account.report_invoice')]).id,
  143. 'invoice_id': invoice.id
  144. }