Browse Source

[REF] Contract: invoice creation

[FIX] - Fix typo

[IMP] - date start required for contract line

[REF] Gitignore: .eggs
pull/207/head
Thomas Binsfeld 6 years ago
committed by sbejaoui
parent
commit
a874e94802
  1. 1
      .gitignore
  2. 8
      contract/models/account_invoice.py
  3. 90
      contract/models/contract.py
  4. 66
      contract/models/contract_line.py

1
.gitignore

@ -21,6 +21,7 @@ var/
*.egg-info/ *.egg-info/
.installed.cfg .installed.cfg
*.egg *.egg
*.eggs
# Installer logs # Installer logs
pip-log.txt pip-log.txt

8
contract/models/account_invoice.py

@ -1,7 +1,7 @@
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> # © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo import api, fields, models
class AccountInvoice(models.Model): class AccountInvoice(models.Model):
@ -10,3 +10,9 @@ class AccountInvoice(models.Model):
contract_id = fields.Many2one( contract_id = fields.Many2one(
'account.analytic.account', string='Contract' 'account.analytic.account', string='Contract'
) )
@api.multi
def finalize_creation_from_contract(self):
for invoice in self:
invoice._onchange_partner_id()
self.compute_taxes()

90
contract/models/contract.py

@ -173,25 +173,20 @@ class AccountAnalyticAccount(models.Model):
invoice_type = 'out_invoice' invoice_type = 'out_invoice'
if self.contract_type == 'purchase': if self.contract_type == 'purchase':
invoice_type = 'in_invoice' invoice_type = 'in_invoice'
invoice = self.env['account.invoice'].new(
{
'reference': self.code,
'type': invoice_type,
'partner_id': self.partner_id.address_get(['invoice'])[
'invoice'
],
'currency_id': currency.id,
'date_invoice': date_invoice,
'journal_id': journal.id,
'origin': self.name,
'company_id': self.company_id.id,
'contract_id': self.id,
'user_id': self.partner_id.user_id.id,
}
)
# Get other invoice values from partner onchange
invoice._onchange_partner_id()
return invoice._convert_to_write(invoice._cache)
return {
'reference': self.code,
'type': invoice_type,
'partner_id': self.partner_id.address_get(['invoice'])[
'invoice'
],
'currency_id': currency.id,
'date_invoice': date_invoice,
'journal_id': journal.id,
'origin': self.name,
'company_id': self.company_id.id,
'contract_id': self.id,
'user_id': self.partner_id.user_id.id,
}
@api.multi @api.multi
def action_contract_send(self): def action_contract_send(self):
@ -217,12 +212,61 @@ class AccountAnalyticAccount(models.Model):
'context': ctx, 'context': ctx,
} }
@api.model
def _get_recurring_create_invoice_domain(self, contract=False):
domain = []
date_ref = fields.Date.context_today(self)
if contract:
contract.ensure_one()
date_ref = contract.recurring_next_date
domain.append(('id', '=', contract.id))
domain.extend(
[
('recurring_invoices', '=', True),
('recurring_next_date', '<=', date_ref),
]
)
return domain
@api.multi
def _get_lines_to_invoice(self, date_ref=False):
self.ensure_one()
if not date_ref:
date_ref = fields.Date.context_today(self)
return self.recurring_invoice_line_ids.filtered(
lambda l: not l.is_canceled and l.recurring_next_date <= date_ref)
@api.multi @api.multi
def recurring_create_invoice(self): def recurring_create_invoice(self):
return self.env[
'account.analytic.invoice.line'
].recurring_create_invoice(self)
invoice_model = self.env['account.invoice']
invoices_values = []
for contract in self:
contract_lines = contract._get_lines_to_invoice()
if not contract_lines:
continue
invoice_values = contract._prepare_invoice(
contract.recurring_next_date)
for line in contract_lines:
invoice_values.setdefault('invoice_line_ids', [])
invoice_values['invoice_line_ids'].append(
(0, 0, line._prepare_invoice_line(False))
)
# If no account on the product, the invoice lines account is
# taken from the invoice's journal in _onchange_product_id
# This code is not in finalize_creation_from_contract because it's
# not possible to create an invoice line with no account
new_invoice = invoice_model.new(invoice_values)
for invoice_line in new_invoice.invoice_line_ids:
invoice_line.invoice_id = new_invoice
invoice_line._onchange_product_id()
invoice_values = new_invoice._convert_to_write(new_invoice._cache)
invoices_values.append(invoice_values)
contract_lines._update_recurring_next_date()
invoices = invoice_model.create(invoices_values)
invoices.finalize_creation_from_contract()
@api.model @api.model
def cron_recurring_create_invoice(self): def cron_recurring_create_invoice(self):
self.env['account.analytic.invoice.line'].recurring_create_invoice()
domain = self._get_recurring_create_invoice_domain()
contracts_to_invoice = self.search(domain)
contracts_to_invoice.recurring_create_invoice()

