2
0

pre-commit

This commit is contained in:
Andrea 2020-09-07 14:17:04 +02:00 committed by Andrea Stirpe
parent d36c50c766
commit 702444752b
22 changed files with 1895 additions and 1458 deletions

View File

@ -11,9 +11,7 @@
"license": "AGPL-3", "license": "AGPL-3",
"website": "https://github.com/OCA/account-financial-tools/", "website": "https://github.com/OCA/account-financial-tools/",
"category": "Accounting & Finance", "category": "Accounting & Finance",
"depends": [ "depends": ["account",],
"account",
],
"data": [ "data": [
"security/ir.model.access.csv", "security/ir.model.access.csv",
"security/account_spread_security.xml", "security/account_spread_security.xml",

View File

@ -1,17 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1"> <odoo noupdate="1">
<record id="ir_cron_spread_create_entries" forcecreate="True" model="ir.cron"> <record id="ir_cron_spread_create_entries" forcecreate="True" model="ir.cron">
<field name="name">Cost/revenue Spread: Create Entries</field> <field name="name">Cost/revenue Spread: Create Entries</field>
<field name="active" eval="True"/> <field name="active" eval="True" />
<field name="user_id" ref="base.user_root"/> <field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field> <field name="interval_number">1</field>
<field name="interval_type">days</field> <field name="interval_type">days</field>
<field name="numbercall">-1</field> <field name="numbercall">-1</field>
<field name="doall" eval="False"/> <field name="doall" eval="False" />
<field name="model_id" ref="model_account_spread_line"/> <field name="model_id" ref="model_account_spread_line" />
<field name="state">code</field> <field name="state">code</field>
<field name="code">model._create_entries()</field> <field name="code">model._create_entries()</field>
</record> </record>
</odoo> </odoo>

View File

@ -5,7 +5,7 @@ from odoo import api, models
class AccountInvoice(models.Model): class AccountInvoice(models.Model):
_inherit = 'account.invoice' _inherit = "account.invoice"
def action_invoice_open(self): def action_invoice_open(self):
for invoice in self: for invoice in self:
@ -16,7 +16,7 @@ class AccountInvoice(models.Model):
def action_move_create(self): def action_move_create(self):
"""Invoked when validating the invoices.""" """Invoked when validating the invoices."""
res = super().action_move_create() res = super().action_move_create()
spreads = self.mapped('invoice_line_ids.spread_id') spreads = self.mapped("invoice_line_ids.spread_id")
spreads.compute_spread_board() spreads.compute_spread_board()
spreads.reconcile_spread_moves() spreads.reconcile_spread_moves()
return res return res
@ -26,14 +26,14 @@ class AccountInvoice(models.Model):
"""Copying expense/revenue account from spread to move lines.""" """Copying expense/revenue account from spread to move lines."""
res = super().invoice_line_move_line_get() res = super().invoice_line_move_line_get()
for line in res: for line in res:
invl_id = line.get('invl_id') invl_id = line.get("invl_id")
invl = self.env['account.invoice.line'].browse(invl_id) invl = self.env["account.invoice.line"].browse(invl_id)
if invl.spread_id: if invl.spread_id:
if invl.invoice_id.type in ('out_invoice', 'in_refund'): if invl.invoice_id.type in ("out_invoice", "in_refund"):
account = invl.spread_id.debit_account_id account = invl.spread_id.debit_account_id
else: else:
account = invl.spread_id.credit_account_id account = invl.spread_id.credit_account_id
line['account_id'] = account.id line["account_id"] = account.id
return res return res
@api.multi @api.multi
@ -41,8 +41,8 @@ class AccountInvoice(models.Model):
"""Cancel the spread lines and their related moves when """Cancel the spread lines and their related moves when
the invoice is canceled.""" the invoice is canceled."""
res = super().action_cancel() res = super().action_cancel()
spread_lines = self.mapped('invoice_line_ids.spread_id.line_ids') spread_lines = self.mapped("invoice_line_ids.spread_id.line_ids")
moves = spread_lines.mapped('move_id') moves = spread_lines.mapped("move_id")
moves.button_cancel() moves.button_cancel()
moves.unlink() moves.unlink()
spread_lines.unlink() spread_lines.unlink()
@ -53,7 +53,7 @@ class AccountInvoice(models.Model):
result = super()._refund_cleanup_lines(lines) result = super()._refund_cleanup_lines(lines)
for i, line in enumerate(lines): for i, line in enumerate(lines):
for name in line._fields.keys(): for name in line._fields.keys():
if name == 'spread_id': if name == "spread_id":
result[i][2][name] = False result[i][2][name] = False
break break
return result return result

View File

@ -6,27 +6,27 @@ from odoo.exceptions import UserError
class AccountInvoiceLine(models.Model): class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line' _inherit = "account.invoice.line"
spread_id = fields.Many2one( spread_id = fields.Many2one("account.spread", string="Spread Board", copy=False)
'account.spread', spread_check = fields.Selection(
string='Spread Board', [
copy=False) ("linked", "Linked"),
spread_check = fields.Selection([ ("unlinked", "Unlinked"),
('linked', 'Linked'), ("unavailable", "Unavailable"),
('unlinked', 'Unlinked'), ],
('unavailable', 'Unavailable') compute="_compute_spread_check",
], compute='_compute_spread_check') )
@api.depends('spread_id', 'invoice_id.state') @api.depends("spread_id", "invoice_id.state")
def _compute_spread_check(self): def _compute_spread_check(self):
for line in self: for line in self:
if line.spread_id: if line.spread_id:
line.spread_check = 'linked' line.spread_check = "linked"
elif line.invoice_id.state == 'draft': elif line.invoice_id.state == "draft":
line.spread_check = 'unlinked' line.spread_check = "unlinked"
else: else:
line.spread_check = 'unavailable' line.spread_check = "unavailable"
@api.multi @api.multi
def spread_details(self): def spread_details(self):
@ -38,14 +38,14 @@ class AccountInvoiceLine(models.Model):
if self.spread_id: if self.spread_id:
return { return {
'name': _('Spread Details'), "name": _("Spread Details"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.spread', "res_model": "account.spread",
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'target': 'current', "target": "current",
'readonly': False, "readonly": False,
'res_id': self.spread_id.id, "res_id": self.spread_id.id,
} }
# In case no spread board is linked to the invoice line # In case no spread board is linked to the invoice line
@ -58,13 +58,13 @@ class AccountInvoiceLine(models.Model):
allow_spread_planning=company.allow_spread_planning, allow_spread_planning=company.allow_spread_planning,
) )
return { return {
'name': _('Link Invoice Line with Spread Board'), "name": _("Link Invoice Line with Spread Board"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.spread.invoice.line.link.wizard', "res_model": "account.spread.invoice.line.link.wizard",
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'target': 'new', "target": "new",
'context': ctx, "context": ctx,
} }
def create_auto_spread(self): def create_auto_spread(self):
@ -76,33 +76,46 @@ class AccountInvoiceLine(models.Model):
return False return False
if aline.account_id and iline.account_id != aline.account_id: if aline.account_id and iline.account_id != aline.account_id:
return False return False
if aline.analytic_account_id and \ if (
iline.account_analytic_id != aline.analytic_account_id: aline.analytic_account_id
and iline.account_analytic_id != aline.analytic_account_id
):
return False return False
return True return True
for line in self: for line in self:
if line.spread_check == 'linked': if line.spread_check == "linked":
continue continue
spread_type = ( spread_type = (
'sale' if line.invoice_type in ['out_invoice', 'out_refund'] "sale"
else 'purchase') if line.invoice_type in ["out_invoice", "out_refund"]
spread_auto = self.env['account.spread.template.auto'].search( else "purchase"
[('template_id.auto_spread', '=', True), )
('template_id.spread_type', '=', spread_type)]) spread_auto = self.env["account.spread.template.auto"].search(
[
("template_id.auto_spread", "=", True),
("template_id.spread_type", "=", spread_type),
]
)
matched = spread_auto.filtered(lambda a, i=line: _filter_line(a, i)) matched = spread_auto.filtered(lambda a, i=line: _filter_line(a, i))
template = matched.mapped('template_id') template = matched.mapped("template_id")
if not template: if not template:
continue continue
elif len(template) > 1: elif len(template) > 1:
raise UserError( raise UserError(
_('Too many auto spread templates (%s) matched with the ' _(
'invoice line, %s') % (len(template), line.display_name)) "Too many auto spread templates (%s) matched with the "
"invoice line, %s"
)
% (len(template), line.display_name)
)
# Found auto spread template for this invoice line, create it # Found auto spread template for this invoice line, create it
wizard = self.env['account.spread.invoice.line.link.wizard'].new({ wizard = self.env["account.spread.invoice.line.link.wizard"].new(
'invoice_line_id': line.id, {
'company_id': line.company_id.id, "invoice_line_id": line.id,
'spread_action_type': 'template', "company_id": line.company_id.id,
'template_id': template.id, "spread_action_type": "template",
}) "template_id": template.id,
}
)
wizard.confirm() wizard.confirm()

View File

@ -7,154 +7,145 @@ import time
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_is_zero from odoo.tools import float_is_zero
from odoo.addons import decimal_precision as dp
class AccountSpread(models.Model): class AccountSpread(models.Model):
_name = 'account.spread' _name = "account.spread"
_description = 'Account Spread' _description = "Account Spread"
_inherit = ['mail.thread'] _inherit = ["mail.thread"]
name = fields.Char(required=True) name = fields.Char(required=True)
template_id = fields.Many2one( template_id = fields.Many2one("account.spread.template", string="Spread Template")
'account.spread.template', invoice_type = fields.Selection(
string='Spread Template') [
invoice_type = fields.Selection([ ("out_invoice", "Customer Invoice"),
('out_invoice', 'Customer Invoice'), ("in_invoice", "Vendor Bill"),
('in_invoice', 'Vendor Bill'), ("out_refund", "Customer Credit Note"),
('out_refund', 'Customer Credit Note'), ("in_refund", "Vendor Credit Note"),
('in_refund', 'Vendor Credit Note')], ],
required=True) required=True,
spread_type = fields.Selection([ )
('sale', 'Customer'), spread_type = fields.Selection(
('purchase', 'Supplier')], [("sale", "Customer"), ("purchase", "Supplier")],
compute='_compute_spread_type', compute="_compute_spread_type",
required=True) required=True,
)
period_number = fields.Integer( period_number = fields.Integer(
string='Number of Repetitions', string="Number of Repetitions",
default=12, default=12,
help="Define the number of spread lines", help="Define the number of spread lines",
required=True) required=True,
period_type = fields.Selection([
('month', 'Month'),
('quarter', 'Quarter'),
('year', 'Year')],
default='month',
help="Period length for the entries",
required=True)
use_invoice_line_account = fields.Boolean(
string="Use invoice line's account",
) )
period_type = fields.Selection(
[("month", "Month"), ("quarter", "Quarter"), ("year", "Year")],
default="month",
help="Period length for the entries",
required=True,
)
use_invoice_line_account = fields.Boolean(string="Use invoice line's account",)
credit_account_id = fields.Many2one( credit_account_id = fields.Many2one(
'account.account', "account.account", string="Credit Account", required=True
string='Credit Account', )
required=True)
debit_account_id = fields.Many2one( debit_account_id = fields.Many2one(
'account.account', "account.account", string="Debit Account", required=True
string='Debit Account', )
required=True)
is_credit_account_deprecated = fields.Boolean( is_credit_account_deprecated = fields.Boolean(
compute='_compute_deprecated_accounts') compute="_compute_deprecated_accounts"
is_debit_account_deprecated = fields.Boolean( )
compute='_compute_deprecated_accounts') is_debit_account_deprecated = fields.Boolean(compute="_compute_deprecated_accounts")
unspread_amount = fields.Float( unspread_amount = fields.Float(
digits=dp.get_precision('Account'), digits=dp.get_precision("Account"), compute="_compute_amounts"
compute='_compute_amounts') )
unposted_amount = fields.Float( unposted_amount = fields.Float(
digits=dp.get_precision('Account'), digits=dp.get_precision("Account"), compute="_compute_amounts"
compute='_compute_amounts') )
posted_amount = fields.Float( posted_amount = fields.Float(
digits=dp.get_precision('Account'), digits=dp.get_precision("Account"), compute="_compute_amounts"
compute='_compute_amounts') )
total_amount = fields.Float( total_amount = fields.Float(
digits=dp.get_precision('Account'), digits=dp.get_precision("Account"), compute="_compute_amounts"
compute='_compute_amounts') )
all_posted = fields.Boolean( all_posted = fields.Boolean(compute="_compute_amounts", store=True)
compute='_compute_amounts',
store=True)
line_ids = fields.One2many( line_ids = fields.One2many(
'account.spread.line', "account.spread.line", "spread_id", string="Spread Lines"
'spread_id', )
string='Spread Lines')
spread_date = fields.Date( spread_date = fields.Date(
string='Start Date', string="Start Date", default=time.strftime("%Y-01-01"), required=True
default=time.strftime('%Y-01-01'), )
required=True) journal_id = fields.Many2one("account.journal", string="Journal", required=True)
journal_id = fields.Many2one(
'account.journal',
string='Journal',
required=True)
invoice_line_ids = fields.One2many( invoice_line_ids = fields.One2many(
'account.invoice.line', "account.invoice.line", "spread_id", copy=False, string="Invoice Lines"
'spread_id', )
copy=False,
string='Invoice Lines')
invoice_line_id = fields.Many2one( invoice_line_id = fields.Many2one(
'account.invoice.line', "account.invoice.line",
string='Invoice line', string="Invoice line",
compute='_compute_invoice_line', compute="_compute_invoice_line",
inverse='_inverse_invoice_line', inverse="_inverse_invoice_line",
store=True) store=True,
)
invoice_id = fields.Many2one( invoice_id = fields.Many2one(
related='invoice_line_id.invoice_id', related="invoice_line_id.invoice_id",
readonly=True, readonly=True,
store=True, store=True,
string='Invoice') string="Invoice",
estimated_amount = fields.Float(digits=dp.get_precision('Account')) )
estimated_amount = fields.Float(digits=dp.get_precision("Account"))
company_id = fields.Many2one( company_id = fields.Many2one(
'res.company', "res.company",
default=lambda self: self.env.user.company_id, default=lambda self: self.env.user.company_id,
string='Company', string="Company",
required=True)
currency_id = fields.Many2one(
'res.currency',
string='Currency',
required=True, required=True,
default=lambda self: self.env.user.company_id.currency_id.id) )
currency_id = fields.Many2one(
"res.currency",
string="Currency",
required=True,
default=lambda self: self.env.user.company_id.currency_id.id,
)
account_analytic_id = fields.Many2one( account_analytic_id = fields.Many2one(
'account.analytic.account', "account.analytic.account", string="Analytic Account"
string='Analytic Account') )
analytic_tag_ids = fields.Many2many( analytic_tag_ids = fields.Many2many("account.analytic.tag", string="Analytic Tags")
'account.analytic.tag', move_line_auto_post = fields.Boolean("Auto-post lines", default=True)
string='Analytic Tags')
move_line_auto_post = fields.Boolean('Auto-post lines', default=True)
display_create_all_moves = fields.Boolean( display_create_all_moves = fields.Boolean(
compute='_compute_display_create_all_moves', compute="_compute_display_create_all_moves", string="Display Button All Moves"
string='Display Button All Moves') )
display_recompute_buttons = fields.Boolean( display_recompute_buttons = fields.Boolean(
compute='_compute_display_recompute_buttons', compute="_compute_display_recompute_buttons", string="Display Buttons Recompute"
string='Display Buttons Recompute') )
display_move_line_auto_post = fields.Boolean( display_move_line_auto_post = fields.Boolean(
compute='_compute_display_move_line_auto_post', compute="_compute_display_move_line_auto_post",
string='Display Button Auto-post lines') string="Display Button Auto-post lines",
)
active = fields.Boolean(default=True) active = fields.Boolean(default=True)
@api.model @api.model
def default_get(self, fields): def default_get(self, fields):
res = super().default_get(fields) res = super().default_get(fields)
if 'company_id' not in fields: if "company_id" not in fields:
company_id = self.env.user.company_id.id company_id = self.env.user.company_id.id
else: else:
company_id = res['company_id'] company_id = res["company_id"]
default_journal = self.env['account.journal'].search([ default_journal = self.env["account.journal"].search(
('type', '=', 'general'), [("type", "=", "general"), ("company_id", "=", company_id)], limit=1
('company_id', '=', company_id) )
], limit=1) if "journal_id" not in res and default_journal:
if 'journal_id' not in res and default_journal: res["journal_id"] = default_journal.id
res['journal_id'] = default_journal.id
return res return res
@api.depends('invoice_type') @api.depends("invoice_type")
def _compute_spread_type(self): def _compute_spread_type(self):
for spread in self: for spread in self:
if spread.invoice_type in ['out_invoice', 'out_refund']: if spread.invoice_type in ["out_invoice", "out_refund"]:
spread.spread_type = 'sale' spread.spread_type = "sale"
else: else:
spread.spread_type = 'purchase' spread.spread_type = "purchase"
@api.depends('invoice_line_ids', 'invoice_line_ids.invoice_id') @api.depends("invoice_line_ids", "invoice_line_ids.invoice_id")
def _compute_invoice_line(self): def _compute_invoice_line(self):
for spread in self: for spread in self:
invoice_lines = spread.invoice_line_ids invoice_lines = spread.invoice_line_ids
@ -165,9 +156,9 @@ class AccountSpread(models.Model):
def _inverse_invoice_line(self): def _inverse_invoice_line(self):
for spread in self: for spread in self:
invoice_line = spread.invoice_line_id invoice_line = spread.invoice_line_id
spread.write({ spread.write(
'invoice_line_ids': [(6, 0, [invoice_line.id])], {"invoice_line_ids": [(6, 0, [invoice_line.id])],}
}) )
@api.depends( @api.depends(
"estimated_amount", "estimated_amount",
@ -189,13 +180,13 @@ class AccountSpread(models.Model):
spread.invoice_line_id.price_subtotal, spread.invoice_line_id.price_subtotal,
spread.currency_id, spread.currency_id,
spread.company_id, spread.company_id,
invoice._get_currency_rate_date() or fields.Date.today() invoice._get_currency_rate_date() or fields.Date.today(),
) )
for spread_line in spread.line_ids: for spread_line in spread.line_ids:
if spread_line.move_id: if spread_line.move_id:
moves_amount += spread_line.amount moves_amount += spread_line.amount
if spread_line.move_id.state == 'posted': if spread_line.move_id.state == "posted":
posted_amount += spread_line.amount posted_amount += spread_line.amount
spread.unspread_amount = total_amount - moves_amount spread.unspread_amount = total_amount - moves_amount
spread.unposted_amount = total_amount - posted_amount spread.unposted_amount = total_amount - posted_amount
@ -216,7 +207,7 @@ class AccountSpread(models.Model):
for spread in self: for spread in self:
spread.display_recompute_buttons = True spread.display_recompute_buttons = True
if not spread.company_id.allow_spread_planning: if not spread.company_id.allow_spread_planning:
if spread.invoice_id.state == 'draft': if spread.invoice_id.state == "draft":
spread.display_recompute_buttons = False spread.display_recompute_buttons = False
@api.multi @api.multi
@ -230,17 +221,17 @@ class AccountSpread(models.Model):
def _get_spread_entry_name(self, seq): def _get_spread_entry_name(self, seq):
"""Use this method to customise the name of the accounting entry.""" """Use this method to customise the name of the accounting entry."""
self.ensure_one() self.ensure_one()
return (self.name or '') + '/' + str(seq) return (self.name or "") + "/" + str(seq)
@api.onchange('template_id') @api.onchange("template_id")
def onchange_template(self): def onchange_template(self):
if self.template_id: if self.template_id:
if self.template_id.spread_type == 'sale': if self.template_id.spread_type == "sale":
if self.invoice_type in ['in_invoice', 'in_refund']: if self.invoice_type in ["in_invoice", "in_refund"]:
self.invoice_type = 'out_invoice' self.invoice_type = "out_invoice"
else: else:
if self.invoice_type in ['out_invoice', 'out_refund']: if self.invoice_type in ["out_invoice", "out_refund"]:
self.invoice_type = 'in_invoice' self.invoice_type = "in_invoice"
if self.template_id.period_number: if self.template_id.period_number:
self.period_number = self.template_id.period_number self.period_number = self.template_id.period_number
if self.template_id.period_type: if self.template_id.period_type:
@ -248,64 +239,72 @@ class AccountSpread(models.Model):
if self.template_id.start_date: if self.template_id.start_date:
self.spread_date = self.template_id.start_date self.spread_date = self.template_id.start_date
@api.onchange('invoice_type', 'company_id') @api.onchange("invoice_type", "company_id")
def onchange_invoice_type(self): def onchange_invoice_type(self):
company = self.company_id company = self.company_id
if not self.env.context.get('default_journal_id'): if not self.env.context.get("default_journal_id"):
journal = company.default_spread_expense_journal_id journal = company.default_spread_expense_journal_id
if self.invoice_type in ('out_invoice', 'in_refund'): if self.invoice_type in ("out_invoice", "in_refund"):
journal = company.default_spread_revenue_journal_id journal = company.default_spread_revenue_journal_id
if journal: if journal:
self.journal_id = journal self.journal_id = journal
if not self.env.context.get('default_debit_account_id'): if not self.env.context.get("default_debit_account_id"):
if self.invoice_type in ('out_invoice', 'in_refund'): if self.invoice_type in ("out_invoice", "in_refund"):
debit_account_id = company.default_spread_revenue_account_id debit_account_id = company.default_spread_revenue_account_id
self.debit_account_id = debit_account_id self.debit_account_id = debit_account_id
if not self.env.context.get('default_credit_account_id'): if not self.env.context.get("default_credit_account_id"):
if self.invoice_type in ('in_invoice', 'out_refund'): if self.invoice_type in ("in_invoice", "out_refund"):
credit_account_id = company.default_spread_expense_account_id credit_account_id = company.default_spread_expense_account_id
self.credit_account_id = credit_account_id self.credit_account_id = credit_account_id
@api.constrains('invoice_id', 'invoice_type') @api.constrains("invoice_id", "invoice_type")
def _check_invoice_type(self): def _check_invoice_type(self):
for spread in self: for spread in self:
if not spread.invoice_id: if not spread.invoice_id:
pass pass
elif spread.invoice_type != spread.invoice_id.type: elif spread.invoice_type != spread.invoice_id.type:
raise ValidationError(_( raise ValidationError(
'The Invoice Type does not correspond to the Invoice')) _("The Invoice Type does not correspond to the Invoice")
)
@api.constrains('journal_id') @api.constrains("journal_id")
def _check_journal(self): def _check_journal(self):
for spread in self: for spread in self:
moves = spread.mapped('line_ids.move_id').filtered('journal_id') moves = spread.mapped("line_ids.move_id").filtered("journal_id")
if any(move.journal_id != spread.journal_id for move in moves): if any(move.journal_id != spread.journal_id for move in moves):
raise ValidationError(_( raise ValidationError(
'The Journal is not consistent with the account moves.')) _("The Journal is not consistent with the account moves.")
)
@api.constrains('template_id', 'invoice_type') @api.constrains("template_id", "invoice_type")
def _check_template_invoice_type(self): def _check_template_invoice_type(self):
for spread in self: for spread in self:
if spread.invoice_type in ['in_invoice', 'in_refund']: if spread.invoice_type in ["in_invoice", "in_refund"]:
if spread.template_id.spread_type == 'sale': if spread.template_id.spread_type == "sale":
raise ValidationError(_( raise ValidationError(
'The Spread Template (Sales) is not compatible ' _(
'with selected invoice type')) "The Spread Template (Sales) is not compatible "
elif spread.invoice_type in ['out_invoice', 'out_refund']: "with selected invoice type"
if spread.template_id.spread_type == 'purchase': )
raise ValidationError(_( )
'The Spread Template (Purchases) is not compatible ' elif spread.invoice_type in ["out_invoice", "out_refund"]:
'with selected invoice type')) if spread.template_id.spread_type == "purchase":
raise ValidationError(
_(
"The Spread Template (Purchases) is not compatible "
"with selected invoice type"
)
)
@api.multi @api.multi
def _get_spread_period_duration(self): def _get_spread_period_duration(self):
"""Converts the selected period_type to number of months.""" """Converts the selected period_type to number of months."""
self.ensure_one() self.ensure_one()
if self.period_type == 'year': if self.period_type == "year":
return 12 return 12
elif self.period_type == 'quarter': elif self.period_type == "quarter":
return 3 return 3
return 1 return 1
@ -348,10 +347,11 @@ class AccountSpread(models.Model):
self.ensure_one() self.ensure_one()
posted_line_ids = self.line_ids.filtered( posted_line_ids = self.line_ids.filtered(
lambda x: x.move_id.state == 'posted').sorted( lambda x: x.move_id.state == "posted"
key=lambda l: l.date) ).sorted(key=lambda l: l.date)
unposted_line_ids = self.line_ids.filtered( unposted_line_ids = self.line_ids.filtered(
lambda x: not x.move_id.state == 'posted') lambda x: not x.move_id.state == "posted"
)
# Remove old unposted spread lines. # Remove old unposted spread lines.
commands = [(2, line_id.id, False) for line_id in unposted_line_ids] commands = [(2, line_id.id, False) for line_id in unposted_line_ids]
@ -375,19 +375,19 @@ class AccountSpread(models.Model):
continue continue
unposted_amount -= amount unposted_amount -= amount
vals = { vals = {
'amount': amount, "amount": amount,
'spread_id': self.id, "spread_id": self.id,
'name': self._get_spread_entry_name(sequence), "name": self._get_spread_entry_name(sequence),
'date': self._get_last_day_of_month(spread_date), "date": self._get_last_day_of_month(spread_date),
} }
commands.append((0, False, vals)) commands.append((0, False, vals))
spread_date = self._next_line_date(month_day, spread_date) spread_date = self._next_line_date(month_day, spread_date)
self.write({'line_ids': commands}) self.write({"line_ids": commands})
invoice_type_selection = dict(self.fields_get( invoice_type_selection = dict(
allfields=['invoice_type'] self.fields_get(allfields=["invoice_type"])["invoice_type"]["selection"]
)['invoice_type']['selection'])[self.invoice_type] )[self.invoice_type]
msg_body = _("Spread table '%s' created.") % invoice_type_selection msg_body = _("Spread table '%s' created.") % invoice_type_selection
self.message_post(body=msg_body) self.message_post(body=msg_body)
@ -430,60 +430,68 @@ class AccountSpread(models.Model):
def action_recalculate_spread(self): def action_recalculate_spread(self):
"""Recalculate spread""" """Recalculate spread"""
self.ensure_one() self.ensure_one()
spread_lines = self.mapped('line_ids').filtered('move_id') spread_lines = self.mapped("line_ids").filtered("move_id")
spread_lines.unlink_move() spread_lines.unlink_move()
self.compute_spread_board() self.compute_spread_board()
self.env['account.spread.line']._create_entries() self.env["account.spread.line"]._create_entries()
@api.multi @api.multi
def action_undo_spread(self): def action_undo_spread(self):
"""Undo spreading: Remove all created moves, """Undo spreading: Remove all created moves,
restore original account on move line""" restore original account on move line"""
self.ensure_one() self.ensure_one()
self.mapped('line_ids').filtered('move_id').unlink_move() self.mapped("line_ids").filtered("move_id").unlink_move()
self.mapped('line_ids').unlink() self.mapped("line_ids").unlink()
@api.multi @api.multi
def action_unlink_invoice_line(self): def action_unlink_invoice_line(self):
"""Unlink the invoice line from the spread board""" """Unlink the invoice line from the spread board"""
self.ensure_one() self.ensure_one()
if self.invoice_id.state != 'draft': if self.invoice_id.state != "draft":
raise UserError( raise UserError(
_("Cannot unlink invoice lines if the invoice is validated")) _("Cannot unlink invoice lines if the invoice is validated")
)
self._action_unlink_invoice_line() self._action_unlink_invoice_line()
@api.multi @api.multi
def _action_unlink_invoice_line(self): def _action_unlink_invoice_line(self):
spread_mls = self.mapped('line_ids.move_id.line_ids') spread_mls = self.mapped("line_ids.move_id.line_ids")
spread_mls.remove_move_reconcile() spread_mls.remove_move_reconcile()
self._message_post_unlink_invoice_line() self._message_post_unlink_invoice_line()
self.write({'invoice_line_ids': [(5, 0, 0)]}) self.write({"invoice_line_ids": [(5, 0, 0)]})
def _message_post_unlink_invoice_line(self): def _message_post_unlink_invoice_line(self):
for spread in self: for spread in self:
invoice_id = spread.invoice_id.id invoice_id = spread.invoice_id.id
inv_link = '<a href=# data-oe-model=account.invoice ' \ inv_link = (
'data-oe-id=%d>%s</a>' % (invoice_id, _("Invoice")) "<a href=# data-oe-model=account.invoice "
"data-oe-id=%d>%s</a>" % (invoice_id, _("Invoice"))
)
msg_body = _("Unlinked invoice line '%s' (view %s).") % ( msg_body = _("Unlinked invoice line '%s' (view %s).") % (
spread.invoice_line_id.name, inv_link) spread.invoice_line_id.name,
inv_link,
)
spread.message_post(body=msg_body) spread.message_post(body=msg_body)
spread_link = '<a href=# data-oe-model=account.spread ' \ spread_link = (
'data-oe-id=%d>%s</a>' % (spread.id, _("Spread")) "<a href=# data-oe-model=account.spread "
"data-oe-id=%d>%s</a>" % (spread.id, _("Spread"))
)
msg_body = _("Unlinked '%s' (invoice line %s).") % ( msg_body = _("Unlinked '%s' (invoice line %s).") % (
spread_link, spread.invoice_line_id.name) spread_link,
spread.invoice_line_id.name,
)
spread.invoice_id.message_post(body=msg_body) spread.invoice_id.message_post(body=msg_body)
@api.multi @api.multi
def unlink(self): def unlink(self):
if self.filtered(lambda s: s.invoice_line_id): if self.filtered(lambda s: s.invoice_line_id):
raise UserError( raise UserError(
_('Cannot delete spread(s) that are linked ' _("Cannot delete spread(s) that are linked " "to an invoice line.")
'to an invoice line.')) )
if self.mapped('line_ids.move_id').filtered( if self.mapped("line_ids.move_id").filtered(lambda m: m.state == "posted"):
lambda m: m.state == 'posted'):
raise ValidationError( raise ValidationError(
_('Cannot delete spread(s): there are ' _("Cannot delete spread(s): there are " "posted Journal Entries.")
'posted Journal Entries.')) )
return super().unlink() return super().unlink()
@api.multi @api.multi
@ -499,40 +507,40 @@ class AccountSpread(models.Model):
if not self.invoice_id.number: if not self.invoice_id.number:
return return
spread_mls = self.line_ids.mapped('move_id.line_ids') spread_mls = self.line_ids.mapped("move_id.line_ids")
if created_moves: if created_moves:
spread_mls |= created_moves.mapped('line_ids') spread_mls |= created_moves.mapped("line_ids")
spread_sign = True if self.total_amount >= 0.0 else False spread_sign = True if self.total_amount >= 0.0 else False
in_invoice_or_out_refund = ('in_invoice', 'out_refund') in_invoice_or_out_refund = ("in_invoice", "out_refund")
if self.invoice_type in in_invoice_or_out_refund and spread_sign: if self.invoice_type in in_invoice_or_out_refund and spread_sign:
spread_mls = spread_mls.filtered(lambda x: x.credit != 0.) spread_mls = spread_mls.filtered(lambda x: x.credit != 0.0)
elif self.invoice_type in in_invoice_or_out_refund: elif self.invoice_type in in_invoice_or_out_refund:
spread_mls = spread_mls.filtered(lambda x: x.debit != 0.) spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0)
elif spread_sign: elif spread_sign:
spread_mls = spread_mls.filtered(lambda x: x.debit != 0.) spread_mls = spread_mls.filtered(lambda x: x.debit != 0.0)
else: else:
spread_mls = spread_mls.filtered(lambda x: x.credit != 0.) spread_mls = spread_mls.filtered(lambda x: x.credit != 0.0)
invoice_mls = self.invoice_id.move_id.mapped('line_ids') invoice_mls = self.invoice_id.move_id.mapped("line_ids")
if self.invoice_id.type in in_invoice_or_out_refund and spread_sign: if self.invoice_id.type in in_invoice_or_out_refund and spread_sign:
invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.) invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.0)
elif self.invoice_id.type in in_invoice_or_out_refund: elif self.invoice_id.type in in_invoice_or_out_refund:
invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.) invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0)
elif spread_sign: elif spread_sign:
invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.) invoice_mls = invoice_mls.filtered(lambda x: x.credit != 0.0)
else: else:
invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.) invoice_mls = invoice_mls.filtered(lambda x: x.debit != 0.0)
to_be_reconciled = self.env['account.move.line'] to_be_reconciled = self.env["account.move.line"]
if len(invoice_mls) > 1: if len(invoice_mls) > 1:
# Refine selection of move line. # Refine selection of move line.
# The name is formatted the same way as it is done when creating # The name is formatted the same way as it is done when creating
# move lines in method "def invoice_line_move_line_get()" of # move lines in method "def invoice_line_move_line_get()" of
# standard account module # standard account module
raw_name = self.invoice_line_id.name raw_name = self.invoice_line_id.name
formatted_name = raw_name.split('\n')[0][:64] formatted_name = raw_name.split("\n")[0][:64]
for move_line in invoice_mls: for move_line in invoice_mls:
if move_line.name == formatted_name: if move_line.name == formatted_name:
to_be_reconciled |= move_line to_be_reconciled |= move_line
@ -546,11 +554,10 @@ class AccountSpread(models.Model):
@api.multi @api.multi
def create_all_moves(self): def create_all_moves(self):
for line in self.mapped('line_ids').filtered(lambda l: not l.move_id): for line in self.mapped("line_ids").filtered(lambda l: not l.move_id):
line.create_move() line.create_move()
@api.depends( @api.depends("debit_account_id.deprecated", "credit_account_id.deprecated")
'debit_account_id.deprecated', 'credit_account_id.deprecated')
def _compute_deprecated_accounts(self): def _compute_deprecated_accounts(self):
for spread in self: for spread in self:
debit_deprecated = bool(spread.debit_account_id.deprecated) debit_deprecated = bool(spread.debit_account_id.deprecated)
@ -561,5 +568,5 @@ class AccountSpread(models.Model):
@api.multi @api.multi
def open_reconcile_view(self): def open_reconcile_view(self):
self.ensure_one() self.ensure_one()
spread_mls = self.line_ids.mapped('move_id.line_ids') spread_mls = self.line_ids.mapped("move_id.line_ids")
return spread_mls.open_reconcile_view() return spread_mls.open_reconcile_view()

