mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[REF] Contract: invoice creation
[FIX] - Fix typo [IMP] - date start required for contract line [REF] Gitignore: .eggs
This commit is contained in:
committed by
sbejaoui
parent
1ac40de7a7
commit
a874e94802
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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(
|
return {
|
||||||
{
|
'reference': self.code,
|
||||||
'reference': self.code,
|
'type': invoice_type,
|
||||||
'type': invoice_type,
|
'partner_id': self.partner_id.address_get(['invoice'])[
|
||||||
'partner_id': self.partner_id.address_get(['invoice'])[
|
'invoice'
|
||||||
'invoice'
|
],
|
||||||
],
|
'currency_id': currency.id,
|
||||||
'currency_id': currency.id,
|
'date_invoice': date_invoice,
|
||||||
'date_invoice': date_invoice,
|
'journal_id': journal.id,
|
||||||
'journal_id': journal.id,
|
'origin': self.name,
|
||||||
'origin': self.name,
|
'company_id': self.company_id.id,
|
||||||
'company_id': self.company_id.id,
|
'contract_id': self.id,
|
||||||
'contract_id': self.id,
|
'user_id': self.partner_id.user_id.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)
|
|
||||||
|
|
||||||
@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[
|
invoice_model = self.env['account.invoice']
|
||||||
'account.analytic.invoice.line'
|
invoices_values = []
|
||||||
].recurring_create_invoice(self)
|
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()
|
||||||
|
|||||||
@@ -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
|
@api.multi
|
||||||
def _create_invoice(self):
|
def _prepare_invoice_line(self, invoice_id=False):
|
||||||
"""
|
|
||||||
: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
|
|
||||||
def _prepare_invoice_line(self, invoice_id):
|
|
||||||
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,
|
||||||
|
|||||||
Reference in New Issue
Block a user