66
contract/models/contract_line.py

@ -24,6 +24,7 @@ class AccountAnalyticInvoiceLine(models.Model):
) )
date_start = fields.Date( date_start = fields.Date(
string='Date Start', string='Date Start',
required=True,
default=lambda self: fields.Date.context_today(self), default=lambda self: fields.Date.context_today(self),
) )
date_end = fields.Date(string='Date End', index=True) date_end = fields.Date(string='Date End', index=True)
@ -78,7 +79,10 @@ class AccountAnalyticInvoiceLine(models.Model):
compute="_compute_state", compute="_compute_state",
) )
active = fields.Boolean( active = fields.Boolean(
string="Active", related="contract_id.active", strore=True
string="Active",
related="contract_id.active",
store=True,
readonly=True,
) )
@api.multi @api.multi
@ -312,69 +316,11 @@ class AccountAnalyticInvoiceLine(models.Model):
rec.recurring_next_date rec.recurring_next_date
) )
@api.model
def _get_recurring_create_invoice_domain(self, contract=False):
domain = []
date_ref = fields.Date.context_today(self)
if contract:
contract.ensure_one()
date_ref = contract.recurring_next_date
domain.append(('contract_id', '=', contract.id))
domain.extend(
[
('contract_id.recurring_invoices', '=', True),
('recurring_next_date', '<=', date_ref),
('is_canceled', '=', False),
]
)
return domain
@api.model
def recurring_create_invoice(self, contract=False):
domain = self._get_recurring_create_invoice_domain(contract)
contract_to_invoice = self.read_group(
domain, ['id', 'contract_id'], ['contract_id']
)
return self._recurring_create_invoice(contract_to_invoice)
@api.model
def _recurring_create_invoice(self, contract_to_invoice):
"""Create invoices from contracts
:return: invoices created
"""
invoices = self.env['account.invoice']
for contract in contract_to_invoice:
lines = self.search(contract['__domain'])
if lines:
invoices |= lines._create_invoice()
lines._update_recurring_next_date()
return invoices
@api.multi
def _create_invoice(self):
"""
:return: invoice created
"""
contract = self.mapped('contract_id')
date_invoice = min(self.mapped('recurring_next_date'))
invoice = self.env['account.invoice'].create(
contract._prepare_invoice(date_invoice)
)
for line in self:
invoice_line_vals = line._prepare_invoice_line(invoice.id)
if invoice_line_vals:
self.env['account.invoice.line'].create(invoice_line_vals)
invoice.compute_taxes()
return invoice
@api.multi @api.multi
def _prepare_invoice_line(self, invoice_id):
def _prepare_invoice_line(self, invoice_id=False):
self.ensure_one() self.ensure_one()
invoice_line = self.env['account.invoice.line'].new( invoice_line = self.env['account.invoice.line'].new(
{ {
'invoice_id': invoice_id,
'product_id': self.product_id.id, 'product_id': self.product_id.id,
'quantity': self.quantity, 'quantity': self.quantity,
'uom_id': self.uom_id.id, 'uom_id': self.uom_id.id,

Loading…
Cancel
Save