View File

@ -2,22 +2,23 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.addons import decimal_precision as dp
class AccountInvoiceSpreadLine(models.Model): class AccountInvoiceSpreadLine(models.Model):
_name = 'account.spread.line' _name = "account.spread.line"
_description = 'Account Spread Lines' _description = "Account Spread Lines"
_order = 'date' _order = "date"
name = fields.Char('Description', readonly=True) name = fields.Char("Description", readonly=True)
amount = fields.Float(digits=dp.get_precision('Account'), required=True) amount = fields.Float(digits=dp.get_precision("Account"), required=True)
date = fields.Date(required=True) date = fields.Date(required=True)
spread_id = fields.Many2one( spread_id = fields.Many2one(
'account.spread', string='Spread Board', ondelete='cascade') "account.spread", string="Spread Board", ondelete="cascade"
move_id = fields.Many2one( )
'account.move', string='Journal Entry', readonly=True) move_id = fields.Many2one("account.move", string="Journal Entry", readonly=True)
@api.multi @api.multi
def create_and_reconcile_moves(self): def create_and_reconcile_moves(self):
@ -25,19 +26,19 @@ class AccountInvoiceSpreadLine(models.Model):
for spread_line in self: for spread_line in self:
spread = spread_line.spread_id spread = spread_line.spread_id
spread_line_list = grouped_lines.get( spread_line_list = grouped_lines.get(
spread, self.env['account.spread.line']) spread, self.env["account.spread.line"]
grouped_lines.update({ )
spread: spread_line_list + spread_line grouped_lines.update({spread: spread_line_list + spread_line})
})
for spread in grouped_lines: for spread in grouped_lines:
created_moves = grouped_lines[spread]._create_moves() created_moves = grouped_lines[spread]._create_moves()
if created_moves: if created_moves:
post_msg = _("Created move(s) ") post_msg = _("Created move(s) ")
post_msg += ", ".join( post_msg += ", ".join(
'<a href=# data-oe-model=account.move data-oe-id=%d' "<a href=# data-oe-model=account.move data-oe-id=%d"
'>%s</a>' % (move.id, move.name) ">%s</a>" % (move.id, move.name)
for move in created_moves) for move in created_moves
)
spread.message_post(body=post_msg) spread.message_post(body=post_msg)
spread._reconcile_spread_moves(created_moves) spread._reconcile_spread_moves(created_moves)
@ -62,15 +63,19 @@ class AccountInvoiceSpreadLine(models.Model):
@api.multi @api.multi
def _create_moves(self): def _create_moves(self):
if self.filtered(lambda l: l.move_id): if self.filtered(lambda l: l.move_id):
raise UserError(_('This spread line is already linked to a ' raise UserError(
'journal entry! Please post or delete it.')) _(
"This spread line is already linked to a "
"journal entry! Please post or delete it."
)
)
created_moves = self.env['account.move'] created_moves = self.env["account.move"]
for line in self: for line in self:
move_vals = line._prepare_move() move_vals = line._prepare_move()
move = self.env['account.move'].create(move_vals) move = self.env["account.move"].create(move_vals)
line.write({'move_id': move.id}) line.write({"move_id": move.id})
created_moves += move created_moves += move
return created_moves return created_moves
@ -78,7 +83,7 @@ class AccountInvoiceSpreadLine(models.Model):
def _prepare_move(self): def _prepare_move(self):
self.ensure_one() self.ensure_one()
spread_date = self.env.context.get('spread_date') or self.date spread_date = self.env.context.get("spread_date") or self.date
spread = self.spread_id spread = self.spread_id
analytic = spread.account_analytic_id analytic = spread.account_analytic_id
analytic_tags = [(4, tag.id, None) for tag in spread.analytic_tag_ids] analytic_tags = [(4, tag.id, None) for tag in spread.analytic_tag_ids]
@ -87,37 +92,49 @@ class AccountInvoiceSpreadLine(models.Model):
current_currency = spread.currency_id current_currency = spread.currency_id
not_same_curr = company_currency != current_currency not_same_curr = company_currency != current_currency
amount = current_currency._convert( amount = current_currency._convert(
self.amount, company_currency, spread.company_id, spread_date) self.amount, company_currency, spread.company_id, spread_date
)
line_ids = [(0, 0, { line_ids = [
'name': spread.name.split('\n')[0][:64], (
'account_id': spread.debit_account_id.id, 0,
'debit': amount if amount > 0.0 else 0.0, 0,
'credit': -amount if amount < 0.0 else 0.0, {
'partner_id': self.spread_id.invoice_id.partner_id.id, "name": spread.name.split("\n")[0][:64],
'analytic_account_id': analytic.id, "account_id": spread.debit_account_id.id,
'analytic_tag_ids': analytic_tags, "debit": amount if amount > 0.0 else 0.0,
'currency_id': not_same_curr and current_currency.id or False, "credit": -amount if amount < 0.0 else 0.0,
'amount_currency': not_same_curr and - 1.0 * self.amount or 0.0, "partner_id": self.spread_id.invoice_id.partner_id.id,
}), (0, 0, { "analytic_account_id": analytic.id,
'name': spread.name.split('\n')[0][:64], "analytic_tag_ids": analytic_tags,
'account_id': spread.credit_account_id.id, "currency_id": not_same_curr and current_currency.id or False,
'credit': amount if amount > 0.0 else 0.0, "amount_currency": not_same_curr and -1.0 * self.amount or 0.0,
'debit': -amount if amount < 0.0 else 0.0, },
'partner_id': self.spread_id.invoice_id.partner_id.id, ),
'analytic_account_id': analytic.id, (
'analytic_tag_ids': analytic_tags, 0,
'currency_id': not_same_curr and current_currency.id or False, 0,
'amount_currency': not_same_curr and self.amount or 0.0, {
})] "name": spread.name.split("\n")[0][:64],
"account_id": spread.credit_account_id.id,
"credit": amount if amount > 0.0 else 0.0,
"debit": -amount if amount < 0.0 else 0.0,
"partner_id": self.spread_id.invoice_id.partner_id.id,
"analytic_account_id": analytic.id,
"analytic_tag_ids": analytic_tags,
"currency_id": not_same_curr and current_currency.id or False,
"amount_currency": not_same_curr and self.amount or 0.0,
},
),
]
return { return {
'name': self.name or "/", "name": self.name or "/",
'ref': self.name, "ref": self.name,
'date': spread_date, "date": spread_date,
'journal_id': spread.journal_id.id, "journal_id": spread.journal_id.id,
'line_ids': line_ids, "line_ids": line_ids,
'company_id': spread.company_id.id, "company_id": spread.company_id.id,
} }
@api.multi @api.multi
@ -127,13 +144,13 @@ class AccountInvoiceSpreadLine(models.Model):
""" """
self.ensure_one() self.ensure_one()
return { return {
'name': _("Journal Entry"), "name": _("Journal Entry"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.move', "res_model": "account.move",
'view_id': False, "view_id": False,
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'res_id': self.move_id.id, "res_id": self.move_id.id,
} }
@api.multi @api.multi
@ -143,7 +160,7 @@ class AccountInvoiceSpreadLine(models.Model):
""" """
for line in self: for line in self:
move = line.move_id move = line.move_id
if move.state == 'posted': if move.state == "posted":
move.button_cancel() move.button_cancel()
move.line_ids.remove_move_reconcile() move.line_ids.remove_move_reconcile()
post_msg = _("Deleted move %s") % line.move_id.id post_msg = _("Deleted move %s") % line.move_id.id
@ -156,18 +173,21 @@ class AccountInvoiceSpreadLine(models.Model):
"""Find spread line entries where date is in the past and """Find spread line entries where date is in the past and
create moves for them. Method also called by the cron job. create moves for them. Method also called by the cron job.
""" """
lines = self.search([ lines = self.search(
('date', '<=', fields.Date.today()), [("date", "<=", fields.Date.today()), ("move_id", "=", False)]
('move_id', '=', False) )
])
lines.create_and_reconcile_moves() lines.create_and_reconcile_moves()
unposted_moves = self.search([('move_id', '!=', False)]).mapped( unposted_moves = (
'move_id').filtered(lambda m: m.state != 'posted') self.search([("move_id", "!=", False)])
unposted_moves.filtered( .mapped("move_id")
lambda m: m.company_id.force_move_auto_post).post() .filtered(lambda m: m.state != "posted")
)
unposted_moves.filtered(lambda m: m.company_id.force_move_auto_post).post()
spreads_to_archive = self.env['account.spread'].search([ spreads_to_archive = (
('all_posted', '=', True) self.env["account.spread"]
]).filtered(lambda s: s.company_id.auto_archive) .search([("all_posted", "=", True)])
spreads_to_archive.write({'active': False}) .filtered(lambda s: s.company_id.auto_archive)
)
spreads_to_archive.write({"active": False})

View File

@ -1,89 +1,89 @@
# Copyright 2018-2019 Onestein (<https://www.onestein.eu>) # Copyright 2018-2019 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _ from odoo import _, api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
class AccountSpreadTemplate(models.Model): class AccountSpreadTemplate(models.Model):
_name = 'account.spread.template' _name = "account.spread.template"
_description = 'Account Spread Template' _description = "Account Spread Template"
name = fields.Char(required=True) name = fields.Char(required=True)
spread_type = fields.Selection([ spread_type = fields.Selection(
('sale', 'Customer'), [("sale", "Customer"), ("purchase", "Supplier")], default="sale", required=True
('purchase', 'Supplier')], )
default='sale',
required=True)
company_id = fields.Many2one( company_id = fields.Many2one(
'res.company', "res.company",
default=lambda self: self.env.user.company_id, default=lambda self: self.env.user.company_id,
string='Company', string="Company",
required=True) required=True,
)
spread_journal_id = fields.Many2one( spread_journal_id = fields.Many2one(
'account.journal', "account.journal", string="Journal", required=True
string='Journal', )
required=True)
use_invoice_line_account = fields.Boolean( use_invoice_line_account = fields.Boolean(
string="Invoice account as spread account", string="Invoice account as spread account",
help="Use invoice line's account as Balance sheet / spread account.\n" help="Use invoice line's account as Balance sheet / spread account.\n"
"In this case, user need to select expense/revenue account too.") "In this case, user need to select expense/revenue account too.",
)
spread_account_id = fields.Many2one( spread_account_id = fields.Many2one(
'account.account', "account.account", string="Spread Balance Sheet Account", required=False
string='Spread Balance Sheet Account', )
required=False)
exp_rev_account_id = fields.Many2one( exp_rev_account_id = fields.Many2one(
'account.account', "account.account",
string='Expense/Revenue Account', string="Expense/Revenue Account",
help="Optional account to overwrite the existing expense/revenue " help="Optional account to overwrite the existing expense/revenue " "account",
"account") )
period_number = fields.Integer( period_number = fields.Integer(
string='Number of Repetitions', string="Number of Repetitions", help="Define the number of spread lines"
help="Define the number of spread lines") )
period_type = fields.Selection([ period_type = fields.Selection(
('month', 'Month'), [("month", "Month"), ("quarter", "Quarter"), ("year", "Year")],
('quarter', 'Quarter'), help="Period length for the entries",
('year', 'Year')], )
help="Period length for the entries")
start_date = fields.Date() start_date = fields.Date()
auto_spread = fields.Boolean( auto_spread = fields.Boolean(
string='Auto assign template on invoice validate', string="Auto assign template on invoice validate",
help="If checked, provide option to auto create spread during " help="If checked, provide option to auto create spread during "
"invoice validation, based on product/account/analytic in invoice line." "invoice validation, based on product/account/analytic in invoice line.",
) )
auto_spread_ids = fields.One2many( auto_spread_ids = fields.One2many(
comodel_name='account.spread.template.auto', comodel_name="account.spread.template.auto",
string='Auto Spread On', string="Auto Spread On",
inverse_name='template_id', inverse_name="template_id",
) )
@api.model @api.model
def default_get(self, fields): def default_get(self, fields):
res = super().default_get(fields) res = super().default_get(fields)
if 'company_id' not in fields: if "company_id" not in fields:
company_id = self.env.user.company_id.id company_id = self.env.user.company_id.id
else: else:
company_id = res['company_id'] company_id = res["company_id"]
default_journal = self.env['account.journal'].search([ default_journal = self.env["account.journal"].search(
('type', '=', 'general'), [("type", "=", "general"), ("company_id", "=", company_id)], limit=1
('company_id', '=', company_id)], )
limit=1) if "spread_journal_id" not in res and default_journal:
if 'spread_journal_id' not in res and default_journal: res["spread_journal_id"] = default_journal.id
res['spread_journal_id'] = default_journal.id
return res return res
@api.constrains('auto_spread', 'auto_spread_ids') @api.constrains("auto_spread", "auto_spread_ids")
def _check_product_account(self): def _check_product_account(self):
for rec in self.filtered('auto_spread'): for rec in self.filtered("auto_spread"):
for line in rec.auto_spread_ids: for line in rec.auto_spread_ids:
if not line.product_id and not line.account_id: if not line.product_id and not line.account_id:
raise UserError(_('Please select product and/or account ' raise UserError(
'on auto spread options')) _(
"Please select product and/or account "
"on auto spread options"
)
)
@api.onchange('spread_type', 'company_id') @api.onchange("spread_type", "company_id")
def onchange_spread_type(self): def onchange_spread_type(self):
company = self.company_id company = self.company_id
if self.spread_type == 'sale': if self.spread_type == "sale":
account = company.default_spread_revenue_account_id account = company.default_spread_revenue_account_id
journal = company.default_spread_revenue_journal_id journal = company.default_spread_revenue_journal_id
else: else:
@ -94,7 +94,7 @@ class AccountSpreadTemplate(models.Model):
if journal: if journal:
self.spread_journal_id = journal self.spread_journal_id = journal
@api.onchange('use_invoice_line_account') @api.onchange("use_invoice_line_account")
def _onchange_user_invoice_line_account(self): def _onchange_user_invoice_line_account(self):
self.exp_rev_account_id = False self.exp_rev_account_id = False
@ -102,32 +102,32 @@ class AccountSpreadTemplate(models.Model):
self.ensure_one() self.ensure_one()
company = self.company_id company = self.company_id
spread_vals = { spread_vals = {
'name': self.name, "name": self.name,
'template_id': self.id, "template_id": self.id,
'journal_id': self.spread_journal_id.id, "journal_id": self.spread_journal_id.id,
'use_invoice_line_account': self.use_invoice_line_account, "use_invoice_line_account": self.use_invoice_line_account,
'company_id': company.id, "company_id": company.id,
} }
account_id = spread_account_id or self.spread_account_id.id account_id = spread_account_id or self.spread_account_id.id
if self.spread_type == 'sale': if self.spread_type == "sale":
invoice_type = 'out_invoice' invoice_type = "out_invoice"
spread_vals['debit_account_id'] = account_id spread_vals["debit_account_id"] = account_id
else: else:
invoice_type = 'in_invoice' invoice_type = "in_invoice"
spread_vals['credit_account_id'] = account_id spread_vals["credit_account_id"] = account_id
if self.period_number: if self.period_number:
spread_vals['period_number'] = self.period_number spread_vals["period_number"] = self.period_number
if self.period_type: if self.period_type:
spread_vals['period_type'] = self.period_type spread_vals["period_type"] = self.period_type
if self.start_date: if self.start_date:
spread_vals['spread_date'] = self.start_date spread_vals["spread_date"] = self.start_date
spread_vals['invoice_type'] = invoice_type spread_vals["invoice_type"] = invoice_type
return spread_vals return spread_vals
@api.constrains('auto_spread_ids', 'auto_spread') @api.constrains("auto_spread_ids", "auto_spread")
def _check_auto_spread_ids_unique(self): def _check_auto_spread_ids_unique(self):
query = """ query = """
select product_id, account_id, analytic_account_id select product_id, account_id, analytic_account_id
@ -141,43 +141,31 @@ class AccountSpreadTemplate(models.Model):
self._cr.execute(query, [self._ids]) self._cr.execute(query, [self._ids])
results = [] results = []
for res in self._cr.fetchall(): for res in self._cr.fetchall():
product = self.env['product.product'].browse(res[0]) product = self.env["product.product"].browse(res[0])
account = self.env['account.account'].browse(res[1]) account = self.env["account.account"].browse(res[1])
analytic = self.env['account.analytic.account'].browse(res[2]) analytic = self.env["account.analytic.account"].browse(res[2])
results.append('%s / %s / %s' % (product.name, account.name, analytic.name)) results.append("{} / {} / {}".format(product.name, account.name, analytic.name))
if results: if results:
raise UserError( raise UserError(
_('Followings are duplicated combinations,\n\n%s' % '\n'.join(results))) _("Followings are duplicated combinations,\n\n%s" % "\n".join(results))
)
class AccountSpreadTemplateAuto(models.Model): class AccountSpreadTemplateAuto(models.Model):
_name = 'account.spread.template.auto' _name = "account.spread.template.auto"
_description = 'Auto create spread, based on product/account/analytic' _description = "Auto create spread, based on product/account/analytic"
template_id = fields.Many2one( template_id = fields.Many2one(
comodel_name='account.spread.template', comodel_name="account.spread.template",
string='Spread Template', string="Spread Template",
required=True, required=True,
ondelete='cascade', ondelete="cascade",
index=True, index=True,
) )
company_id = fields.Many2one( company_id = fields.Many2one(related="template_id.company_id", store=True,)
related='template_id.company_id', name = fields.Char(required=True, default="/",)
store=True, product_id = fields.Many2one(comodel_name="product.product", string="Product",)
) account_id = fields.Many2one(comodel_name="account.account", string="Account",)
name = fields.Char(
required=True,
default='/',
)
product_id = fields.Many2one(
comodel_name='product.product',
string='Product',
)
account_id = fields.Many2one(
comodel_name='account.account',
string='Account',
)
analytic_account_id = fields.Many2one( analytic_account_id = fields.Many2one(
comodel_name='account.analytic.account', comodel_name="account.analytic.account", string="Analytic",
string='Analytic',
) )

View File

@ -5,29 +5,36 @@ from odoo import fields, models
class ResCompany(models.Model): class ResCompany(models.Model):
_inherit = 'res.company' _inherit = "res.company"
default_spread_revenue_account_id = fields.Many2one( default_spread_revenue_account_id = fields.Many2one(
'account.account', string='Revenue Spread Account') "account.account", string="Revenue Spread Account"
)
default_spread_expense_account_id = fields.Many2one( default_spread_expense_account_id = fields.Many2one(
'account.account', string='Expense Spread Account') "account.account", string="Expense Spread Account"
)
default_spread_revenue_journal_id = fields.Many2one( default_spread_revenue_journal_id = fields.Many2one(
'account.journal', string='Revenue Spread Journal') "account.journal", string="Revenue Spread Journal"
)
default_spread_expense_journal_id = fields.Many2one( default_spread_expense_journal_id = fields.Many2one(
'account.journal', string='Expense Spread Journal') "account.journal", string="Expense Spread Journal"
)
allow_spread_planning = fields.Boolean( allow_spread_planning = fields.Boolean(
default=True, default=True,
help="Disable this option if you do not want to allow the " help="Disable this option if you do not want to allow the "
"spreading before the invoice is validated.") "spreading before the invoice is validated.",
)
force_move_auto_post = fields.Boolean( force_move_auto_post = fields.Boolean(
'Auto-post spread lines', "Auto-post spread lines",
help="Enable this option if you want to post automatically the " help="Enable this option if you want to post automatically the "
"accounting moves of all the spreads.") "accounting moves of all the spreads.",
)
auto_archive = fields.Boolean( auto_archive = fields.Boolean(
'Auto-archive spread', "Auto-archive spread",
help="Enable this option if you want the cron job to automatically " help="Enable this option if you want the cron job to automatically "
"archive the spreads when all lines are posted.") "archive the spreads when all lines are posted.",
)

View File

@ -1,27 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record id="account_spread_multi_company_rule" model="ir.rule"> <record id="account_spread_multi_company_rule" model="ir.rule">
<field name="name">Account Spread multi-company</field> <field name="name">Account Spread multi-company</field>
<field ref="model_account_spread" name="model_id"/> <field ref="model_account_spread" name="model_id" />
<field eval="True" name="global"/> <field eval="True" name="global" />
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> <field
name="domain_force"
>['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record> </record>
<record id="account_spread_template_multi_company_rule" model="ir.rule"> <record id="account_spread_template_multi_company_rule" model="ir.rule">
<field name="name">Account Spread Template multi-company</field> <field name="name">Account Spread Template multi-company</field>
<field ref="model_account_spread_template" name="model_id"/> <field ref="model_account_spread_template" name="model_id" />
<field eval="True" name="global"/> <field eval="True" name="global" />
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> <field
name="domain_force"
>['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record> </record>
<record id="account_spread_template_auto_multi_company_rule" model="ir.rule"> <record id="account_spread_template_auto_multi_company_rule" model="ir.rule">
<field name="name">Account Spread Tempalte Auto multi-company</field> <field name="name">Account Spread Tempalte Auto multi-company</field>
<field ref="model_account_spread_template_auto" name="model_id"/> <field ref="model_account_spread_template_auto" name="model_id" />
<field eval="True" name="global"/> <field eval="True" name="global" />
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> <field
name="domain_force"
>['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@ -1,41 +1,41 @@
odoo.define('account_spread_cost_revenue.widget', function (require) { odoo.define("account_spread_cost_revenue.widget", function(require) {
"use strict"; "use strict";
var AbstractField = require('web.AbstractField'); var AbstractField = require("web.AbstractField");
var core = require('web.core'); var core = require("web.core");
var registry = require('web.field_registry'); var registry = require("web.field_registry");
var _t = core._t; var _t = core._t;
var AccountSpreadWidget = AbstractField.extend({ var AccountSpreadWidget = AbstractField.extend({
events: _.extend({}, AbstractField.prototype.events, { events: _.extend({}, AbstractField.prototype.events, {
'click': '_onClick', click: "_onClick",
}), }),
description: "", description: "",
/** /**
* @override * @override
*/ */
isSet: function () { isSet: function() {
return this.value !== 'unavailable'; return this.value !== "unavailable";
}, },
/** /**
* @override * @override
* @private * @private
*/ */
_render: function () { _render: function() {
var className = ''; var className = "";
var style = 'btn fa fa-arrow-circle-right o_spread_line '; var style = "btn fa fa-arrow-circle-right o_spread_line ";
var title = ''; var title = "";
if (this.recordData.spread_check === 'linked') { if (this.recordData.spread_check === "linked") {
className = 'o_is_linked'; className = "o_is_linked";
title = _t('Linked to spread'); title = _t("Linked to spread");
} else { } else {
title = _t('Not linked to spread'); title = _t("Not linked to spread");
} }
var $button = $('<button/>', { var $button = $("<button/>", {
type: 'button', type: "button",
title: title, title: title,
}).addClass(style + className); }).addClass(style + className);
this.$el.html($button); this.$el.html($button);
@ -45,12 +45,12 @@ odoo.define('account_spread_cost_revenue.widget', function (require) {
* @private * @private
* @param {MouseEvent} event * @param {MouseEvent} event
*/ */
_onClick: function (event) { _onClick: function(event) {
event.stopPropagation(); event.stopPropagation();
this.trigger_up('button_clicked', { this.trigger_up("button_clicked", {
attrs: { attrs: {
name: 'spread_details', name: "spread_details",
type: 'object', type: "object",
}, },
record: this.record, record: this.record,
}); });
@ -58,5 +58,4 @@ odoo.define('account_spread_cost_revenue.widget', function (require) {
}); });
registry.add("spread_line_widget", AccountSpreadWidget); registry.add("spread_line_widget", AccountSpreadWidget);
}); });

View File

@ -1,5 +1,5 @@
.o_web_client .o_spread_line { .o_web_client .o_spread_line {
&.o_is_linked { &.o_is_linked {
color: theme-color('success'); color: theme-color("success");
} }
} }

View File

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<template id="assets_backend" name="account spread" inherit_id="web.assets_backend"> <template id="assets_backend" name="account spread" inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <xpath expr="." position="inside">
<link rel="stylesheet" href="/account_spread_cost_revenue/static/src/scss/account_spread.scss"/> <link
<script type="text/javascript" src="/account_spread_cost_revenue/static/src/js/account_spread.js"></script> rel="stylesheet"
href="/account_spread_cost_revenue/static/src/scss/account_spread.scss"
/>
<script
type="text/javascript"
src="/account_spread_cost_revenue/static/src/js/account_spread.js"
/>
</xpath> </xpath>
</template> </template>
</odoo> </odoo>

View File

@ -1,106 +1,127 @@
# Copyright 2018-2019 Onestein (<https://www.onestein.eu>) # Copyright 2018-2019 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.tools import convert_file
from odoo.modules.module import get_resource_path
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.modules.module import get_resource_path
from odoo.tests import common from odoo.tests import common
from odoo.tools import convert_file
class TestAccountInvoiceSpread(common.TransactionCase): class TestAccountInvoiceSpread(common.TransactionCase):
def _load(self, module, *args): def _load(self, module, *args):
convert_file( convert_file(
self.cr, self.cr,
'account_spread_cost_revenue', "account_spread_cost_revenue",
get_resource_path(module, *args), get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report) {},
"init",
False,
"test",
self.registry._assertion_report,
)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self._load('account', 'test', 'account_minimal_test.xml') self._load("account", "test", "account_minimal_test.xml")
type_receivable = self.env.ref('account.data_account_type_receivable') type_receivable = self.env.ref("account.data_account_type_receivable")
type_payable = self.env.ref('account.data_account_type_payable') type_payable = self.env.ref("account.data_account_type_payable")
type_revenue = self.env.ref('account.data_account_type_revenue') type_revenue = self.env.ref("account.data_account_type_revenue")
self.invoice_account = self.env['account.account'].create({ self.invoice_account = self.env["account.account"].create(
'name': 'test_account_receivable', {
'code': '123', "name": "test_account_receivable",
'user_type_id': type_receivable.id, "code": "123",
'reconcile': True "user_type_id": type_receivable.id,
}) "reconcile": True,
}
)
self.account_payable = self.env['account.account'].create({ self.account_payable = self.env["account.account"].create(
'name': 'test_account_payable', {
'code': '321', "name": "test_account_payable",
'user_type_id': type_payable.id, "code": "321",
'reconcile': True "user_type_id": type_payable.id,
}) "reconcile": True,
}
)
self.account_revenue = self.env['account.account'].create({ self.account_revenue = self.env["account.account"].create(
'name': 'test_account_revenue', {
'code': '864', "name": "test_account_revenue",
'user_type_id': type_revenue.id, "code": "864",
'reconcile': True "user_type_id": type_revenue.id,
}) "reconcile": True,
}
)
self.invoice_line_account = self.account_payable self.invoice_line_account = self.account_payable
self.spread_account = self.env['account.account'].create({ self.spread_account = self.env["account.account"].create(
'name': 'test spread account_payable', {
'code': '765', "name": "test spread account_payable",
'user_type_id': type_payable.id, "code": "765",
'reconcile': True "user_type_id": type_payable.id,
}) "reconcile": True,
}
)
partner = self.env['res.partner'].create({ partner = self.env["res.partner"].create(
'name': 'Partner Name', {"name": "Partner Name", "supplier": True,}
'supplier': True, )
})
# Purchase Invoice # Purchase Invoice
self.invoice = self.env['account.invoice'].create({ self.invoice = self.env["account.invoice"].create(
'partner_id': partner.id, {
'account_id': self.invoice_account.id, "partner_id": partner.id,
'type': 'in_invoice', "account_id": self.invoice_account.id,
}) "type": "in_invoice",
self.invoice_line = self.env['account.invoice.line'].create({ }
'quantity': 1.0, )
'price_unit': 1000.0, self.invoice_line = self.env["account.invoice.line"].create(
'invoice_id': self.invoice.id, {
'name': 'product that cost 1000', "quantity": 1.0,
'account_id': self.invoice_account.id, "price_unit": 1000.0,
}) "invoice_id": self.invoice.id,
"name": "product that cost 1000",
"account_id": self.invoice_account.id,
}
)
# Sales Invoice # Sales Invoice
self.invoice_2 = self.env['account.invoice'].create({ self.invoice_2 = self.env["account.invoice"].create(
'partner_id': partner.id, {
'account_id': self.invoice_account.id, "partner_id": partner.id,
'type': 'out_invoice', "account_id": self.invoice_account.id,
}) "type": "out_invoice",
self.invoice_line_2 = self.env['account.invoice.line'].create({ }
'quantity': 1.0, )
'price_unit': 1000.0, self.invoice_line_2 = self.env["account.invoice.line"].create(
'invoice_id': self.invoice_2.id, {
'name': 'product that cost 1000', "quantity": 1.0,
'account_id': self.invoice_line_account.id, "price_unit": 1000.0,
}) "invoice_id": self.invoice_2.id,
"name": "product that cost 1000",
"account_id": self.invoice_line_account.id,
}
)
def test_01_no_auto_spread_sheet(self): def test_01_no_auto_spread_sheet(self):
self.env['account.spread.template'].create({ self.env["account.spread.template"].create(
'name': 'test', {
'spread_type': 'purchase', "name": "test",
'period_number': 5, "spread_type": "purchase",
'period_type': 'month', "period_number": 5,
'spread_account_id': self.account_payable.id, "period_type": "month",
'spread_journal_id': self.ref( "spread_account_id": self.account_payable.id,
'account_spread_cost_revenue.expenses_journal'), "spread_journal_id": self.ref(
'auto_spread': False, # Auto Spread = False "account_spread_cost_revenue.expenses_journal"
'auto_spread_ids': [ ),
(0, 0, {'account_id': self.invoice_account.id})] "auto_spread": False, # Auto Spread = False
}) "auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})],
}
)
self.assertFalse(self.invoice_line.spread_id) self.assertFalse(self.invoice_line.spread_id)
self.invoice.action_invoice_open() self.invoice.action_invoice_open()
@ -108,30 +129,34 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_02_new_auto_spread_sheet_purchase(self): def test_02_new_auto_spread_sheet_purchase(self):
self.env['account.spread.template'].create({ self.env["account.spread.template"].create(
'name': 'test 1', {
'spread_type': 'purchase', "name": "test 1",
'period_number': 5, "spread_type": "purchase",
'period_type': 'month', "period_number": 5,
'spread_account_id': self.account_payable.id, "period_type": "month",
'spread_journal_id': self.ref( "spread_account_id": self.account_payable.id,
'account_spread_cost_revenue.expenses_journal'), "spread_journal_id": self.ref(
'auto_spread': True, # Auto Spread "account_spread_cost_revenue.expenses_journal"
'auto_spread_ids': [ ),
(0, 0, {'account_id': self.invoice_account.id})] "auto_spread": True, # Auto Spread
}) "auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})],
template2 = self.env['account.spread.template'].create({ }
'name': 'test 2', )
'spread_type': 'purchase', template2 = self.env["account.spread.template"].create(
'period_number': 5, {
'period_type': 'month', "name": "test 2",
'spread_account_id': self.account_payable.id, "spread_type": "purchase",
'spread_journal_id': self.ref( "period_number": 5,
'account_spread_cost_revenue.expenses_journal'), "period_type": "month",
'auto_spread': True, # Auto Spread "spread_account_id": self.account_payable.id,
'auto_spread_ids': [ "spread_journal_id": self.ref(
(0, 0, {'account_id': self.invoice_account.id})] "account_spread_cost_revenue.expenses_journal"
}) ),
"auto_spread": True, # Auto Spread
"auto_spread_ids": [(0, 0, {"account_id": self.invoice_account.id})],
}
)
template2._check_auto_spread_ids_unique() template2._check_auto_spread_ids_unique()
self.assertFalse(self.invoice_line.spread_id) self.assertFalse(self.invoice_line.spread_id)
@ -151,17 +176,22 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_03_new_auto_spread_sheet_sale(self): def test_03_new_auto_spread_sheet_sale(self):
self.env['account.spread.template'].create({ self.env["account.spread.template"].create(
'name': 'test', {
'spread_type': 'sale', "name": "test",
'period_number': 5, "spread_type": "sale",
'period_type': 'month', "period_number": 5,
'spread_account_id': self.account_revenue.id, "period_type": "month",
'spread_journal_id': self.ref( "spread_account_id": self.account_revenue.id,
'account_spread_cost_revenue.sales_journal'), "spread_journal_id": self.ref(
'auto_spread': True, # Auto Spread "account_spread_cost_revenue.sales_journal"
'auto_spread_ids': [(0, 0, {'account_id': self.invoice_line_account.id})] ),
}) "auto_spread": True, # Auto Spread
"auto_spread_ids": [
(0, 0, {"account_id": self.invoice_line_account.id})
],
}
)
self.assertFalse(self.invoice_line_2.spread_id) self.assertFalse(self.invoice_line_2.spread_id)
self.invoice_2.action_invoice_open() self.invoice_2.action_invoice_open()

View File

@ -3,123 +3,152 @@
import datetime import datetime
from odoo.tools import convert_file
from odoo.modules.module import get_resource_path
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from odoo.modules.module import get_resource_path
from odoo.tests import common from odoo.tests import common
from odoo.tools import convert_file
class TestAccountInvoiceSpread(common.TransactionCase): class TestAccountInvoiceSpread(common.TransactionCase):
def _load(self, module, *args): def _load(self, module, *args):
convert_file( convert_file(
self.cr, self.cr,
'account_spread_cost_revenue', "account_spread_cost_revenue",
get_resource_path(module, *args), get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report) {},
"init",
False,
"test",
self.registry._assertion_report,
)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self._load('account', 'test', 'account_minimal_test.xml') self._load("account", "test", "account_minimal_test.xml")
type_receivable = self.env.ref('account.data_account_type_receivable') type_receivable = self.env.ref("account.data_account_type_receivable")
type_payable = self.env.ref('account.data_account_type_payable') type_payable = self.env.ref("account.data_account_type_payable")
type_revenue = self.env.ref('account.data_account_type_revenue') type_revenue = self.env.ref("account.data_account_type_revenue")
self.invoice_account = self.env['account.account'].create({ self.invoice_account = self.env["account.account"].create(
'name': 'test_account_receivable', {
'code': '123', "name": "test_account_receivable",
'user_type_id': type_receivable.id, "code": "123",
'reconcile': True "user_type_id": type_receivable.id,
}) "reconcile": True,
}
)
self.account_payable = self.env['account.account'].create({ self.account_payable = self.env["account.account"].create(
'name': 'test_account_payable', {
'code': '321', "name": "test_account_payable",
'user_type_id': type_payable.id, "code": "321",
'reconcile': True "user_type_id": type_payable.id,
}) "reconcile": True,
}
)
self.account_revenue = self.env['account.account'].create({ self.account_revenue = self.env["account.account"].create(
'name': 'test_account_revenue', {
'code': '864', "name": "test_account_revenue",
'user_type_id': type_revenue.id, "code": "864",
'reconcile': True "user_type_id": type_revenue.id,
}) "reconcile": True,
}
)
self.invoice_line_account = self.account_payable self.invoice_line_account = self.account_payable
self.spread_account = self.env['account.account'].create({ self.spread_account = self.env["account.account"].create(
'name': 'test spread account_payable', {
'code': '765', "name": "test spread account_payable",
'user_type_id': type_payable.id, "code": "765",
'reconcile': True "user_type_id": type_payable.id,
}) "reconcile": True,
}
)
partner = self.env['res.partner'].create({ partner = self.env["res.partner"].create(
'name': 'Partner Name', {"name": "Partner Name", "supplier": True,}
'supplier': True, )
}) self.invoice = self.env["account.invoice"].create(
self.invoice = self.env['account.invoice'].create({ {
'partner_id': partner.id, "partner_id": partner.id,
'account_id': self.invoice_account.id, "account_id": self.invoice_account.id,
'type': 'in_invoice', "type": "in_invoice",
}) }
self.invoice_line = self.env['account.invoice.line'].create({ )
'quantity': 1.0, self.invoice_line = self.env["account.invoice.line"].create(
'price_unit': 1000.0, {
'invoice_id': self.invoice.id, "quantity": 1.0,
'name': 'product that cost 1000', "price_unit": 1000.0,
'account_id': self.invoice_account.id, "invoice_id": self.invoice.id,
}) "name": "product that cost 1000",
"account_id": self.invoice_account.id,
}
)
analytic_tags = [(6, 0, self.env.ref('analytic.tag_contract').ids)] analytic_tags = [(6, 0, self.env.ref("analytic.tag_contract").ids)]
self.analytic_account = self.env['account.analytic.account'].create({ self.analytic_account = self.env["account.analytic.account"].create(
'name': 'test account', {"name": "test account",}
}) )
self.spread = self.env['account.spread'].with_context( self.spread = (
mail_create_nosubscribe=True self.env["account.spread"]
).create([{ .with_context(mail_create_nosubscribe=True)
'name': 'test', .create(
'debit_account_id': self.spread_account.id, [
'credit_account_id': self.invoice_line_account.id, {
'period_number': 12, "name": "test",
'period_type': 'month', "debit_account_id": self.spread_account.id,
'spread_date': datetime.date(2017, 2, 1), "credit_account_id": self.invoice_line_account.id,
'estimated_amount': 1000.0, "period_number": 12,
'journal_id': self.invoice.journal_id.id, "period_type": "month",
'invoice_type': 'in_invoice', "spread_date": datetime.date(2017, 2, 1),
'account_analytic_id': self.analytic_account.id, "estimated_amount": 1000.0,
'analytic_tag_ids': analytic_tags, "journal_id": self.invoice.journal_id.id,
}]) "invoice_type": "in_invoice",
"account_analytic_id": self.analytic_account.id,
"analytic_tag_ids": analytic_tags,
}
]
)
)
self.invoice_2 = self.env['account.invoice'].create({ self.invoice_2 = self.env["account.invoice"].create(
'partner_id': partner.id, {
'account_id': self.invoice_account.id, "partner_id": partner.id,
'type': 'out_invoice', "account_id": self.invoice_account.id,
}) "type": "out_invoice",
self.invoice_line_2 = self.env['account.invoice.line'].create({ }
'quantity': 1.0, )
'price_unit': 1000.0, self.invoice_line_2 = self.env["account.invoice.line"].create(
'invoice_id': self.invoice_2.id, {
'name': 'product that cost 1000', "quantity": 1.0,
'account_id': self.invoice_line_account.id, "price_unit": 1000.0,
}) "invoice_id": self.invoice_2.id,
self.spread2 = self.env['account.spread'].create([{ "name": "product that cost 1000",
'name': 'test2', "account_id": self.invoice_line_account.id,
'debit_account_id': self.spread_account.id, }
'credit_account_id': self.invoice_line_account.id, )
'period_number': 12, self.spread2 = self.env["account.spread"].create(
'period_type': 'month', [
'spread_date': datetime.date(2017, 2, 1), {
'estimated_amount': 1000.0, "name": "test2",
'journal_id': self.invoice_2.journal_id.id, "debit_account_id": self.spread_account.id,
'invoice_type': 'out_invoice', "credit_account_id": self.invoice_line_account.id,
}]) "period_number": 12,
"period_type": "month",
"spread_date": datetime.date(2017, 2, 1),
"estimated_amount": 1000.0,
"journal_id": self.invoice_2.journal_id.id,
"invoice_type": "out_invoice",
}
]
)
def test_01_wizard_defaults(self): def test_01_wizard_defaults(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
Wizard = self.env['account.spread.invoice.line.link.wizard'] Wizard = self.env["account.spread.invoice.line.link.wizard"]
wizard1 = Wizard.with_context( wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id, default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id, default_company_id=my_company.id,
@ -128,10 +157,10 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertEqual(wizard1.invoice_line_id, self.invoice_line) self.assertEqual(wizard1.invoice_line_id, self.invoice_line)
self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice) self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice)
self.assertEqual(wizard1.invoice_type, 'in_invoice') self.assertEqual(wizard1.invoice_type, "in_invoice")
self.assertFalse(wizard1.spread_id) self.assertFalse(wizard1.spread_id)
self.assertEqual(wizard1.company_id, my_company) self.assertEqual(wizard1.company_id, my_company)
self.assertEqual(wizard1.spread_action_type, 'link') self.assertEqual(wizard1.spread_action_type, "link")
self.assertFalse(wizard1.spread_account_id) self.assertFalse(wizard1.spread_account_id)
self.assertFalse(wizard1.spread_journal_id) self.assertFalse(wizard1.spread_journal_id)
@ -142,21 +171,21 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2) self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2)
self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2) self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2)
self.assertEqual(wizard2.invoice_type, 'out_invoice') self.assertEqual(wizard2.invoice_type, "out_invoice")
self.assertFalse(wizard2.spread_id) self.assertFalse(wizard2.spread_id)
self.assertEqual(wizard2.company_id, my_company) self.assertEqual(wizard2.company_id, my_company)
self.assertEqual(wizard2.spread_action_type, 'template') self.assertEqual(wizard2.spread_action_type, "template")
self.assertFalse(wizard2.spread_account_id) self.assertFalse(wizard2.spread_account_id)
self.assertFalse(wizard2.spread_journal_id) self.assertFalse(wizard2.spread_journal_id)
def test_02_wizard_defaults(self): def test_02_wizard_defaults(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
Wizard = self.env['account.spread.invoice.line.link.wizard'] Wizard = self.env["account.spread.invoice.line.link.wizard"]
account_revenue = self.account_revenue account_revenue = self.account_revenue
account_payable = self.account_payable account_payable = self.account_payable
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal') exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref('account_spread_cost_revenue.sales_journal') sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = account_payable my_company.default_spread_expense_account_id = account_payable
my_company.default_spread_revenue_journal_id = sales_journal my_company.default_spread_revenue_journal_id = sales_journal
@ -175,16 +204,16 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertEqual(wizard1.invoice_line_id, self.invoice_line) self.assertEqual(wizard1.invoice_line_id, self.invoice_line)
self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice) self.assertEqual(wizard1.invoice_line_id.invoice_id, self.invoice)
self.assertEqual(wizard1.invoice_type, 'in_invoice') self.assertEqual(wizard1.invoice_type, "in_invoice")
self.assertFalse(wizard1.spread_id) self.assertFalse(wizard1.spread_id)
self.assertEqual(wizard1.company_id, my_company) self.assertEqual(wizard1.company_id, my_company)
self.assertEqual(wizard1.spread_action_type, 'link') self.assertEqual(wizard1.spread_action_type, "link")
self.assertFalse(wizard1.spread_account_id) self.assertFalse(wizard1.spread_account_id)
self.assertFalse(wizard1.spread_journal_id) self.assertFalse(wizard1.spread_journal_id)
res_onchange = wizard1.onchange_invoice_type() res_onchange = wizard1.onchange_invoice_type()
self.assertTrue(res_onchange) self.assertTrue(res_onchange)
self.assertTrue(res_onchange.get('domain')) self.assertTrue(res_onchange.get("domain"))
wizard1._onchange_spread_journal_account() wizard1._onchange_spread_journal_account()
self.assertTrue(wizard1.spread_account_id) self.assertTrue(wizard1.spread_account_id)
@ -199,16 +228,16 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2) self.assertEqual(wizard2.invoice_line_id, self.invoice_line_2)
self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2) self.assertEqual(wizard2.invoice_line_id.invoice_id, self.invoice_2)
self.assertEqual(wizard2.invoice_type, 'out_invoice') self.assertEqual(wizard2.invoice_type, "out_invoice")
self.assertFalse(wizard2.spread_id) self.assertFalse(wizard2.spread_id)
self.assertEqual(wizard2.company_id, my_company) self.assertEqual(wizard2.company_id, my_company)
self.assertEqual(wizard2.spread_action_type, 'template') self.assertEqual(wizard2.spread_action_type, "template")
self.assertFalse(wizard2.spread_account_id) self.assertFalse(wizard2.spread_account_id)
self.assertFalse(wizard2.spread_journal_id) self.assertFalse(wizard2.spread_journal_id)
res_onchange = wizard2.onchange_invoice_type() res_onchange = wizard2.onchange_invoice_type()
self.assertTrue(res_onchange) self.assertTrue(res_onchange)
self.assertTrue(res_onchange.get('domain')) self.assertTrue(res_onchange.get("domain"))
wizard2._onchange_spread_journal_account() wizard2._onchange_spread_journal_account()
self.assertTrue(wizard2.spread_account_id) self.assertTrue(wizard2.spread_account_id)
@ -219,22 +248,23 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_03_link_invoice_line_with_spread_sheet(self): def test_03_link_invoice_line_with_spread_sheet(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
Wizard = self.env['account.spread.invoice.line.link.wizard'] Wizard = self.env["account.spread.invoice.line.link.wizard"]
wizard1 = Wizard.with_context( wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id, default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id, default_company_id=my_company.id,
allow_spread_planning=True, allow_spread_planning=True,
).create({}) ).create({})
self.assertEqual(wizard1.spread_action_type, 'link') self.assertEqual(wizard1.spread_action_type, "link")
wizard1.spread_account_id = self.account_revenue wizard1.spread_account_id = self.account_revenue
wizard1.spread_journal_id = self.ref( wizard1.spread_journal_id = self.ref(
'account_spread_cost_revenue.expenses_journal') "account_spread_cost_revenue.expenses_journal"
)
wizard1.spread_id = self.spread wizard1.spread_id = self.spread
res_action = wizard1.confirm() res_action = wizard1.confirm()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertTrue(res_action.get('res_id')) self.assertTrue(res_action.get("res_id"))
self.assertEqual(res_action.get('res_id'), self.spread.id) self.assertEqual(res_action.get("res_id"), self.spread.id)
self.assertTrue(self.spread.invoice_line_id) self.assertTrue(self.spread.invoice_line_id)
self.assertEqual(self.spread.invoice_line_id, self.invoice_line) self.assertEqual(self.spread.invoice_line_id, self.invoice_line)
@ -252,7 +282,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertTrue(line.move_id.journal_id.update_posted) self.assertTrue(line.move_id.journal_id.update_posted)
for ml in line.move_id.line_ids: for ml in line.move_id.line_ids:
ml_analytic_account = ml.analytic_account_id ml_analytic_account = ml.analytic_account_id
analytic_tag = self.env.ref('analytic.tag_contract') analytic_tag = self.env.ref("analytic.tag_contract")
self.assertEqual(ml_analytic_account, self.analytic_account) self.assertEqual(ml_analytic_account, self.analytic_account)
self.assertEqual(ml.analytic_tag_ids, analytic_tag) self.assertEqual(ml.analytic_tag_ids, analytic_tag)
@ -268,35 +298,34 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_04_new_spread_sheet(self): def test_04_new_spread_sheet(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
Wizard = self.env['account.spread.invoice.line.link.wizard'] Wizard = self.env["account.spread.invoice.line.link.wizard"]
spread_account = self.account_revenue spread_account = self.account_revenue
spread_journal_id = self.ref( spread_journal_id = self.ref("account_spread_cost_revenue.expenses_journal")
'account_spread_cost_revenue.expenses_journal')
wizard1 = Wizard.with_context( wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id, default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id, default_company_id=my_company.id,
).create({ ).create({"spread_action_type": "new",})
'spread_action_type': 'new', self.assertEqual(wizard1.spread_action_type, "new")
})
self.assertEqual(wizard1.spread_action_type, 'new')
wizard1.write({ wizard1.write(
'spread_account_id': spread_account.id, {
'spread_journal_id': spread_journal_id, "spread_account_id": spread_account.id,
}) "spread_journal_id": spread_journal_id,
}
)
res_action = wizard1.confirm() res_action = wizard1.confirm()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id')) self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get('context')) self.assertTrue(res_action.get("context"))
res_context = res_action.get('context') res_context = res_action.get("context")
self.assertTrue(res_context.get('default_name')) self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get('default_invoice_type')) self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get('default_invoice_line_id')) self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get('default_debit_account_id')) self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get('default_credit_account_id')) self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
for line in spread_lines: for line in spread_lines:
@ -311,26 +340,26 @@ class TestAccountInvoiceSpread(common.TransactionCase):
wizard2 = Wizard.with_context( wizard2 = Wizard.with_context(
default_invoice_line_id=self.invoice_line_2.id, default_invoice_line_id=self.invoice_line_2.id,
default_company_id=my_company.id, default_company_id=my_company.id,
).create({ ).create({"spread_action_type": "new",})
'spread_action_type': 'new', self.assertEqual(wizard2.spread_action_type, "new")
})
self.assertEqual(wizard2.spread_action_type, 'new')
wizard2.write({ wizard2.write(
'spread_account_id': spread_account.id, {
'spread_journal_id': spread_journal_id, "spread_account_id": spread_account.id,
}) "spread_journal_id": spread_journal_id,
}
)
res_action = wizard2.confirm() res_action = wizard2.confirm()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id')) self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get('context')) self.assertTrue(res_action.get("context"))
res_context = res_action.get('context') res_context = res_action.get("context")
self.assertTrue(res_context.get('default_name')) self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get('default_invoice_type')) self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get('default_invoice_line_id')) self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get('default_debit_account_id')) self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get('default_credit_account_id')) self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread2.line_ids spread_lines = self.spread2.line_ids
for line in spread_lines: for line in spread_lines:
@ -344,34 +373,32 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_05_new_spread_sheet_from_template(self): def test_05_new_spread_sheet_from_template(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
Wizard = self.env['account.spread.invoice.line.link.wizard'] Wizard = self.env["account.spread.invoice.line.link.wizard"]
spread_account = self.account_payable spread_account = self.account_payable
self.assertTrue(spread_account) self.assertTrue(spread_account)
spread_journal_id = self.ref( spread_journal_id = self.ref("account_spread_cost_revenue.expenses_journal")
'account_spread_cost_revenue.expenses_journal')
template = self.env['account.spread.template'].create({ template = self.env["account.spread.template"].create(
'name': 'test', {
'spread_type': 'purchase', "name": "test",
'period_number': 5, "spread_type": "purchase",
'period_type': 'month', "period_number": 5,
'spread_account_id': spread_account.id, "period_type": "month",
'spread_journal_id': spread_journal_id, "spread_account_id": spread_account.id,
}) "spread_journal_id": spread_journal_id,
}
)
wizard1 = Wizard.with_context( wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id, default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id, default_company_id=my_company.id,
).create({ ).create({"spread_action_type": "template", "template_id": template.id,})
'spread_action_type': 'template', self.assertEqual(wizard1.spread_action_type, "template")
'template_id': template.id,
})
self.assertEqual(wizard1.spread_action_type, 'template')
res_action = wizard1.confirm() res_action = wizard1.confirm()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertTrue(res_action.get('res_id')) self.assertTrue(res_action.get("res_id"))
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
for line in spread_lines: for line in spread_lines:
@ -386,26 +413,26 @@ class TestAccountInvoiceSpread(common.TransactionCase):
wizard2 = Wizard.with_context( wizard2 = Wizard.with_context(
default_invoice_line_id=self.invoice_line_2.id, default_invoice_line_id=self.invoice_line_2.id,
default_company_id=my_company.id, default_company_id=my_company.id,
).create({ ).create({"spread_action_type": "new",})
'spread_action_type': 'new', self.assertEqual(wizard2.spread_action_type, "new")
})
self.assertEqual(wizard2.spread_action_type, 'new')
wizard2.write({ wizard2.write(
'spread_account_id': spread_account.id, {
'spread_journal_id': spread_journal_id, "spread_account_id": spread_account.id,
}) "spread_journal_id": spread_journal_id,
}
)
res_action = wizard2.confirm() res_action = wizard2.confirm()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id')) self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get('context')) self.assertTrue(res_action.get("context"))
res_context = res_action.get('context') res_context = res_action.get("context")
self.assertTrue(res_context.get('default_name')) self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get('default_invoice_type')) self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get('default_invoice_line_id')) self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get('default_debit_account_id')) self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get('default_credit_account_id')) self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread2.line_ids spread_lines = self.spread2.line_ids
for line in spread_lines: for line in spread_lines:
@ -420,8 +447,8 @@ class TestAccountInvoiceSpread(common.TransactionCase):
res_action = self.invoice_line.spread_details() res_action = self.invoice_line.spread_details()
self.assertTrue(isinstance(res_action, dict)) self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id')) self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get('context')) self.assertTrue(res_action.get("context"))
def test_07_unlink_invoice_line_and_spread_sheet(self): def test_07_unlink_invoice_line_and_spread_sheet(self):
@ -465,7 +492,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice # Validate invoice
self.invoice.action_invoice_open() self.invoice.action_invoice_open()
invoice_mls = self.invoice.move_id.mapped('line_ids') invoice_mls = self.invoice.move_id.mapped("line_ids")
self.assertTrue(invoice_mls) self.assertTrue(invoice_mls)
for invoice_ml in invoice_mls: for invoice_ml in invoice_mls:
if invoice_ml.debit: if invoice_ml.debit:
@ -474,15 +501,17 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_10_link_vendor_bill_line_with_spread_sheet(self): def test_10_link_vendor_bill_line_with_spread_sheet(self):
copied_line = self.invoice_line.copy() copied_line = self.invoice_line.copy()
copied_line.name = 'new test line' copied_line.name = "new test line"
self.spread.write({ self.spread.write(
'estimated_amount': 1000.0, {
'period_number': 12, "estimated_amount": 1000.0,
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7), "period_type": "month",
'invoice_line_id': self.invoice_line.id, "spread_date": datetime.date(2017, 1, 7),
'move_line_auto_post': False, "invoice_line_id": self.invoice_line.id,
}) "move_line_auto_post": False,
}
)
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
for line in spread_lines: for line in spread_lines:
@ -498,7 +527,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.credit_account_id balance_sheet = self.spread.credit_account_id
self.assertTrue(balance_sheet.reconcile) self.assertTrue(balance_sheet.reconcile)
spread_mls = self.spread.line_ids.mapped('move_id.line_ids') spread_mls = self.spread.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
if spread_ml.debit: if spread_ml.debit:
@ -509,16 +538,17 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice # Validate invoice
self.invoice.action_invoice_open() self.invoice.action_invoice_open()
invoice_mls = self.invoice.move_id.mapped('line_ids') invoice_mls = self.invoice.move_id.mapped("line_ids")
self.assertTrue(invoice_mls) self.assertTrue(invoice_mls)
count_balance_sheet = len(invoice_mls.filtered( count_balance_sheet = len(
lambda x: x.account_id == balance_sheet)) invoice_mls.filtered(lambda x: x.account_id == balance_sheet)
)
self.assertEqual(count_balance_sheet, 1) self.assertEqual(count_balance_sheet, 1)
self.spread.line_ids.create_and_reconcile_moves() self.spread.line_ids.create_and_reconcile_moves()
spread_mls = self.spread.line_ids.mapped('move_id.line_ids') spread_mls = self.spread.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
if spread_ml.debit: if spread_ml.debit:
@ -528,19 +558,21 @@ class TestAccountInvoiceSpread(common.TransactionCase):
action_reconcile_view = self.spread2.open_reconcile_view() action_reconcile_view = self.spread2.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict)) self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertFalse(action_reconcile_view.get('domain')[0][2]) self.assertFalse(action_reconcile_view.get("domain")[0][2])
self.assertTrue(action_reconcile_view.get('context')) self.assertTrue(action_reconcile_view.get("context"))
def test_11_link_vendor_bill_line_with_spread_sheet(self): def test_11_link_vendor_bill_line_with_spread_sheet(self):
self.invoice_line.copy() self.invoice_line.copy()
self.spread.write({ self.spread.write(
'estimated_amount': 1000.0, {
'period_number': 12, "estimated_amount": 1000.0,
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7), "period_type": "month",
'invoice_line_id': self.invoice_line.id, "spread_date": datetime.date(2017, 1, 7),
'move_line_auto_post': False, "invoice_line_id": self.invoice_line.id,
}) "move_line_auto_post": False,
}
)
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
for line in spread_lines: for line in spread_lines:
@ -556,7 +588,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.credit_account_id balance_sheet = self.spread.credit_account_id
self.assertTrue(balance_sheet.reconcile) self.assertTrue(balance_sheet.reconcile)
spread_mls = self.spread.line_ids.mapped('move_id.line_ids') spread_mls = self.spread.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
if spread_ml.debit: if spread_ml.debit:
@ -567,40 +599,43 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice # Validate invoice
self.invoice.action_invoice_open() self.invoice.action_invoice_open()
invoice_mls = self.invoice.move_id.mapped('line_ids') invoice_mls = self.invoice.move_id.mapped("line_ids")
self.assertTrue(invoice_mls) self.assertTrue(invoice_mls)
count_balance_sheet = len(invoice_mls.filtered( count_balance_sheet = len(
lambda x: x.account_id == balance_sheet)) invoice_mls.filtered(lambda x: x.account_id == balance_sheet)
)
self.assertEqual(count_balance_sheet, 1) self.assertEqual(count_balance_sheet, 1)
self.spread.company_id.force_move_auto_post = True self.spread.company_id.force_move_auto_post = True
self.spread.line_ids.create_and_reconcile_moves() self.spread.line_ids.create_and_reconcile_moves()
spread_mls = self.spread.line_ids.mapped('move_id.line_ids') spread_mls = self.spread.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
self.assertFalse(spread_ml.full_reconcile_id) self.assertFalse(spread_ml.full_reconcile_id)
action_reconcile_view = self.spread.open_reconcile_view() action_reconcile_view = self.spread.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict)) self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertTrue(action_reconcile_view.get('domain')[0][2]) self.assertTrue(action_reconcile_view.get("domain")[0][2])
self.assertTrue(action_reconcile_view.get('context')) self.assertTrue(action_reconcile_view.get("context"))
action_spread_details = self.invoice_line.spread_details() action_spread_details = self.invoice_line.spread_details()
self.assertTrue(isinstance(action_spread_details, dict)) self.assertTrue(isinstance(action_spread_details, dict))
self.assertTrue(action_spread_details.get('res_id')) self.assertTrue(action_spread_details.get("res_id"))
def test_12_link_invoice_line_with_spread_sheet_full_reconcile(self): def test_12_link_invoice_line_with_spread_sheet_full_reconcile(self):
self.spread2.write({ self.spread2.write(
'estimated_amount': 1000.0, {
'period_number': 12, "estimated_amount": 1000.0,
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7), "period_type": "month",
'invoice_line_id': self.invoice_line_2.id, "spread_date": datetime.date(2017, 1, 7),
'move_line_auto_post': False, "invoice_line_id": self.invoice_line_2.id,
}) "move_line_auto_post": False,
}
)
spread_lines = self.spread2.line_ids spread_lines = self.spread2.line_ids
for line in spread_lines: for line in spread_lines:
@ -616,7 +651,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.debit_account_id balance_sheet = self.spread.debit_account_id
self.assertTrue(balance_sheet.reconcile) self.assertTrue(balance_sheet.reconcile)
spread_mls = self.spread2.line_ids.mapped('move_id.line_ids') spread_mls = self.spread2.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
if spread_ml.debit: if spread_ml.debit:
@ -627,7 +662,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice # Validate invoice
self.invoice_2.action_invoice_open() self.invoice_2.action_invoice_open()
invoice_mls = self.invoice_2.move_id.mapped('line_ids') invoice_mls = self.invoice_2.move_id.mapped("line_ids")
self.assertTrue(invoice_mls) self.assertTrue(invoice_mls)
for invoice_ml in invoice_mls: for invoice_ml in invoice_mls:
if invoice_ml.credit: if invoice_ml.credit:
@ -635,7 +670,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.spread2.line_ids.create_and_reconcile_moves() self.spread2.line_ids.create_and_reconcile_moves()
spread_mls = self.spread2.line_ids.mapped('move_id.line_ids') spread_mls = self.spread2.line_ids.mapped("move_id.line_ids")
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
for spread_ml in spread_mls: for spread_ml in spread_mls:
if spread_ml.debit: if spread_ml.debit:
@ -645,22 +680,24 @@ class TestAccountInvoiceSpread(common.TransactionCase):
action_reconcile_view = self.spread2.open_reconcile_view() action_reconcile_view = self.spread2.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict)) self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertTrue(action_reconcile_view.get('domain')[0][2]) self.assertTrue(action_reconcile_view.get("domain")[0][2])
self.assertFalse(action_reconcile_view.get('res_id')) self.assertFalse(action_reconcile_view.get("res_id"))
self.assertTrue(action_reconcile_view.get('context')) self.assertTrue(action_reconcile_view.get("context"))
action_spread_details = self.invoice_line_2.spread_details() action_spread_details = self.invoice_line_2.spread_details()
self.assertTrue(isinstance(action_spread_details, dict)) self.assertTrue(isinstance(action_spread_details, dict))
self.assertTrue(action_spread_details.get('res_id')) self.assertTrue(action_spread_details.get("res_id"))
def test_13_link_invoice_line_with_spread_sheet_partial_reconcile(self): def test_13_link_invoice_line_with_spread_sheet_partial_reconcile(self):
self.spread2.write({ self.spread2.write(
'estimated_amount': 1000.0, {
'period_number': 12, "estimated_amount": 1000.0,
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7), "period_type": "month",
}) "spread_date": datetime.date(2017, 1, 7),
}
)
self.spread2.compute_spread_board() self.spread2.compute_spread_board()
spread_lines = self.spread2.line_ids spread_lines = self.spread2.line_ids
@ -674,10 +711,10 @@ class TestAccountInvoiceSpread(common.TransactionCase):
spread_lines[2]._create_moves().post() spread_lines[2]._create_moves().post()
spread_lines[3]._create_moves().post() spread_lines[3]._create_moves().post()
self.assertEqual(spread_lines[0].move_id.state, 'posted') self.assertEqual(spread_lines[0].move_id.state, "posted")
self.assertEqual(spread_lines[1].move_id.state, 'posted') self.assertEqual(spread_lines[1].move_id.state, "posted")
self.assertEqual(spread_lines[2].move_id.state, 'posted') self.assertEqual(spread_lines[2].move_id.state, "posted")
self.assertEqual(spread_lines[3].move_id.state, 'posted') self.assertEqual(spread_lines[3].move_id.state, "posted")
spread_mls = spread_lines[0].move_id.line_ids spread_mls = spread_lines[0].move_id.line_ids
self.assertTrue(spread_mls) self.assertTrue(spread_mls)
@ -694,14 +731,14 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.debit_account_id balance_sheet = self.spread.debit_account_id
self.assertTrue(balance_sheet.reconcile) self.assertTrue(balance_sheet.reconcile)
self.spread2.write({ self.spread2.write(
'invoice_line_id': self.invoice_line_2.id, {"invoice_line_id": self.invoice_line_2.id,}
}) )
# Validate invoice # Validate invoice
self.invoice_2.action_invoice_open() self.invoice_2.action_invoice_open()
invoice_mls = self.invoice_2.move_id.mapped('line_ids') invoice_mls = self.invoice_2.move_id.mapped("line_ids")
self.assertTrue(invoice_mls) self.assertTrue(invoice_mls)
for invoice_ml in invoice_mls: for invoice_ml in invoice_mls:
if invoice_ml.credit: if invoice_ml.credit:
@ -719,8 +756,9 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertFalse(spread_ml.matched_credit_ids) self.assertFalse(spread_ml.matched_credit_ids)
self.assertFalse(spread_ml.full_reconcile_id) self.assertFalse(spread_ml.full_reconcile_id)
other_journal = self.env['account.journal'].create({ other_journal = self.env["account.journal"].create(
'name': 'Other Journal', 'type': 'general', 'code': 'test2'}) {"name": "Other Journal", "type": "general", "code": "test2"}
)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
self.spread2.journal_id = other_journal self.spread2.journal_id = other_journal
@ -749,18 +787,19 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice # Validate invoice
self.invoice.action_invoice_open() self.invoice.action_invoice_open()
self.assertTrue(self.invoice.invoice_line_ids.mapped('spread_id')) self.assertTrue(self.invoice.invoice_line_ids.mapped("spread_id"))
# Create a refund for invoice. # Create a refund for invoice.
self.env['account.invoice.refund'].with_context({ self.env["account.invoice.refund"].with_context(
'active_model': 'account.invoice', {
'active_ids': [self.invoice.id], "active_model": "account.invoice",
'active_id': self.invoice.id "active_ids": [self.invoice.id],
}).create(dict( "active_id": self.invoice.id,
description='Invoice Refund', }
filter_refund='refund', ).create(
)).invoice_refund() dict(description="Invoice Refund", filter_refund="refund",)
).invoice_refund()
# Invoice lines do not contain the lint to the spread. # Invoice lines do not contain the lint to the spread.
refund = self.invoice.refund_invoice_ids[0] refund = self.invoice.refund_invoice_ids[0]
self.assertFalse(refund.invoice_line_ids.mapped('spread_id')) self.assertFalse(refund.invoice_line_ids.mapped("spread_id"))

View File

@ -5,68 +5,82 @@ import datetime
from psycopg2 import IntegrityError from psycopg2 import IntegrityError
from odoo.tools import convert_file, mute_logger
from odoo.modules.module import get_resource_path
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.modules.module import get_resource_path
from odoo.tests import common from odoo.tests import common
from odoo.tools import convert_file, mute_logger
class TestAccountSpreadCostRevenue(common.TransactionCase): class TestAccountSpreadCostRevenue(common.TransactionCase):
def _load(self, module, *args): def _load(self, module, *args):
convert_file( convert_file(
self.cr, self.cr,
'account_spread_cost_revenue', "account_spread_cost_revenue",
get_resource_path(module, *args), get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report) {},
"init",
False,
"test",
self.registry._assertion_report,
)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self._load('account', 'test', 'account_minimal_test.xml') self._load("account", "test", "account_minimal_test.xml")
type_receivable = self.env.ref('account.data_account_type_receivable') type_receivable = self.env.ref("account.data_account_type_receivable")
type_expenses = self.env.ref('account.data_account_type_expenses') type_expenses = self.env.ref("account.data_account_type_expenses")
type_payable = self.env.ref('account.data_account_type_payable') type_payable = self.env.ref("account.data_account_type_payable")
type_revenue = self.env.ref('account.data_account_type_revenue') type_revenue = self.env.ref("account.data_account_type_revenue")
self.account_receivable = self.env['account.account'].create({ self.account_receivable = self.env["account.account"].create(
'name': 'test_account_receivable', {
'code': '123', "name": "test_account_receivable",
'user_type_id': type_receivable.id, "code": "123",
'reconcile': True "user_type_id": type_receivable.id,
}) "reconcile": True,
}
)
self.credit_account = self.account_receivable self.credit_account = self.account_receivable
self.account_expenses = self.env['account.account'].create({ self.account_expenses = self.env["account.account"].create(
'name': 'test account_expenses', {
'code': '765', "name": "test account_expenses",
'user_type_id': type_expenses.id, "code": "765",
'reconcile': True "user_type_id": type_expenses.id,
}) "reconcile": True,
}
)
self.debit_account = self.account_expenses self.debit_account = self.account_expenses
self.account_payable = self.env['account.account'].create({ self.account_payable = self.env["account.account"].create(
'name': 'test_account_payable', {
'code': '321', "name": "test_account_payable",
'user_type_id': type_payable.id, "code": "321",
'reconcile': True "user_type_id": type_payable.id,
}) "reconcile": True,
}
)
self.account_revenue = self.env['account.account'].create({ self.account_revenue = self.env["account.account"].create(
'name': 'test_account_revenue', {
'code': '864', "name": "test_account_revenue",
'user_type_id': type_revenue.id, "code": "864",
'reconcile': True "user_type_id": type_revenue.id,
}) "reconcile": True,
}
)
def test_01_account_spread_defaults(self): def test_01_account_spread_defaults(self):
this_year = datetime.date.today().year this_year = datetime.date.today().year
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
my_company = self.env.user.company_id my_company = self.env.user.company_id
self.assertTrue(spread) self.assertTrue(spread)
@ -77,21 +91,21 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertFalse(spread.account_analytic_id) self.assertFalse(spread.account_analytic_id)
self.assertFalse(spread.analytic_tag_ids) self.assertFalse(spread.analytic_tag_ids)
self.assertTrue(spread.move_line_auto_post) self.assertTrue(spread.move_line_auto_post)
self.assertEqual(spread.name, 'test') self.assertEqual(spread.name, "test")
self.assertEqual(spread.invoice_type, 'out_invoice') self.assertEqual(spread.invoice_type, "out_invoice")
self.assertEqual(spread.company_id, my_company) self.assertEqual(spread.company_id, my_company)
self.assertEqual(spread.currency_id, my_company.currency_id) self.assertEqual(spread.currency_id, my_company.currency_id)
self.assertEqual(spread.period_number, 12) self.assertEqual(spread.period_number, 12)
self.assertEqual(spread.period_type, 'month') self.assertEqual(spread.period_type, "month")
self.assertEqual(spread.debit_account_id, self.debit_account) self.assertEqual(spread.debit_account_id, self.debit_account)
self.assertEqual(spread.credit_account_id, self.credit_account) self.assertEqual(spread.credit_account_id, self.credit_account)
self.assertEqual(spread.unspread_amount, 0.) self.assertEqual(spread.unspread_amount, 0.0)
self.assertEqual(spread.unposted_amount, 0.) self.assertEqual(spread.unposted_amount, 0.0)
self.assertEqual(spread.total_amount, 0.) self.assertEqual(spread.total_amount, 0.0)
self.assertEqual(spread.estimated_amount, 0.) self.assertEqual(spread.estimated_amount, 0.0)
self.assertEqual(spread.spread_date, datetime.date(this_year, 1, 1)) self.assertEqual(spread.spread_date, datetime.date(this_year, 1, 1))
self.assertTrue(spread.journal_id) self.assertTrue(spread.journal_id)
self.assertEqual(spread.journal_id.type, 'general') self.assertEqual(spread.journal_id.type, "general")
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
@ -104,27 +118,26 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertFalse(my_company.default_spread_revenue_journal_id) self.assertFalse(my_company.default_spread_revenue_journal_id)
self.assertFalse(my_company.default_spread_expense_journal_id) self.assertFalse(my_company.default_spread_expense_journal_id)
@mute_logger('odoo.sql_db') @mute_logger("odoo.sql_db")
def test_03_no_defaults(self): def test_03_no_defaults(self):
with self.assertRaises(IntegrityError): with self.assertRaises(IntegrityError):
self.env['account.spread'].create({ self.env["account.spread"].create(
'name': 'test', {"name": "test",}
}) )
@mute_logger('odoo.sql_db') @mute_logger("odoo.sql_db")
def test_04_no_defaults(self): def test_04_no_defaults(self):
with self.assertRaises(IntegrityError): with self.assertRaises(IntegrityError):
self.env['account.spread'].create({ self.env["account.spread"].create(
'name': 'test', {"name": "test", "invoice_type": "out_invoice",}
'invoice_type': 'out_invoice', )
})
def test_05_config_settings(self): def test_05_config_settings(self):
my_company = self.env.user.company_id my_company = self.env.user.company_id
account_revenue = self.account_revenue account_revenue = self.account_revenue
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal') exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref('account_spread_cost_revenue.sales_journal') sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = self.account_payable my_company.default_spread_expense_account_id = self.account_payable
my_company.default_spread_revenue_journal_id = sales_journal my_company.default_spread_revenue_journal_id = sales_journal
@ -135,9 +148,7 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertTrue(my_company.default_spread_revenue_journal_id) self.assertTrue(my_company.default_spread_revenue_journal_id)
self.assertTrue(my_company.default_spread_expense_journal_id) self.assertTrue(my_company.default_spread_expense_journal_id)
spread = self.env['account.spread'].new({ spread = self.env["account.spread"].new({"name": "test",})
'name': 'test',
})
self.assertTrue(spread) self.assertTrue(spread)
self.assertFalse(spread.line_ids) self.assertFalse(spread.line_ids)
@ -148,66 +159,71 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertFalse(spread.analytic_tag_ids) self.assertFalse(spread.analytic_tag_ids)
self.assertFalse(spread.move_line_auto_post) self.assertFalse(spread.move_line_auto_post)
defaults = (self.env['account.spread'].default_get([ defaults = self.env["account.spread"].default_get(
'company_id', ["company_id", "currency_id",]
'currency_id', )
]))
self.assertEqual(defaults['company_id'], my_company.id) self.assertEqual(defaults["company_id"], my_company.id)
self.assertEqual(defaults['currency_id'], my_company.currency_id.id) self.assertEqual(defaults["currency_id"], my_company.currency_id.id)
spread.invoice_type = 'out_invoice' spread.invoice_type = "out_invoice"
spread.company_id = my_company spread.company_id = my_company
spread.onchange_invoice_type() spread.onchange_invoice_type()
self.assertEqual(spread.debit_account_id, account_revenue) self.assertEqual(spread.debit_account_id, account_revenue)
self.assertFalse(spread.credit_account_id) self.assertFalse(spread.credit_account_id)
self.assertEqual(spread.journal_id.id, sales_journal) self.assertEqual(spread.journal_id.id, sales_journal)
self.assertEqual(spread.spread_type, 'sale') self.assertEqual(spread.spread_type, "sale")
spread.invoice_type = 'in_invoice' spread.invoice_type = "in_invoice"
spread.onchange_invoice_type() spread.onchange_invoice_type()
self.assertEqual(spread.credit_account_id, self.account_payable) self.assertEqual(spread.credit_account_id, self.account_payable)
self.assertEqual(spread.journal_id.id, exp_journal) self.assertEqual(spread.journal_id.id, exp_journal)
self.assertEqual(spread.spread_type, 'purchase') self.assertEqual(spread.spread_type, "purchase")
def test_06_invoice_line_compute_spread_check(self): def test_06_invoice_line_compute_spread_check(self):
invoice_account = self.account_receivable invoice_account = self.account_receivable
invoice_line_account = self.account_expenses invoice_line_account = self.account_expenses
invoice = self.env['account.invoice'].create({ invoice = self.env["account.invoice"].create(
'partner_id': self.env.ref('base.res_partner_2').id, {
'account_id': invoice_account.id, "partner_id": self.env.ref("base.res_partner_2").id,
'type': 'in_invoice', "account_id": invoice_account.id,
}) "type": "in_invoice",
invoice_line = self.env['account.invoice.line'].create({ }
'product_id': self.env.ref('product.product_product_4').id, )
'quantity': 1.0, invoice_line = self.env["account.invoice.line"].create(
'price_unit': 100.0, {
'invoice_id': invoice.id, "product_id": self.env.ref("product.product_product_4").id,
'name': 'product that cost 100', "quantity": 1.0,
'account_id': invoice_line_account.id, "price_unit": 100.0,
}) "invoice_id": invoice.id,
"name": "product that cost 100",
"account_id": invoice_line_account.id,
}
)
invoice_line2 = invoice_line.copy() invoice_line2 = invoice_line.copy()
self.assertFalse(invoice_line.spread_id) self.assertFalse(invoice_line.spread_id)
self.assertEqual(invoice_line.spread_check, 'unlinked') self.assertEqual(invoice_line.spread_check, "unlinked")
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'in_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "in_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
invoice_line.spread_id = spread invoice_line.spread_id = spread
self.assertTrue(invoice_line.spread_id) self.assertTrue(invoice_line.spread_id)
self.assertEqual(invoice_line.spread_check, 'linked') self.assertEqual(invoice_line.spread_check, "linked")
self.assertFalse(invoice_line2.spread_id) self.assertFalse(invoice_line2.spread_id)
self.assertEqual(invoice_line2.spread_check, 'unlinked') self.assertEqual(invoice_line2.spread_check, "unlinked")
invoice.action_invoice_open() invoice.action_invoice_open()
self.assertTrue(invoice_line.spread_id) self.assertTrue(invoice_line.spread_id)
self.assertEqual(invoice_line.spread_check, 'linked') self.assertEqual(invoice_line.spread_check, "linked")
self.assertFalse(invoice_line2.spread_id) self.assertFalse(invoice_line2.spread_id)
self.assertEqual(invoice_line2.spread_check, 'unavailable') self.assertEqual(invoice_line2.spread_check, "unavailable")
self.assertTrue(spread.display_create_all_moves) self.assertTrue(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
@ -216,24 +232,26 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
def test_07_create_spread_template(self): def test_07_create_spread_template(self):
account_revenue = self.account_revenue account_revenue = self.account_revenue
account_payable = self.account_payable account_payable = self.account_payable
spread_template = self.env['account.spread.template'].create({ spread_template = self.env["account.spread.template"].create(
'name': 'test', {
'spread_type': 'sale', "name": "test",
'spread_account_id': account_revenue.id, "spread_type": "sale",
}) "spread_account_id": account_revenue.id,
}
)
my_company = self.env.user.company_id my_company = self.env.user.company_id
self.assertEqual(spread_template.company_id, my_company) self.assertEqual(spread_template.company_id, my_company)
self.assertTrue(spread_template.spread_journal_id) self.assertTrue(spread_template.spread_journal_id)
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal') exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref('account_spread_cost_revenue.sales_journal') sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = account_payable my_company.default_spread_expense_account_id = account_payable
my_company.default_spread_revenue_journal_id = sales_journal my_company.default_spread_revenue_journal_id = sales_journal
my_company.default_spread_expense_journal_id = exp_journal my_company.default_spread_expense_journal_id = exp_journal
spread_template.spread_type = 'purchase' spread_template.spread_type = "purchase"
spread_template.onchange_spread_type() spread_template.onchange_spread_type()
self.assertTrue(spread_template.spread_journal_id) self.assertTrue(spread_template.spread_journal_id)
self.assertTrue(spread_template.spread_account_id) self.assertTrue(spread_template.spread_account_id)
@ -241,14 +259,14 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertEqual(spread_template.spread_journal_id.id, exp_journal) self.assertEqual(spread_template.spread_journal_id.id, exp_journal)
spread_vals = spread_template._prepare_spread_from_template() spread_vals = spread_template._prepare_spread_from_template()
self.assertTrue(spread_vals['name']) self.assertTrue(spread_vals["name"])
self.assertTrue(spread_vals['template_id']) self.assertTrue(spread_vals["template_id"])
self.assertTrue(spread_vals['journal_id']) self.assertTrue(spread_vals["journal_id"])
self.assertTrue(spread_vals['company_id']) self.assertTrue(spread_vals["company_id"])
self.assertTrue(spread_vals['invoice_type']) self.assertTrue(spread_vals["invoice_type"])
self.assertTrue(spread_vals['credit_account_id']) self.assertTrue(spread_vals["credit_account_id"])
spread_template.spread_type = 'sale' spread_template.spread_type = "sale"
spread_template.onchange_spread_type() spread_template.onchange_spread_type()
self.assertTrue(spread_template.spread_journal_id) self.assertTrue(spread_template.spread_journal_id)
self.assertTrue(spread_template.spread_account_id) self.assertTrue(spread_template.spread_account_id)
@ -256,68 +274,74 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertEqual(spread_template.spread_journal_id.id, sales_journal) self.assertEqual(spread_template.spread_journal_id.id, sales_journal)
spread_vals = spread_template._prepare_spread_from_template() spread_vals = spread_template._prepare_spread_from_template()
self.assertTrue(spread_vals['name']) self.assertTrue(spread_vals["name"])
self.assertTrue(spread_vals['template_id']) self.assertTrue(spread_vals["template_id"])
self.assertTrue(spread_vals['journal_id']) self.assertTrue(spread_vals["journal_id"])
self.assertTrue(spread_vals['company_id']) self.assertTrue(spread_vals["company_id"])
self.assertTrue(spread_vals['invoice_type']) self.assertTrue(spread_vals["invoice_type"])
self.assertTrue(spread_vals['debit_account_id']) self.assertTrue(spread_vals["debit_account_id"])
def test_08_check_template_invoice_type(self): def test_08_check_template_invoice_type(self):
account_revenue = self.account_revenue account_revenue = self.account_revenue
template_sale = self.env['account.spread.template'].create({ template_sale = self.env["account.spread.template"].create(
'name': 'test', {
'spread_type': 'sale', "name": "test",
'spread_account_id': account_revenue.id, "spread_type": "sale",
}) "spread_account_id": account_revenue.id,
template_purchase = self.env['account.spread.template'].create({ }
'name': 'test', )
'spread_type': 'purchase', template_purchase = self.env["account.spread.template"].create(
'spread_account_id': self.account_payable.id, {
}) "name": "test",
spread = self.env['account.spread'].create({ "spread_type": "purchase",
'name': 'test', "spread_account_id": self.account_payable.id,
'invoice_type': 'out_invoice', }
'debit_account_id': self.debit_account.id, )
'credit_account_id': self.credit_account.id, spread = self.env["account.spread"].create(
}) {
"name": "test",
"invoice_type": "out_invoice",
"debit_account_id": self.debit_account.id,
"credit_account_id": self.credit_account.id,
}
)
spread.template_id = template_sale spread.template_id = template_sale
self.assertEqual(spread.template_id, template_sale) self.assertEqual(spread.template_id, template_sale)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
spread.template_id = template_purchase spread.template_id = template_purchase
self.assertEqual(spread.invoice_type, 'out_invoice') self.assertEqual(spread.invoice_type, "out_invoice")
spread.onchange_template() spread.onchange_template()
self.assertEqual(spread.invoice_type, 'in_invoice') self.assertEqual(spread.invoice_type, "in_invoice")
spread.template_id = False spread.template_id = False
spread.invoice_type = 'in_invoice' spread.invoice_type = "in_invoice"
spread.template_id = template_purchase spread.template_id = template_purchase
self.assertEqual(spread.template_id, template_purchase) self.assertEqual(spread.template_id, template_purchase)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
spread.template_id = template_sale spread.template_id = template_sale
self.assertEqual(spread.invoice_type, 'in_invoice') self.assertEqual(spread.invoice_type, "in_invoice")
spread.onchange_template() spread.onchange_template()
self.assertEqual(spread.invoice_type, 'out_invoice') self.assertEqual(spread.invoice_type, "out_invoice")
spread.template_id = False spread.template_id = False
spread.invoice_type = 'out_invoice' spread.invoice_type = "out_invoice"
spread.template_id = template_sale spread.template_id = template_sale
self.assertEqual(spread.template_id, template_sale) self.assertEqual(spread.template_id, template_sale)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
spread.invoice_type = 'in_invoice' spread.invoice_type = "in_invoice"
self.assertEqual(spread.invoice_type, 'in_invoice') self.assertEqual(spread.invoice_type, "in_invoice")
spread.onchange_template() spread.onchange_template()
self.assertEqual(spread.invoice_type, 'out_invoice') self.assertEqual(spread.invoice_type, "out_invoice")
spread.template_id = False spread.template_id = False
spread.invoice_type = 'in_invoice' spread.invoice_type = "in_invoice"
spread.template_id = template_purchase spread.template_id = template_purchase
self.assertEqual(spread.template_id, template_purchase) self.assertEqual(spread.template_id, template_purchase)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
spread.invoice_type = 'out_invoice' spread.invoice_type = "out_invoice"
self.assertEqual(spread.invoice_type, 'out_invoice') self.assertEqual(spread.invoice_type, "out_invoice")
spread.onchange_template() spread.onchange_template()
self.assertEqual(spread.invoice_type, 'in_invoice') self.assertEqual(spread.invoice_type, "in_invoice")
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
@ -326,80 +350,96 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
def test_09_wrong_invoice_type(self): def test_09_wrong_invoice_type(self):
invoice_account = self.account_receivable invoice_account = self.account_receivable
invoice_line_account = self.account_expenses invoice_line_account = self.account_expenses
invoice = self.env['account.invoice'].create({ invoice = self.env["account.invoice"].create(
'partner_id': self.env.ref('base.res_partner_2').id, {
'account_id': invoice_account.id, "partner_id": self.env.ref("base.res_partner_2").id,
'type': 'in_invoice', "account_id": invoice_account.id,
}) "type": "in_invoice",
invoice_line = self.env['account.invoice.line'].create({ }
'product_id': self.env.ref('product.product_product_4').id, )
'quantity': 1.0, invoice_line = self.env["account.invoice.line"].create(
'price_unit': 100.0, {
'invoice_id': invoice.id, "product_id": self.env.ref("product.product_product_4").id,
'name': 'product that cost 100', "quantity": 1.0,
'account_id': invoice_line_account.id, "price_unit": 100.0,
}) "invoice_id": invoice.id,
spread = self.env['account.spread'].create({ "name": "product that cost 100",
'name': 'test', "account_id": invoice_line_account.id,
'invoice_type': 'out_invoice', }
'debit_account_id': self.debit_account.id, )
'credit_account_id': self.credit_account.id, spread = self.env["account.spread"].create(
}) {
"name": "test",
"invoice_type": "out_invoice",
"debit_account_id": self.debit_account.id,
"credit_account_id": self.credit_account.id,
}
)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
invoice_line.spread_id = spread invoice_line.spread_id = spread
def test_10_account_spread_unlink(self): def test_10_account_spread_unlink(self):
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
spread.unlink() spread.unlink()
def test_11_compute_display_fields(self): def test_11_compute_display_fields(self):
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
spread.company_id.allow_spread_planning = True spread.company_id.allow_spread_planning = True
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
self.assertTrue(spread.display_move_line_auto_post) self.assertTrue(spread.display_move_line_auto_post)
def test_12_compute_display_fields(self): def test_12_compute_display_fields(self):
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
spread.company_id.allow_spread_planning = False spread.company_id.allow_spread_planning = False
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
self.assertTrue(spread.display_move_line_auto_post) self.assertTrue(spread.display_move_line_auto_post)
def test_13_compute_display_fields(self): def test_13_compute_display_fields(self):
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
spread.company_id.force_move_auto_post = True spread.company_id.force_move_auto_post = True
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)
self.assertFalse(spread.display_move_line_auto_post) self.assertFalse(spread.display_move_line_auto_post)
def test_14_compute_display_fields(self): def test_14_compute_display_fields(self):
spread = self.env['account.spread'].create({ spread = self.env["account.spread"].create(
'name': 'test', {
'invoice_type': 'out_invoice', "name": "test",
'debit_account_id': self.debit_account.id, "invoice_type": "out_invoice",
'credit_account_id': self.credit_account.id, "debit_account_id": self.debit_account.id,
}) "credit_account_id": self.credit_account.id,
}
)
spread.company_id.force_move_auto_post = False spread.company_id.force_move_auto_post = False
self.assertFalse(spread.display_create_all_moves) self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons) self.assertTrue(spread.display_recompute_buttons)

View File

@ -3,64 +3,74 @@
import datetime import datetime
from odoo.tests import common
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.tests import common
class TestComputeSpreadBoard(common.TransactionCase): class TestComputeSpreadBoard(common.TransactionCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
type_receivable = self.env.ref('account.data_account_type_receivable') type_receivable = self.env.ref("account.data_account_type_receivable")
type_expenses = self.env.ref('account.data_account_type_expenses') type_expenses = self.env.ref("account.data_account_type_expenses")
journal = self.env['account.journal'].create({ journal = self.env["account.journal"].create(
'name': 'Test', 'type': 'general', 'code': 'test'}) {"name": "Test", "type": "general", "code": "test"}
)
self.receivable_account = self.env['account.account'].create({ self.receivable_account = self.env["account.account"].create(
'name': 'test_account_receivable', {
'code': '123', "name": "test_account_receivable",
'user_type_id': type_receivable.id, "code": "123",
'reconcile': True "user_type_id": type_receivable.id,
}) "reconcile": True,
}
)
self.expense_account = self.env['account.account'].create({ self.expense_account = self.env["account.account"].create(
'name': 'test account_expenses', {
'code': '765', "name": "test account_expenses",
'user_type_id': type_expenses.id, "code": "765",
'reconcile': True "user_type_id": type_expenses.id,
}) "reconcile": True,
}
)
self.spread_account = self.env['account.account'].create({ self.spread_account = self.env["account.account"].create(
'name': 'test spread account_expenses', {
'code': '321', "name": "test spread account_expenses",
'user_type_id': type_expenses.id, "code": "321",
'reconcile': True "user_type_id": type_expenses.id,
}) "reconcile": True,
}
)
self.spread = self.env['account.spread'].create({ self.spread = self.env["account.spread"].create(
'name': 'test', {
'debit_account_id': self.spread_account.id, "name": "test",
'credit_account_id': self.expense_account.id, "debit_account_id": self.spread_account.id,
'period_number': 12, "credit_account_id": self.expense_account.id,
'period_type': 'month', "period_number": 12,
'spread_date': '2017-02-01', "period_type": "month",
'estimated_amount': 1000.0, "spread_date": "2017-02-01",
'journal_id': journal.id, "estimated_amount": 1000.0,
'invoice_type': 'in_invoice', "journal_id": journal.id,
}) "invoice_type": "in_invoice",
}
)
self.spread2 = self.env['account.spread'].create({ self.spread2 = self.env["account.spread"].create(
'name': 'test2', {
'debit_account_id': self.spread_account.id, "name": "test2",
'credit_account_id': self.expense_account.id, "debit_account_id": self.spread_account.id,
'period_number': 12, "credit_account_id": self.expense_account.id,
'period_type': 'month', "period_number": 12,
'spread_date': '2017-02-01', "period_type": "month",
'estimated_amount': 1000.0, "spread_date": "2017-02-01",
'journal_id': journal.id, "estimated_amount": 1000.0,
'invoice_type': 'out_invoice', "journal_id": journal.id,
}) "invoice_type": "out_invoice",
}
)
def test_01_supplier_invoice(self): def test_01_supplier_invoice(self):
self.spread.compute_spread_board() self.spread.compute_spread_board()
@ -111,11 +121,13 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_02_supplier_invoice(self): def test_02_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7) "period_type": "month",
}) "spread_date": datetime.date(2017, 1, 7),
}
)
self.spread_account.reconcile = True self.spread_account.reconcile = True
self.assertTrue(self.spread_account.reconcile) self.assertTrue(self.spread_account.reconcile)
@ -163,12 +175,14 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_03_supplier_invoice(self): def test_03_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 31), "period_type": "month",
'move_line_auto_post': False "spread_date": datetime.date(2017, 1, 31),
}) "move_line_auto_post": False,
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
@ -249,13 +263,15 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertEqual(datetime.date(2018, 1, 31), spread_lines[12].date) self.assertEqual(datetime.date(2018, 1, 31), spread_lines[12].date)
def test_04_supplier_invoice(self): def test_04_supplier_invoice(self):
self.spread.write({ self.spread.write(
'credit_account_id': self.expense_account.id, {
'debit_account_id': self.spread_account.id, "credit_account_id": self.expense_account.id,
'period_number': 3, "debit_account_id": self.spread_account.id,
'period_type': 'year', "period_number": 3,
'spread_date': datetime.date(2018, 10, 24) "period_type": "year",
}) "spread_date": datetime.date(2018, 10, 24),
}
)
# change the state of invoice to open by clicking Validate button # change the state of invoice to open by clicking Validate button
self.spread.compute_spread_board() self.spread.compute_spread_board()
@ -280,11 +296,13 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_05_supplier_invoice(self): def test_05_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 2, 1) "period_type": "month",
}) "spread_date": datetime.date(2017, 2, 1),
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
@ -295,7 +313,7 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertTrue(isinstance(attrs, dict)) self.assertTrue(isinstance(attrs, dict))
# post and then unlink all created moves # post and then unlink all created moves
self.spread.journal_id.write({'update_posted': True}) self.spread.journal_id.write({"update_posted": True})
for line in self.spread.line_ids: for line in self.spread.line_ids:
line.move_id.post() line.move_id.post()
self.spread.line_ids.unlink_move() self.spread.line_ids.unlink_move()
@ -307,11 +325,9 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_06_supplier_invoice(self): def test_06_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 3, {"period_number": 3, "period_type": "quarter", "move_line_auto_post": False}
'period_type': 'quarter', )
'move_line_auto_post': False
})
self.spread.compute_spread_board() self.spread.compute_spread_board()
@ -328,35 +344,37 @@ class TestComputeSpreadBoard(common.TransactionCase):
for line in self.spread.line_ids: for line in self.spread.line_ids:
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertFalse(line.move_id.state == 'posted') self.assertFalse(line.move_id.state == "posted")
self.assertEqual(self.spread.unspread_amount, 0.) self.assertEqual(self.spread.unspread_amount, 0.0)
self.assertEqual(self.spread.unposted_amount, 1000.) self.assertEqual(self.spread.unposted_amount, 1000.0)
# try to create move lines again: an error is raised # try to create move lines again: an error is raised
for line in self.spread.line_ids: for line in self.spread.line_ids:
with self.assertRaises(UserError): with self.assertRaises(UserError):
line.create_move() line.create_move()
self.spread.write({ self.spread.write(
'move_line_auto_post': True, {"move_line_auto_post": True,}
}) )
self.spread.action_recalculate_spread() self.spread.action_recalculate_spread()
for line in self.spread.line_ids: for line in self.spread.line_ids:
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertTrue(line.move_id.state == 'posted') self.assertTrue(line.move_id.state == "posted")
self.assertEqual(self.spread.unspread_amount, 0.) self.assertEqual(self.spread.unspread_amount, 0.0)
self.assertEqual(self.spread.unposted_amount, 0.) self.assertEqual(self.spread.unposted_amount, 0.0)
def test_07_supplier_invoice(self): def test_07_supplier_invoice(self):
self.spread.write({ self.spread.write(
'period_number': 3, {
'period_type': 'month', "period_number": 3,
'spread_date': datetime.date(2017, 1, 1), "period_type": "month",
'estimated_amount': 345.96, "spread_date": datetime.date(2017, 1, 1),
}) "estimated_amount": 345.96,
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
@ -376,11 +394,13 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_08_supplier_invoice(self): def test_08_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 2, 1) "period_type": "month",
}) "spread_date": datetime.date(2017, 2, 1),
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
self.assertTrue(self.spread.line_ids) self.assertTrue(self.spread.line_ids)
@ -392,11 +412,13 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_09_supplier_invoice(self): def test_09_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 2, 1) "period_type": "month",
}) "spread_date": datetime.date(2017, 2, 1),
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
for line in self.spread.line_ids: for line in self.spread.line_ids:
@ -415,11 +437,11 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertEqual(self.spread.unposted_amount, 1000.0) self.assertEqual(self.spread.unposted_amount, 1000.0)
def test_10_create_entries(self): def test_10_create_entries(self):
self.env['account.spread.line']._create_entries() self.env["account.spread.line"]._create_entries()
self.assertFalse(self.spread.line_ids) self.assertFalse(self.spread.line_ids)
self.spread.compute_spread_board() self.spread.compute_spread_board()
self.env['account.spread.line']._create_entries() self.env["account.spread.line"]._create_entries()
self.assertTrue(self.spread.line_ids) self.assertTrue(self.spread.line_ids)
for line in self.spread.line_ids: for line in self.spread.line_ids:
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
@ -431,7 +453,7 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertFalse(line.move_id) self.assertFalse(line.move_id)
line.create_move() line.create_move()
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertFalse(line.move_id.state == 'posted') self.assertFalse(line.move_id.state == "posted")
self.spread2.action_undo_spread() self.spread2.action_undo_spread()
for line in self.spread2.line_ids: for line in self.spread2.line_ids:
@ -441,18 +463,16 @@ class TestComputeSpreadBoard(common.TransactionCase):
for line in self.spread2.line_ids: for line in self.spread2.line_ids:
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertFalse(line.move_id.state == 'posted') self.assertFalse(line.move_id.state == "posted")
# try to create move lines again: an error is raised # try to create move lines again: an error is raised
with self.assertRaises(UserError): with self.assertRaises(UserError):
line.create_move() line.create_move()
def test_12_supplier_invoice_auto_post(self): def test_12_supplier_invoice_auto_post(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 8, {"period_number": 8, "period_type": "month", "move_line_auto_post": True,}
'period_type': 'month', )
'move_line_auto_post': True,
})
self.spread.compute_spread_board() self.spread.compute_spread_board()
@ -470,16 +490,15 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertTrue(self.spread.move_line_auto_post) self.assertTrue(self.spread.move_line_auto_post)
for line in self.spread.line_ids: for line in self.spread.line_ids:
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertTrue(line.move_id.state == 'posted') self.assertTrue(line.move_id.state == "posted")
self.assertEqual(self.spread.unspread_amount, 0.) self.assertEqual(self.spread.unspread_amount, 0.0)
self.assertEqual(self.spread.unposted_amount, 0.) self.assertEqual(self.spread.unposted_amount, 0.0)
def test_13_create_move_in_invoice_auto_post(self): def test_13_create_move_in_invoice_auto_post(self):
self.spread2.write({ self.spread2.write(
'period_number': 4, {"period_number": 4, "move_line_auto_post": True,}
'move_line_auto_post': True, )
})
self.spread_account.reconcile = True self.spread_account.reconcile = True
self.assertTrue(self.spread_account.reconcile) self.assertTrue(self.spread_account.reconcile)
@ -488,19 +507,21 @@ class TestComputeSpreadBoard(common.TransactionCase):
self.assertFalse(line.move_id) self.assertFalse(line.move_id)
line.create_move() line.create_move()
self.assertTrue(line.move_id) self.assertTrue(line.move_id)
self.assertTrue(line.move_id.state == 'posted') self.assertTrue(line.move_id.state == "posted")
self.assertEqual(self.spread.unspread_amount, 1000.0) self.assertEqual(self.spread.unspread_amount, 1000.0)
self.assertEqual(self.spread.unposted_amount, 1000.0) self.assertEqual(self.spread.unposted_amount, 1000.0)
def test_14_negative_amount(self): def test_14_negative_amount(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'estimated_amount': -1000.0, {
'period_number': 12, "estimated_amount": -1000.0,
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7) "period_type": "month",
}) "spread_date": datetime.date(2017, 1, 7),
}
)
self.spread.compute_spread_board() self.spread.compute_spread_board()
spread_lines = self.spread.line_ids spread_lines = self.spread.line_ids
@ -541,11 +562,13 @@ class TestComputeSpreadBoard(common.TransactionCase):
def test_18_supplier_invoice(self): def test_18_supplier_invoice(self):
# spread date set # spread date set
self.spread.write({ self.spread.write(
'period_number': 12, {
'period_type': 'month', "period_number": 12,
'spread_date': datetime.date(2017, 1, 7) "period_type": "month",
}) "spread_date": datetime.date(2017, 1, 7),
}
)
self.spread_account.reconcile = True self.spread_account.reconcile = True
self.assertTrue(self.spread_account.reconcile) self.assertTrue(self.spread_account.reconcile)
@ -561,10 +584,10 @@ class TestComputeSpreadBoard(common.TransactionCase):
spread_lines[2]._create_moves().post() spread_lines[2]._create_moves().post()
spread_lines[3]._create_moves().post() spread_lines[3]._create_moves().post()
self.assertEqual(spread_lines[0].move_id.state, 'posted') self.assertEqual(spread_lines[0].move_id.state, "posted")
self.assertEqual(spread_lines[1].move_id.state, 'posted') self.assertEqual(spread_lines[1].move_id.state, "posted")
self.assertEqual(spread_lines[2].move_id.state, 'posted') self.assertEqual(spread_lines[2].move_id.state, "posted")
self.assertEqual(spread_lines[3].move_id.state, 'posted') self.assertEqual(spread_lines[3].move_id.state, "posted")
self.assertAlmostEqual(self.spread.unspread_amount, 682.81) self.assertAlmostEqual(self.spread.unspread_amount, 682.81)
self.assertAlmostEqual(self.spread.unposted_amount, 682.81) self.assertAlmostEqual(self.spread.unposted_amount, 682.81)

View File

@ -1,24 +1,35 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_supplier_invoice_spread" model="ir.ui.view"> <record id="view_supplier_invoice_spread" model="ir.ui.view">
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/> <field name="inherit_id" ref="account.invoice_supplier_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='quantity']" position="before"> <xpath
<field name="spread_check" widget="spread_line_widget" groups="account.group_account_user,account.group_account_manager"/> expr="//field[@name='invoice_line_ids']/tree/field[@name='quantity']"
position="before"
>
<field
name="spread_check"
widget="spread_line_widget"
groups="account.group_account_user,account.group_account_manager"
/>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="view_customer_invoice_spread" model="ir.ui.view"> <record id="view_customer_invoice_spread" model="ir.ui.view">
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/> <field name="inherit_id" ref="account.invoice_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='quantity']" position="before"> <xpath
<field name="spread_check" widget="spread_line_widget" groups="account.group_account_user,account.group_account_manager"/> expr="//field[@name='invoice_line_ids']/tree/field[@name='quantity']"
position="before"
>
<field
name="spread_check"
widget="spread_line_widget"
groups="account.group_account_user,account.group_account_manager"
/>
</xpath> </xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -1,177 +1,367 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_account_spread" model="ir.ui.view"> <record id="view_account_spread" model="ir.ui.view">
<field name="model">account.spread</field> <field name="model">account.spread</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<header> <header>
<button name="compute_spread_board" type="object" string="Recalculate unposted lines" class="oe_highlight" attrs="{'invisible': ['|',('debit_account_id', '=', False),('display_recompute_buttons', '=', False)]}" /> <button
<button name="action_recalculate_spread" type="object" string="Recalculate entire spread" attrs="{'invisible': ['|',('debit_account_id', '=', False),('display_recompute_buttons', '=', False)]}" groups="account.group_account_manager" /> name="compute_spread_board"
<button name="action_undo_spread" type="object" string="Undo spread" attrs="{'invisible': [('line_ids', '=', [])]}" groups="account.group_account_manager" /> type="object"
<button name="action_unlink_invoice_line" type="object" string="Unlink Invoice Line" attrs="{'invisible': [('invoice_line_id', '=', False)]}" groups="account.group_account_manager" /> string="Recalculate unposted lines"
class="oe_highlight"
attrs="{'invisible': ['|',('debit_account_id', '=', False),('display_recompute_buttons', '=', False)]}"
/>
<button
name="action_recalculate_spread"
type="object"
string="Recalculate entire spread"
attrs="{'invisible': ['|',('debit_account_id', '=', False),('display_recompute_buttons', '=', False)]}"
groups="account.group_account_manager"
/>
<button
name="action_undo_spread"
type="object"
string="Undo spread"
attrs="{'invisible': [('line_ids', '=', [])]}"
groups="account.group_account_manager"
/>
<button
name="action_unlink_invoice_line"
type="object"
string="Unlink Invoice Line"
attrs="{'invisible': [('invoice_line_id', '=', False)]}"
groups="account.group_account_manager"
/>
</header> </header>
<sheet> <sheet>
<div class="oe_button_box"> <div class="oe_button_box">
<button name="open_reconcile_view" <button
name="open_reconcile_view"
class="oe_stat_button" class="oe_stat_button"
icon="fa-bars" icon="fa-bars"
type="object" type="object"
string="Reconciled entries"> string="Reconciled entries"
>
</button> </button>
<button name="toggle_active" type="object" <button
attrs="{'invisible': [('all_posted','=',False)]}" name="toggle_active"
class="oe_stat_button" icon="fa-archive"> type="object"
<field name="active" widget="boolean_button" attrs="{'invisible': [('all_posted','=',False)]}"
options='{"terminology": "archive"}'/> class="oe_stat_button"
icon="fa-archive"
>
<field
name="active"
widget="boolean_button"
options='{"terminology": "archive"}'
/>
</button> </button>
</div> </div>
<div class="oe_title"> <div class="oe_title">
<label for="name" string="Spread Board Name"/> <label for="name" string="Spread Board Name" />
<h1><field name="name" placeholder="e.g. One year offices cleaning contract"/></h1> <h1>
<field
name="name"
placeholder="e.g. One year offices cleaning contract"
/>
</h1>
</div> </div>
<group name="header_info"> <group name="header_info">
<group name="spread_definitions"> <group name="spread_definitions">
<field name="template_id"/> <field name="template_id" />
<field name="invoice_type" attrs="{'readonly':[('invoice_line_id','!=',False)]}"/> <field
<field name="display_recompute_buttons" invisible="1"/> name="invoice_type"
<field name="display_move_line_auto_post" invisible="1"/> attrs="{'readonly':[('invoice_line_id','!=',False)]}"
<field name="all_posted" invisible="1"/> />
<field name="use_invoice_line_account" invisible="1"/> <field name="display_recompute_buttons" invisible="1" />
<field name="display_move_line_auto_post" invisible="1" />
<field name="all_posted" invisible="1" />
<field name="use_invoice_line_account" invisible="1" />
</group> </group>
</group> </group>
<group name="accounts"> <group name="accounts">
<group name="debits"> <group name="debits">
<field name="is_debit_account_deprecated" invisible="1"/> <field name="is_debit_account_deprecated" invisible="1" />
<label for="debit_account_id" colspan="3" string="Balance sheet account / Spread account" <label
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"/> for="debit_account_id"
<label for="debit_account_id" colspan="3" string="Expense account" colspan="3"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"/> string="Balance sheet account / Spread account"
<div attrs="{'invisible': [('use_invoice_line_account', '=', True)]}" colspan="2"> attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
<span class="help-block" colspan="2" />
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"> <label
The Balance Sheet account used for the spreading.<br/>This account is the counterpart of the account in the invoice line. for="debit_account_id"
colspan="3"
string="Expense account"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
/>
<div
attrs="{'invisible': [('use_invoice_line_account', '=', True)]}"
colspan="2"
>
<span
class="help-block"
colspan="2"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
>
The Balance Sheet account used for the spreading.<br
/>This account is the counterpart of the account in the invoice line.
</span> </span>
<span class="help-block" colspan="2" <span
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"> class="help-block"
The Expense account in the vendor bill line.<br/>Usually the same account of the vendor bill line. colspan="2"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
>
The Expense account in the vendor bill line.<br
/>Usually the same account of the vendor bill line.
</span> </span>
</div> </div>
<div attrs="{'invisible': [('use_invoice_line_account', '!=', True)]}" colspan="2"> <div
<span class="help-block" colspan="2" attrs="{'invisible': [('use_invoice_line_account', '!=', True)]}"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"> colspan="2"
The Balance Sheet account.<br/>This is the account in the invoice line. >
<span
class="help-block"
colspan="2"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
>
The Balance Sheet account.<br
/>This is the account in the invoice line.
</span> </span>
<span class="help-block" colspan="2" <span
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"> class="help-block"
The Expense account used for the spreading.<br/>This account is the counterpart of the account of the vendor bill line. colspan="2"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
>
The Expense account used for the spreading.<br
/>This account is the counterpart of the account of the vendor bill line.
</span> </span>
</div> </div>
<field name="debit_account_id" required="1" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" attrs="{'readonly':[('invoice_line_id','!=',False)]}"/> <field
<span class="help-block text-danger" colspan="2" name="debit_account_id"
attrs="{'invisible':[('is_debit_account_deprecated','!=',True)]}"> required="1"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
attrs="{'readonly':[('invoice_line_id','!=',False)]}"
/>
<span
class="help-block text-danger"
colspan="2"
attrs="{'invisible':[('is_debit_account_deprecated','!=',True)]}"
>
This account in deprecated! The reconciliation will be NOT possible. This account in deprecated! The reconciliation will be NOT possible.
</span> </span>
</group> </group>
<group name="credits"> <group name="credits">
<field name="is_credit_account_deprecated" invisible="1"/> <field name="is_credit_account_deprecated" invisible="1" />
<label for="credit_account_id" colspan="3" string="Revenue account" <label
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"/> for="credit_account_id"
<label for="credit_account_id" colspan="3" string="Balance sheet account / Spread account" colspan="3"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"/> string="Revenue account"
<div attrs="{'invisible': [('use_invoice_line_account', '=', True)]}" colspan="2"> attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
<span class="help-block" colspan="2" />
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"> <label
The Revenue account in the invoice line.<br/>Usually the same account of the invoice line. for="credit_account_id"
colspan="3"
string="Balance sheet account / Spread account"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
/>
<div
attrs="{'invisible': [('use_invoice_line_account', '=', True)]}"
colspan="2"
>
<span
class="help-block"
colspan="2"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
>
The Revenue account in the invoice line.<br
/>Usually the same account of the invoice line.
</span> </span>
<span class="help-block" colspan="2" <span
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"> class="help-block"
The Balance Sheet account used for the spreading.<br/>This account is the counterpart of the account in the vendor bill line. colspan="2"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
>
The Balance Sheet account used for the spreading.<br
/>This account is the counterpart of the account in the vendor bill line.
</span> </span>
</div> </div>
<div attrs="{'invisible': [('use_invoice_line_account', '!=', True)]}" colspan="2"> <div
<span class="help-block" colspan="2" attrs="{'invisible': [('use_invoice_line_account', '!=', True)]}"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"> colspan="2"
The Revenue account used for the spreading.<br/>This account is the counterpart of the account of the invoice line. >
<span
class="help-block"
colspan="2"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
>
The Revenue account used for the spreading.<br
/>This account is the counterpart of the account of the invoice line.
</span> </span>
<span class="help-block" colspan="2" <span
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"> class="help-block"
The Balance Sheet account.<br/>This is the account in the vendor bill line. colspan="2"
attrs="{'invisible':[('invoice_type','not in',('in_invoice','out_refund'))]}"
>
The Balance Sheet account.<br
/>This is the account in the vendor bill line.
</span> </span>
</div> </div>
<field name="credit_account_id" required="1" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" attrs="{'readonly':[('invoice_line_id','!=',False)]}"/> <field
<span class="help-block text-danger" colspan="2" name="credit_account_id"
attrs="{'invisible':[('is_credit_account_deprecated','!=',True)]}"> required="1"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
attrs="{'readonly':[('invoice_line_id','!=',False)]}"
/>
<span
class="help-block text-danger"
colspan="2"
attrs="{'invisible':[('is_credit_account_deprecated','!=',True)]}"
>
This account in deprecated! The reconciliation will be NOT possible. This account in deprecated! The reconciliation will be NOT possible.
</span> </span>
</group> </group>
</group> </group>
<group name="main_info"> <group name="main_info">
<group> <group>
<field name="invoice_id" attrs="{'invisible':[('invoice_id','=',False)]}"/> <field
<field name="invoice_line_id" readonly="1" attrs="{'invisible':[('invoice_line_id','=',False)]}"/> name="invoice_id"
<field name="estimated_amount" attrs="{'readonly':[('invoice_line_id','!=',False)],'invisible':[('estimated_amount','=',0.0),('invoice_line_id','!=',False)]}"/> attrs="{'invisible':[('invoice_id','=',False)]}"
<field name="total_amount" attrs="{'invisible':[('invoice_line_id','=',False)]}"/> />
<field name="move_line_auto_post" attrs="{'invisible':[('display_move_line_auto_post','=',False)]}"/> <field
name="invoice_line_id"
readonly="1"
attrs="{'invisible':[('invoice_line_id','=',False)]}"
/>
<field
name="estimated_amount"
attrs="{'readonly':[('invoice_line_id','!=',False)],'invisible':[('estimated_amount','=',0.0),('invoice_line_id','!=',False)]}"
/>
<field
name="total_amount"
attrs="{'invisible':[('invoice_line_id','=',False)]}"
/>
<field
name="move_line_auto_post"
attrs="{'invisible':[('display_move_line_auto_post','=',False)]}"
/>
</group> </group>
<group> <group>
<field name="period_number"/> <field name="period_number" />
<field name="period_type"/> <field name="period_type" />
<field name="spread_date"/> <field name="spread_date" />
<field name="journal_id" domain="[('company_id', '=', company_id)]" widget="selection"/> <field
name="journal_id"
domain="[('company_id', '=', company_id)]"
widget="selection"
/>
</group> </group>
</group> </group>
<notebook name="notebook"> <notebook name="notebook">
<page name="spread_lines" string="Spread lines"> <page name="spread_lines" string="Spread lines">
<field name="line_ids" readonly="1"> <field name="line_ids" readonly="1">
<tree> <tree>
<field name="name" readonly="1"/> <field name="name" readonly="1" />
<field name="amount" attrs="{'readonly':[('move_id','!=',False)]}" sum="Total"/> <field
<field name="date" readonly="1"/> name="amount"
<field name="move_id" readonly="1"/> attrs="{'readonly':[('move_id','!=',False)]}"
<button name="create_move" icon="fa-play" string="Create Move" type="object" groups="account.group_account_manager" sum="Total"
attrs="{'invisible':['|',('move_id','!=',False)]}"/> />
<button name="open_move" icon="fa-plus-square-o" string="View Move" type="object" <field name="date" readonly="1" />
attrs="{'invisible':[('move_id','=',False)]}"/> <field name="move_id" readonly="1" />
<button name="unlink_move" icon="fa-times" string="Delete Move" type="object" confirm="This will delete the move. Are you sure ?" groups="account.group_account_manager" <button
attrs="{'invisible':[('move_id','=',False)]}"/> name="create_move"
icon="fa-play"
string="Create Move"
type="object"
groups="account.group_account_manager"
attrs="{'invisible':['|',('move_id','!=',False)]}"
/>
<button
name="open_move"
icon="fa-plus-square-o"
string="View Move"
type="object"
attrs="{'invisible':[('move_id','=',False)]}"
/>
<button
name="unlink_move"
icon="fa-times"
string="Delete Move"
type="object"
confirm="This will delete the move. Are you sure ?"
groups="account.group_account_manager"
attrs="{'invisible':[('move_id','=',False)]}"
/>
</tree> </tree>
</field> </field>
<group name="extension"> <group name="extension">
<group name="extension_left"> <group name="extension_left">
</group> </group>
<group name="extension_right"> <group name="extension_right">
<field name="display_create_all_moves" invisible="1"/> <field
<button name="create_all_moves" string="Create All Moves" type="object" name="display_create_all_moves"
icon="fa-play" attrs="{'invisible':[('display_create_all_moves','!=',True)]}"/> invisible="1"
<field name="unspread_amount" attrs="{'invisible': [('unspread_amount', '=', 0)]}" /> />
<field name="unposted_amount" attrs="{'invisible': [('unposted_amount', '=', 0)]}" /> <button
<field name="posted_amount" attrs="{'invisible': [('posted_amount', '=', 0)]}" /> name="create_all_moves"
string="Create All Moves"
type="object"
icon="fa-play"
attrs="{'invisible':[('display_create_all_moves','!=',True)]}"
/>
<field
name="unspread_amount"
attrs="{'invisible': [('unspread_amount', '=', 0)]}"
/>
<field
name="unposted_amount"
attrs="{'invisible': [('unposted_amount', '=', 0)]}"
/>
<field
name="posted_amount"
attrs="{'invisible': [('posted_amount', '=', 0)]}"
/>
</group> </group>
</group> </group>
</page> </page>
<page name="details" string="Details"> <page name="details" string="Details">
<group name="extra_details"> <group name="extra_details">
<group> <group>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/> <field
<field name="currency_id" groups="base.group_multi_currency"/> name="company_id"
groups="base.group_multi_company"
options="{'no_create': True}"
/>
<field
name="currency_id"
groups="base.group_multi_currency"
/>
</group> </group>
<group> <group>
<field name="account_analytic_id" domain="[('company_id', '=', company_id)]" groups="analytic.group_analytic_accounting" options="{'no_create': True}"/> <field
<field name="analytic_tag_ids" groups="analytic.group_analytic_accounting" widget="many2many_tags"/> name="account_analytic_id"
domain="[('company_id', '=', company_id)]"
groups="analytic.group_analytic_accounting"
options="{'no_create': True}"
/>
<field
name="analytic_tag_ids"
groups="analytic.group_analytic_accounting"
widget="many2many_tags"
/>
</group> </group>
</group> </group>
</page> </page>
</notebook> </notebook>
</sheet> </sheet>
<div class="oe_chatter"> <div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/> <field name="message_follower_ids" widget="mail_followers" />
<field name="message_ids" widget="mail_thread"/> <field name="message_ids" widget="mail_thread" />
</div> </div>
</form> </form>
</field> </field>
</record> </record>
<record id="view_account_spread_account_manager" model="ir.ui.view"> <record id="view_account_spread_account_manager" model="ir.ui.view">
<field name="model">account.spread</field> <field name="model">account.spread</field>
<field name="inherit_id" ref="view_account_spread" /> <field name="inherit_id" ref="view_account_spread" />
@ -181,44 +371,45 @@
<attribute name="editable">1</attribute> <attribute name="editable">1</attribute>
</tree> </tree>
<field name="amount" position="attributes"> <field name="amount" position="attributes">
<attribute name="readonly"/> <attribute name="readonly" />
</field> </field>
<field name="line_ids" position="attributes"> <field name="line_ids" position="attributes">
<attribute name="readonly"/> <attribute name="readonly" />
</field> </field>
</field> </field>
</record> </record>
<record id="view_account_spread_tree" model="ir.ui.view"> <record id="view_account_spread_tree" model="ir.ui.view">
<field name="model">account.spread</field> <field name="model">account.spread</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="name"/> <field name="name" />
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company" />
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_account_spread_search" model="ir.ui.view"> <record id="view_account_spread_search" model="ir.ui.view">
<field name="model">account.spread</field> <field name="model">account.spread</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/> <filter
</search> string="Archived"
name="inactive"
domain="[('active','=',False)]"
/>
</search>
</field> </field>
</record> </record>
<record id="action_account_spread_form" model="ir.actions.act_window"> <record id="action_account_spread_form" model="ir.actions.act_window">
<field name="name">Spread Costs/Revenues</field> <field name="name">Spread Costs/Revenues</field>
<field name="res_model">account.spread</field> <field name="res_model">account.spread</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
<field name="view_id" ref="view_account_spread_tree"/> <field name="view_id" ref="view_account_spread_tree" />
</record> </record>
<menuitem
<menuitem id="menu_action_account_spread_form" id="menu_action_account_spread_form"
parent="account.menu_finance_entries_accounting_entries" parent="account.menu_finance_entries_accounting_entries"
action="action_account_spread_form" action="action_account_spread_form"
groups="account.group_account_user,account.group_account_manager"/> groups="account.group_account_user,account.group_account_manager"
/>
</odoo> </odoo>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_account_spread_template" model="ir.ui.view"> <record id="view_account_spread_template" model="ir.ui.view">
<field name="model">account.spread.template</field> <field name="model">account.spread.template</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@ -9,68 +8,94 @@
</header> </header>
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<label for="name" string="Spread Template Name"/> <label for="name" string="Spread Template Name" />
<h1><field name="name" placeholder="e.g. Template cleaning contract"/></h1> <h1>
<field
name="name"
placeholder="e.g. Template cleaning contract"
/>
</h1>
</div> </div>
<group name="main_info"> <group name="main_info">
<group> <group>
<field name="spread_type"/> <field name="spread_type" />
<field name="company_id" groups="base.group_multi_company"/> <field
<field name="period_number"/> name="company_id"
<field name="period_type"/> groups="base.group_multi_company"
<field name="start_date"/> />
<field name="period_number" />
<field name="period_type" />
<field name="start_date" />
</group> </group>
<group> <group>
<field name="use_invoice_line_account"/> <field name="use_invoice_line_account" />
<field name="spread_account_id" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" options="{'no_create': True}" <field
attrs="{'required': [('use_invoice_line_account', '!=', True)], 'invisible': [('use_invoice_line_account', '=', True)]}" /> name="spread_account_id"
<field name="exp_rev_account_id" attrs="{'invisible': ['|', ('use_invoice_line_account', '=', False)], 'required': [('use_invoice_line_account', '=', True)]}" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" options="{'no_create': True}"/> domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
<field name="spread_journal_id" domain="[('company_id', '=', company_id)]" widget="selection"/> options="{'no_create': True}"
attrs="{'required': [('use_invoice_line_account', '!=', True)], 'invisible': [('use_invoice_line_account', '=', True)]}"
/>
<field
name="exp_rev_account_id"
attrs="{'invisible': ['|', ('use_invoice_line_account', '=', False)], 'required': [('use_invoice_line_account', '=', True)]}"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
options="{'no_create': True}"
/>
<field
name="spread_journal_id"
domain="[('company_id', '=', company_id)]"
widget="selection"
/>
</group> </group>
</group> </group>
<div> <div>
<field name="auto_spread"/> <field name="auto_spread" />
<label for="auto_spread"/> <label for="auto_spread" />
</div> </div>
<p attrs="{'invisible': [('auto_spread', '!=', True)]}"> <p attrs="{'invisible': [('auto_spread', '!=', True)]}">
Automatically use this spread template on invoice validation for invoice lines using below product and/or account and/or analytic, Automatically use this spread template on invoice validation for invoice lines using below product and/or account and/or analytic,
</p> </p>
<field name="auto_spread_ids" attrs="{'invisible': [('auto_spread', '!=', True)]}" nolabel="1"> <field
name="auto_spread_ids"
attrs="{'invisible': [('auto_spread', '!=', True)]}"
nolabel="1"
>
<tree editable="bottom"> <tree editable="bottom">
<field name="name"/> <field name="name" />
<field name="product_id"/> <field name="product_id" />
<field name="account_id"/> <field name="account_id" />
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/> <field
name="analytic_account_id"
groups="analytic.group_analytic_accounting"
/>
</tree> </tree>
</field> </field>
</sheet> </sheet>
</form> </form>
</field> </field>
</record> </record>
<record id="view_account_spread_template_tree" model="ir.ui.view"> <record id="view_account_spread_template_tree" model="ir.ui.view">
<field name="model">account.spread.template</field> <field name="model">account.spread.template</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="name"/> <field name="name" />
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company" />
<field name="spread_account_id"/> <field name="spread_account_id" />
<field name="spread_journal_id"/> <field name="spread_journal_id" />
</tree> </tree>
</field> </field>
</record> </record>
<record id="action_account_spread_template_form" model="ir.actions.act_window"> <record id="action_account_spread_template_form" model="ir.actions.act_window">
<field name="name">Spread Templates</field> <field name="name">Spread Templates</field>
<field name="res_model">account.spread.template</field> <field name="res_model">account.spread.template</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
<field name="view_id" ref="view_account_spread_template_tree"/> <field name="view_id" ref="view_account_spread_template_tree" />
</record> </record>
<menuitem
<menuitem id="menu_action_account_spread_template_form" id="menu_action_account_spread_template_form"
parent="account.account_account_menu" parent="account.account_account_menu"
action="action_account_spread_template_form" action="action_account_spread_template_form"
groups="account.group_account_manager"/> groups="account.group_account_manager"
/>
</odoo> </odoo>

View File

@ -1,34 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_company_form" model="ir.ui.view"> <record id="view_company_form" model="ir.ui.view">
<field name="model">res.company</field> <field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" /> <field name="inherit_id" ref="base.view_company_form" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//notebook"> <xpath expr="//notebook">
<page name="account_spread_cost_revenue" string="Account Spread" groups="account.group_account_manager"> <page
name="account_spread_cost_revenue"
string="Account Spread"
groups="account.group_account_manager"
>
<group> <group>
<group string="Default Spread Accounts" name="default_spread_accounts"> <group
string="Default Spread Accounts"
name="default_spread_accounts"
>
<field name="default_spread_revenue_account_id" /> <field name="default_spread_revenue_account_id" />
<field name="default_spread_expense_account_id" /> <field name="default_spread_expense_account_id" />
</group> </group>
<group string="Default Spread Journals" name="default_spread_journals"> <group
string="Default Spread Journals"
name="default_spread_journals"
>
<field name="default_spread_revenue_journal_id" /> <field name="default_spread_revenue_journal_id" />
<field name="default_spread_expense_journal_id" /> <field name="default_spread_expense_journal_id" />
</group> </group>
</group> </group>
<group name="spreading_options"> <group name="spreading_options">
<group name="spreading_options_left"> <group name="spreading_options_left">
<field name="allow_spread_planning"/> <field name="allow_spread_planning" />
</group> </group>
<group name="spreading_options_right"> <group name="spreading_options_right">
<field name="force_move_auto_post"/> <field name="force_move_auto_post" />
<field name="auto_archive"/> <field name="auto_archive" />
</group> </group>
</group> </group>
</page> </page>
</xpath> </xpath>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -5,90 +5,85 @@ from odoo import _, api, fields, models
class AccountSpreadInvoiceLineLinkWizard(models.TransientModel): class AccountSpreadInvoiceLineLinkWizard(models.TransientModel):
_name = 'account.spread.invoice.line.link.wizard' _name = "account.spread.invoice.line.link.wizard"
_description = 'Account Spread Invoice Line Link Wizard' _description = "Account Spread Invoice Line Link Wizard"
def _selection_spread_action_type(self): def _selection_spread_action_type(self):
base_selection = [ base_selection = [
('template', _('Create from spread template')), ("template", _("Create from spread template")),
('new', _('Create new spread board')) ("new", _("Create new spread board")),
] ]
if not self.env.context.get('allow_spread_planning'): if not self.env.context.get("allow_spread_planning"):
return base_selection return base_selection
link_selection = [ link_selection = [
('link', _('Link to existing spread board')), ("link", _("Link to existing spread board")),
] ]
return link_selection + base_selection return link_selection + base_selection
def _selection_default_spread_action_type(self): def _selection_default_spread_action_type(self):
if not self.env.context.get('allow_spread_planning'): if not self.env.context.get("allow_spread_planning"):
return 'template' return "template"
return 'link' return "link"
invoice_line_id = fields.Many2one( invoice_line_id = fields.Many2one(
'account.invoice.line', "account.invoice.line",
string='Invoice Line', string="Invoice Line",
readonly=True, readonly=True,
required=True, required=True,
ondelete='cascade') ondelete="cascade",
invoice_id = fields.Many2one( )
related='invoice_line_id.invoice_id', invoice_id = fields.Many2one(related="invoice_line_id.invoice_id", readonly=True)
readonly=True) invoice_type = fields.Selection(
invoice_type = fields.Selection([ [
('out_invoice', 'Customer Invoice'), ("out_invoice", "Customer Invoice"),
('in_invoice', 'Vendor Bill'), ("in_invoice", "Vendor Bill"),
('out_refund', 'Customer Credit Note'), ("out_refund", "Customer Credit Note"),
('in_refund', 'Vendor Credit Note')], ("in_refund", "Vendor Credit Note"),
compute='_compute_invoice_type', ],
store=True) compute="_compute_invoice_type",
spread_type = fields.Selection([ store=True,
('sale', 'Customer'), )
('purchase', 'Supplier')], spread_type = fields.Selection(
compute='_compute_invoice_type', [("sale", "Customer"), ("purchase", "Supplier")],
store=True) compute="_compute_invoice_type",
spread_id = fields.Many2one( store=True,
'account.spread', )
string='Spread Board') spread_id = fields.Many2one("account.spread", string="Spread Board")
company_id = fields.Many2one( company_id = fields.Many2one("res.company", string="Company", required=True)
'res.company',
string='Company',
required=True)
spread_action_type = fields.Selection( spread_action_type = fields.Selection(
selection=_selection_spread_action_type, selection=_selection_spread_action_type,
default=_selection_default_spread_action_type) default=_selection_default_spread_action_type,
template_id = fields.Many2one( )
'account.spread.template', template_id = fields.Many2one("account.spread.template", string="Spread Template")
string='Spread Template')
use_invoice_line_account = fields.Boolean( use_invoice_line_account = fields.Boolean(
string="Use invoice line's account", string="Use invoice line's account",
help="Use invoice line's account as Balance sheet / spread account.\n" help="Use invoice line's account as Balance sheet / spread account.\n"
"In this case, user need to select expense/revenue account too.") "In this case, user need to select expense/revenue account too.",
)
spread_account_id = fields.Many2one( spread_account_id = fields.Many2one(
'account.account', "account.account", string="Balance sheet account / Spread account", store=True
string='Balance sheet account / Spread account', )
store=True)
exp_rev_account_id = fields.Many2one( exp_rev_account_id = fields.Many2one(
'account.account', "account.account",
string='Expense/revenue account', string="Expense/revenue account",
help="Optional account to overwrite the existing expense/revenue " help="Optional account to overwrite the existing expense/revenue " "account",
"account") )
spread_journal_id = fields.Many2one( spread_journal_id = fields.Many2one(
'account.journal', "account.journal", string="Spread Journal", store=True
string='Spread Journal', )
store=True)
@api.depends('invoice_line_id') @api.depends("invoice_line_id")
def _compute_invoice_type(self): def _compute_invoice_type(self):
for wizard in self: for wizard in self:
invoice = wizard.invoice_line_id.invoice_id invoice = wizard.invoice_line_id.invoice_id
wizard.invoice_type = invoice.type wizard.invoice_type = invoice.type
if invoice.type in ['out_invoice', 'out_refund']: if invoice.type in ["out_invoice", "out_refund"]:
wizard.spread_type = 'sale' wizard.spread_type = "sale"
else: else:
wizard.spread_type = 'purchase' wizard.spread_type = "purchase"
@api.onchange('company_id', 'invoice_type') @api.onchange("company_id", "invoice_type")
def _onchange_spread_journal_account(self): def _onchange_spread_journal_account(self):
for wizard in self: for wizard in self:
company = wizard.company_id company = wizard.company_id
@ -96,7 +91,7 @@ class AccountSpreadInvoiceLineLinkWizard(models.TransientModel):
acc_expense = company.default_spread_expense_account_id acc_expense = company.default_spread_expense_account_id
journal_revenue = company.default_spread_revenue_journal_id journal_revenue = company.default_spread_revenue_journal_id
journal_expense = company.default_spread_expense_journal_id journal_expense = company.default_spread_expense_journal_id
if wizard.invoice_type in ('out_invoice', 'in_refund'): if wizard.invoice_type in ("out_invoice", "in_refund"):
wizard.spread_account_id = acc_revenue wizard.spread_account_id = acc_revenue
wizard.spread_journal_id = journal_revenue wizard.spread_journal_id = journal_revenue
else: else:
@ -108,47 +103,51 @@ class AccountSpreadInvoiceLineLinkWizard(models.TransientModel):
"""Keep this for making the fields editable""" """Keep this for making the fields editable"""
pass pass
@api.onchange('invoice_type') @api.onchange("invoice_type")
def onchange_invoice_type(self): def onchange_invoice_type(self):
domain = [ domain = [
('invoice_id', '=', False), ("invoice_id", "=", False),
('invoice_type', '=', self.invoice_type), ("invoice_type", "=", self.invoice_type),
('company_id', '=', self.company_id.id)] ("company_id", "=", self.company_id.id),
res = {'domain': {'spread_id': domain}} ]
res = {"domain": {"spread_id": domain}}
return res return res
@api.onchange('use_invoice_line_account') @api.onchange("use_invoice_line_account")
def _onchange_user_invoice_line_account(self): def _onchange_user_invoice_line_account(self):
self.spread_account_id = (self.use_invoice_line_account and self.spread_account_id = (
self.invoice_line_id.account_id or False) self.use_invoice_line_account and self.invoice_line_id.account_id or False
)
self.exp_rev_account_id = False self.exp_rev_account_id = False
@api.multi @api.multi
def confirm(self): def confirm(self):
self.ensure_one() self.ensure_one()
if self.spread_action_type == 'link': if self.spread_action_type == "link":
if not self.invoice_line_id.spread_id: if not self.invoice_line_id.spread_id:
self.invoice_line_id.spread_id = self.spread_id self.invoice_line_id.spread_id = self.spread_id
return { return {
'name': _('Spread Details'), "name": _("Spread Details"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.spread', "res_model": "account.spread",
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'target': 'current', "target": "current",
'readonly': False, "readonly": False,
'res_id': self.invoice_line_id.spread_id.id, "res_id": self.invoice_line_id.spread_id.id,
} }
elif self.spread_action_type == 'new': elif self.spread_action_type == "new":
debit_account = credit_account = self.spread_account_id debit_account = credit_account = self.spread_account_id
if self.invoice_type in ('out_invoice', 'in_refund'): if self.invoice_type in ("out_invoice", "in_refund"):
credit_account = (self.exp_rev_account_id or credit_account = (
self.invoice_line_id.account_id) self.exp_rev_account_id or self.invoice_line_id.account_id
)
else: else:
debit_account = (self.exp_rev_account_id or debit_account = (
self.invoice_line_id.account_id) self.exp_rev_account_id or self.invoice_line_id.account_id
)
analytic_account = self.invoice_line_id.account_analytic_id analytic_account = self.invoice_line_id.account_analytic_id
analytic_tags = self.invoice_line_id.analytic_tag_ids analytic_tags = self.invoice_line_id.analytic_tag_ids
@ -156,27 +155,27 @@ class AccountSpreadInvoiceLineLinkWizard(models.TransientModel):
use_il_account = self.use_invoice_line_account use_il_account = self.use_invoice_line_account
return { return {
'name': _('New Spread Board'), "name": _("New Spread Board"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.spread', "res_model": "account.spread",
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'target': 'current', "target": "current",
'readonly': False, "readonly": False,
'context': { "context": {
'default_name': self.invoice_line_id.name, "default_name": self.invoice_line_id.name,
'default_invoice_type': self.invoice_type, "default_invoice_type": self.invoice_type,
'default_invoice_line_id': self.invoice_line_id.id, "default_invoice_line_id": self.invoice_line_id.id,
'default_use_invoice_line_account': use_il_account, "default_use_invoice_line_account": use_il_account,
'default_debit_account_id': debit_account.id, "default_debit_account_id": debit_account.id,
'default_credit_account_id': credit_account.id, "default_credit_account_id": credit_account.id,
'default_journal_id': self.spread_journal_id.id, "default_journal_id": self.spread_journal_id.id,
'default_account_analytic_id': analytic_account.id, "default_account_analytic_id": analytic_account.id,
'default_analytic_tag_ids': analytic_tags.ids, "default_analytic_tag_ids": analytic_tags.ids,
'default_spread_date': date_invoice, "default_spread_date": date_invoice,
}, },
} }
elif self.spread_action_type == 'template': elif self.spread_action_type == "template":
if not self.invoice_line_id.spread_id: if not self.invoice_line_id.spread_id:
account = self.invoice_line_id.account_id account = self.invoice_line_id.account_id
spread_account_id = False spread_account_id = False
@ -190,34 +189,34 @@ class AccountSpreadInvoiceLineLinkWizard(models.TransientModel):
date_invoice = self.invoice_id.date_invoice date_invoice = self.invoice_id.date_invoice
date_invoice = date_invoice or self.template_id.start_date date_invoice = date_invoice or self.template_id.start_date
date_invoice = date_invoice or fields.Date.today() date_invoice = date_invoice or fields.Date.today()
spread_vals['spread_date'] = date_invoice spread_vals["spread_date"] = date_invoice
spread_vals['name'] = ('%s %s') % ( spread_vals["name"] = ("%s %s") % (
spread_vals['name'], spread_vals["name"],
self.invoice_line_id.name self.invoice_line_id.name,
) )
if spread_vals['invoice_type'] == 'out_invoice': if spread_vals["invoice_type"] == "out_invoice":
spread_vals['credit_account_id'] = account.id spread_vals["credit_account_id"] = account.id
else: else:
spread_vals['debit_account_id'] = account.id spread_vals["debit_account_id"] = account.id
analytic_account = self.invoice_line_id.account_analytic_id analytic_account = self.invoice_line_id.account_analytic_id
spread_vals['account_analytic_id'] = analytic_account.id spread_vals["account_analytic_id"] = analytic_account.id
spread = self.env['account.spread'].create(spread_vals) spread = self.env["account.spread"].create(spread_vals)
analytic_tags = self.invoice_line_id.analytic_tag_ids analytic_tags = self.invoice_line_id.analytic_tag_ids
spread.analytic_tag_ids = analytic_tags spread.analytic_tag_ids = analytic_tags
self.invoice_line_id.spread_id = spread self.invoice_line_id.spread_id = spread
return { return {
'name': _('Spread Details'), "name": _("Spread Details"),
'view_type': 'form', "view_type": "form",
'view_mode': 'form', "view_mode": "form",
'res_model': 'account.spread', "res_model": "account.spread",
'type': 'ir.actions.act_window', "type": "ir.actions.act_window",
'target': 'current', "target": "current",
'readonly': False, "readonly": False,
'res_id': self.invoice_line_id.spread_id.id, "res_id": self.invoice_line_id.spread_id.id,
} }

View File

@ -1,34 +1,69 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_account_spread_invoice_line_link_wizard" model="ir.ui.view"> <record id="view_account_spread_invoice_line_link_wizard" model="ir.ui.view">
<field name="model">account.spread.invoice.line.link.wizard</field> <field name="model">account.spread.invoice.line.link.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<group name="main_info"> <group name="main_info">
<group> <group>
<field name="company_id" readonly="1" groups="base.group_multi_company"/> <field
<field name="invoice_type" readonly="1"/> name="company_id"
<field name="spread_type" invisible="1"/> readonly="1"
<field name="invoice_id" readonly="1"/> groups="base.group_multi_company"
<field name="invoice_line_id" readonly="1"/> />
<field name="invoice_type" readonly="1" />
<field name="spread_type" invisible="1" />
<field name="invoice_id" readonly="1" />
<field name="invoice_line_id" readonly="1" />
</group> </group>
<group> <group>
<field name="spread_action_type" widget="radio"/> <field name="spread_action_type" widget="radio" />
<field name="spread_id" attrs="{'invisible': [('spread_action_type', '!=', 'link')],'required': [('spread_action_type', '=', 'link')]}" domain="[('invoice_type', '=', invoice_type)]" options="{'no_create': True}"/> <field
<field name="template_id" attrs="{'invisible': [('spread_action_type', '!=', 'template')],'required': [('spread_action_type', '=', 'template')]}" domain="[('spread_type', '=', spread_type)]" options="{'no_create': True}"/> name="spread_id"
<field name="use_invoice_line_account" attrs="{'invisible': [('spread_action_type', '!=', 'new')]}"/> attrs="{'invisible': [('spread_action_type', '!=', 'link')],'required': [('spread_action_type', '=', 'link')]}"
<field name="spread_account_id" attrs="{'invisible': [('spread_action_type', '!=', 'new')],'required': [('spread_action_type', '=', 'new')]}" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" options="{'no_create': True}"/> domain="[('invoice_type', '=', invoice_type)]"
<field name="exp_rev_account_id" attrs="{'invisible': ['|', ('use_invoice_line_account', '=', False), ('spread_action_type', '!=', 'new')], 'required': [('use_invoice_line_account', '=', True)]}" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" options="{'no_create': True}"/> options="{'no_create': True}"
<field name="spread_journal_id" attrs="{'invisible': [('spread_action_type', '!=', 'new')],'required': [('spread_action_type', '=', 'new')]}" domain="[('company_id', '=', company_id)]" options="{'no_create': True}"/> />
<field
name="template_id"
attrs="{'invisible': [('spread_action_type', '!=', 'template')],'required': [('spread_action_type', '=', 'template')]}"
domain="[('spread_type', '=', spread_type)]"
options="{'no_create': True}"
/>
<field
name="use_invoice_line_account"
attrs="{'invisible': [('spread_action_type', '!=', 'new')]}"
/>
<field
name="spread_account_id"
attrs="{'invisible': [('spread_action_type', '!=', 'new')],'required': [('spread_action_type', '=', 'new')]}"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
options="{'no_create': True}"
/>
<field
name="exp_rev_account_id"
attrs="{'invisible': ['|', ('use_invoice_line_account', '=', False), ('spread_action_type', '!=', 'new')], 'required': [('use_invoice_line_account', '=', True)]}"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
options="{'no_create': True}"
/>
<field
name="spread_journal_id"
attrs="{'invisible': [('spread_action_type', '!=', 'new')],'required': [('spread_action_type', '=', 'new')]}"
domain="[('company_id', '=', company_id)]"
options="{'no_create': True}"
/>
</group> </group>
</group> </group>
<footer> <footer>
<button string="Confirm" type="object" name="confirm" class="btn-primary"/> <button
string="Confirm"
type="object"
name="confirm"
class="btn-primary"
/>
<button string="Cancel" class="oe_link" special="cancel" /> <button string="Cancel" class="oe_link" special="cancel" />
</footer> </footer>
</form> </form>
</field> </field>
</record> </record>
</odoo> </odoo>