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",
"website": "https://github.com/OCA/account-financial-tools/",
"category": "Accounting & Finance",
"depends": [
"account",
],
"depends": ["account",],
"data": [
"security/ir.model.access.csv",
"security/account_spread_security.xml",

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="ir_cron_spread_create_entries" forcecreate="True" model="ir.cron">
<field name="name">Cost/revenue Spread: Create Entries</field>
<field name="active" eval="True" />
@ -13,5 +12,4 @@
<field name="state">code</field>
<field name="code">model._create_entries()</field>
</record>
</odoo>

View File

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

View File

@ -6,27 +6,27 @@ from odoo.exceptions import UserError
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
_inherit = "account.invoice.line"
spread_id = fields.Many2one(
'account.spread',
string='Spread Board',
copy=False)
spread_check = fields.Selection([
('linked', 'Linked'),
('unlinked', 'Unlinked'),
('unavailable', 'Unavailable')
], compute='_compute_spread_check')
spread_id = fields.Many2one("account.spread", string="Spread Board", copy=False)
spread_check = fields.Selection(
[
("linked", "Linked"),
("unlinked", "Unlinked"),
("unavailable", "Unavailable"),
],
compute="_compute_spread_check",
)
@api.depends('spread_id', 'invoice_id.state')
@api.depends("spread_id", "invoice_id.state")
def _compute_spread_check(self):
for line in self:
if line.spread_id:
line.spread_check = 'linked'
elif line.invoice_id.state == 'draft':
line.spread_check = 'unlinked'
line.spread_check = "linked"
elif line.invoice_id.state == "draft":
line.spread_check = "unlinked"
else:
line.spread_check = 'unavailable'
line.spread_check = "unavailable"
@api.multi
def spread_details(self):
@ -38,14 +38,14 @@ class AccountInvoiceLine(models.Model):
if self.spread_id:
return {
'name': _('Spread Details'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.spread',
'type': 'ir.actions.act_window',
'target': 'current',
'readonly': False,
'res_id': self.spread_id.id,
"name": _("Spread Details"),
"view_type": "form",
"view_mode": "form",
"res_model": "account.spread",
"type": "ir.actions.act_window",
"target": "current",
"readonly": False,
"res_id": self.spread_id.id,
}
# 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,
)
return {
'name': _('Link Invoice Line with Spread Board'),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.spread.invoice.line.link.wizard',
'type': 'ir.actions.act_window',
'target': 'new',
'context': ctx,
"name": _("Link Invoice Line with Spread Board"),
"view_type": "form",
"view_mode": "form",
"res_model": "account.spread.invoice.line.link.wizard",
"type": "ir.actions.act_window",
"target": "new",
"context": ctx,
}
def create_auto_spread(self):
@ -76,33 +76,46 @@ class AccountInvoiceLine(models.Model):
return False
if aline.account_id and iline.account_id != aline.account_id:
return False
if aline.analytic_account_id and \
iline.account_analytic_id != aline.analytic_account_id:
if (
aline.analytic_account_id
and iline.account_analytic_id != aline.analytic_account_id
):
return False
return True
for line in self:
if line.spread_check == 'linked':
if line.spread_check == "linked":
continue
spread_type = (
'sale' if line.invoice_type in ['out_invoice', 'out_refund']
else 'purchase')
spread_auto = self.env['account.spread.template.auto'].search(
[('template_id.auto_spread', '=', True),
('template_id.spread_type', '=', spread_type)])
"sale"
if line.invoice_type in ["out_invoice", "out_refund"]
else "purchase"
)
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))
template = matched.mapped('template_id')
template = matched.mapped("template_id")
if not template:
continue
elif len(template) > 1:
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
wizard = self.env['account.spread.invoice.line.link.wizard'].new({
'invoice_line_id': line.id,
'company_id': line.company_id.id,
'spread_action_type': 'template',
'template_id': template.id,
})
wizard = self.env["account.spread.invoice.line.link.wizard"].new(
{
"invoice_line_id": line.id,
"company_id": line.company_id.id,
"spread_action_type": "template",
"template_id": template.id,
}
)
wizard.confirm()

View File

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

View File

@ -2,22 +2,23 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError
from odoo.addons import decimal_precision as dp
class AccountInvoiceSpreadLine(models.Model):
_name = 'account.spread.line'
_description = 'Account Spread Lines'
_order = 'date'
_name = "account.spread.line"
_description = "Account Spread Lines"
_order = "date"
name = fields.Char('Description', readonly=True)
amount = fields.Float(digits=dp.get_precision('Account'), required=True)
name = fields.Char("Description", readonly=True)
amount = fields.Float(digits=dp.get_precision("Account"), required=True)
date = fields.Date(required=True)
spread_id = fields.Many2one(
'account.spread', string='Spread Board', ondelete='cascade')
move_id = fields.Many2one(
'account.move', string='Journal Entry', readonly=True)
"account.spread", string="Spread Board", ondelete="cascade"
)
move_id = fields.Many2one("account.move", string="Journal Entry", readonly=True)
@api.multi
def create_and_reconcile_moves(self):
@ -25,19 +26,19 @@ class AccountInvoiceSpreadLine(models.Model):
for spread_line in self:
spread = spread_line.spread_id
spread_line_list = grouped_lines.get(
spread, self.env['account.spread.line'])
grouped_lines.update({
spread: spread_line_list + spread_line
})
spread, self.env["account.spread.line"]
)
grouped_lines.update({spread: spread_line_list + spread_line})
for spread in grouped_lines:
created_moves = grouped_lines[spread]._create_moves()
if created_moves:
post_msg = _("Created move(s) ")
post_msg += ", ".join(
'<a href=# data-oe-model=account.move data-oe-id=%d'
'>%s</a>' % (move.id, move.name)
for move in created_moves)
"<a href=# data-oe-model=account.move data-oe-id=%d"
">%s</a>" % (move.id, move.name)
for move in created_moves
)
spread.message_post(body=post_msg)
spread._reconcile_spread_moves(created_moves)
@ -62,15 +63,19 @@ class AccountInvoiceSpreadLine(models.Model):
@api.multi
def _create_moves(self):
if self.filtered(lambda l: l.move_id):
raise UserError(_('This spread line is already linked to a '
'journal entry! Please post or delete it.'))
raise UserError(
_(
"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:
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
return created_moves
@ -78,7 +83,7 @@ class AccountInvoiceSpreadLine(models.Model):
def _prepare_move(self):
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
analytic = spread.account_analytic_id
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
not_same_curr = company_currency != current_currency
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, {
'name': spread.name.split('\n')[0][:64],
'account_id': spread.debit_account_id.id,
'debit': amount if amount > 0.0 else 0.0,
'credit': -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 - 1.0 * self.amount or 0.0,
}), (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,
})]
line_ids = [
(
0,
0,
{
"name": spread.name.split("\n")[0][:64],
"account_id": spread.debit_account_id.id,
"debit": amount if amount > 0.0 else 0.0,
"credit": -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 -1.0 * self.amount or 0.0,
},
),
(
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 {
'name': self.name or "/",
'ref': self.name,
'date': spread_date,
'journal_id': spread.journal_id.id,
'line_ids': line_ids,
'company_id': spread.company_id.id,
"name": self.name or "/",
"ref": self.name,
"date": spread_date,
"journal_id": spread.journal_id.id,
"line_ids": line_ids,
"company_id": spread.company_id.id,
}
@api.multi
@ -127,13 +144,13 @@ class AccountInvoiceSpreadLine(models.Model):
"""
self.ensure_one()
return {
'name': _("Journal Entry"),
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.move',
'view_id': False,
'type': 'ir.actions.act_window',
'res_id': self.move_id.id,
"name": _("Journal Entry"),
"view_type": "form",
"view_mode": "form",
"res_model": "account.move",
"view_id": False,
"type": "ir.actions.act_window",
"res_id": self.move_id.id,
}
@api.multi
@ -143,7 +160,7 @@ class AccountInvoiceSpreadLine(models.Model):
"""
for line in self:
move = line.move_id
if move.state == 'posted':
if move.state == "posted":
move.button_cancel()
move.line_ids.remove_move_reconcile()
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
create moves for them. Method also called by the cron job.
"""
lines = self.search([
('date', '<=', fields.Date.today()),
('move_id', '=', False)
])
lines = self.search(
[("date", "<=", fields.Date.today()), ("move_id", "=", False)]
)
lines.create_and_reconcile_moves()
unposted_moves = self.search([('move_id', '!=', False)]).mapped(
'move_id').filtered(lambda m: m.state != 'posted')
unposted_moves.filtered(
lambda m: m.company_id.force_move_auto_post).post()
unposted_moves = (
self.search([("move_id", "!=", False)])
.mapped("move_id")
.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([
('all_posted', '=', True)
]).filtered(lambda s: s.company_id.auto_archive)
spreads_to_archive.write({'active': False})
spreads_to_archive = (
self.env["account.spread"]
.search([("all_posted", "=", True)])
.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>)
# 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
class AccountSpreadTemplate(models.Model):
_name = 'account.spread.template'
_description = 'Account Spread Template'
_name = "account.spread.template"
_description = "Account Spread Template"
name = fields.Char(required=True)
spread_type = fields.Selection([
('sale', 'Customer'),
('purchase', 'Supplier')],
default='sale',
required=True)
spread_type = fields.Selection(
[("sale", "Customer"), ("purchase", "Supplier")], default="sale", required=True
)
company_id = fields.Many2one(
'res.company',
"res.company",
default=lambda self: self.env.user.company_id,
string='Company',
required=True)
string="Company",
required=True,
)
spread_journal_id = fields.Many2one(
'account.journal',
string='Journal',
required=True)
"account.journal", string="Journal", required=True
)
use_invoice_line_account = fields.Boolean(
string="Invoice account as spread account",
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(
'account.account',
string='Spread Balance Sheet Account',
required=False)
"account.account", string="Spread Balance Sheet Account", required=False
)
exp_rev_account_id = fields.Many2one(
'account.account',
string='Expense/Revenue Account',
help="Optional account to overwrite the existing expense/revenue "
"account")
"account.account",
string="Expense/Revenue Account",
help="Optional account to overwrite the existing expense/revenue " "account",
)
period_number = fields.Integer(
string='Number of Repetitions',
help="Define the number of spread lines")
period_type = fields.Selection([
('month', 'Month'),
('quarter', 'Quarter'),
('year', 'Year')],
help="Period length for the entries")
string="Number of Repetitions", help="Define the number of spread lines"
)
period_type = fields.Selection(
[("month", "Month"), ("quarter", "Quarter"), ("year", "Year")],
help="Period length for the entries",
)
start_date = fields.Date()
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 "
"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(
comodel_name='account.spread.template.auto',
string='Auto Spread On',
inverse_name='template_id',
comodel_name="account.spread.template.auto",
string="Auto Spread On",
inverse_name="template_id",
)
@api.model
def default_get(self, 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
else:
company_id = res['company_id']
default_journal = self.env['account.journal'].search([
('type', '=', 'general'),
('company_id', '=', company_id)],
limit=1)
if 'spread_journal_id' not in res and default_journal:
res['spread_journal_id'] = default_journal.id
company_id = res["company_id"]
default_journal = self.env["account.journal"].search(
[("type", "=", "general"), ("company_id", "=", company_id)], limit=1
)
if "spread_journal_id" not in res and default_journal:
res["spread_journal_id"] = default_journal.id
return res
@api.constrains('auto_spread', 'auto_spread_ids')
@api.constrains("auto_spread", "auto_spread_ids")
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:
if not line.product_id and not line.account_id:
raise UserError(_('Please select product and/or account '
'on auto spread options'))
raise UserError(
_(
"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):
company = self.company_id
if self.spread_type == 'sale':
if self.spread_type == "sale":
account = company.default_spread_revenue_account_id
journal = company.default_spread_revenue_journal_id
else:
@ -94,7 +94,7 @@ class AccountSpreadTemplate(models.Model):
if 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):
self.exp_rev_account_id = False
@ -102,32 +102,32 @@ class AccountSpreadTemplate(models.Model):
self.ensure_one()
company = self.company_id
spread_vals = {
'name': self.name,
'template_id': self.id,
'journal_id': self.spread_journal_id.id,
'use_invoice_line_account': self.use_invoice_line_account,
'company_id': company.id,
"name": self.name,
"template_id": self.id,
"journal_id": self.spread_journal_id.id,
"use_invoice_line_account": self.use_invoice_line_account,
"company_id": company.id,
}
account_id = spread_account_id or self.spread_account_id.id
if self.spread_type == 'sale':
invoice_type = 'out_invoice'
spread_vals['debit_account_id'] = account_id
if self.spread_type == "sale":
invoice_type = "out_invoice"
spread_vals["debit_account_id"] = account_id
else:
invoice_type = 'in_invoice'
spread_vals['credit_account_id'] = account_id
invoice_type = "in_invoice"
spread_vals["credit_account_id"] = account_id
if self.period_number:
spread_vals['period_number'] = self.period_number
spread_vals["period_number"] = self.period_number
if self.period_type:
spread_vals['period_type'] = self.period_type
spread_vals["period_type"] = self.period_type
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
@api.constrains('auto_spread_ids', 'auto_spread')
@api.constrains("auto_spread_ids", "auto_spread")
def _check_auto_spread_ids_unique(self):
query = """
select product_id, account_id, analytic_account_id
@ -141,43 +141,31 @@ class AccountSpreadTemplate(models.Model):
self._cr.execute(query, [self._ids])
results = []
for res in self._cr.fetchall():
product = self.env['product.product'].browse(res[0])
account = self.env['account.account'].browse(res[1])
analytic = self.env['account.analytic.account'].browse(res[2])
results.append('%s / %s / %s' % (product.name, account.name, analytic.name))
product = self.env["product.product"].browse(res[0])
account = self.env["account.account"].browse(res[1])
analytic = self.env["account.analytic.account"].browse(res[2])
results.append("{} / {} / {}".format(product.name, account.name, analytic.name))
if results:
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):
_name = 'account.spread.template.auto'
_description = 'Auto create spread, based on product/account/analytic'
_name = "account.spread.template.auto"
_description = "Auto create spread, based on product/account/analytic"
template_id = fields.Many2one(
comodel_name='account.spread.template',
string='Spread Template',
comodel_name="account.spread.template",
string="Spread Template",
required=True,
ondelete='cascade',
ondelete="cascade",
index=True,
)
company_id = fields.Many2one(
related='template_id.company_id',
store=True,
)
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',
)
company_id = fields.Many2one(related="template_id.company_id", store=True,)
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(
comodel_name='account.analytic.account',
string='Analytic',
comodel_name="account.analytic.account", string="Analytic",
)

View File

@ -5,29 +5,36 @@ from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
_inherit = "res.company"
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(
'account.account', string='Expense Spread Account')
"account.account", string="Expense Spread Account"
)
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(
'account.journal', string='Expense Spread Journal')
"account.journal", string="Expense Spread Journal"
)
allow_spread_planning = fields.Boolean(
default=True,
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(
'Auto-post spread lines',
"Auto-post spread lines",
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 spread',
"Auto-archive spread",
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" ?>
<odoo>
<data noupdate="1">
<record id="account_spread_multi_company_rule" model="ir.rule">
<field name="name">Account Spread multi-company</field>
<field ref="model_account_spread" name="model_id" />
<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 id="account_spread_template_multi_company_rule" model="ir.rule">
<field name="name">Account Spread Template multi-company</field>
<field ref="model_account_spread_template" name="model_id" />
<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 id="account_spread_template_auto_multi_company_rule" model="ir.rule">
<field name="name">Account Spread Tempalte Auto multi-company</field>
<field ref="model_account_spread_template_auto" name="model_id" />
<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>
</data>
</odoo>

View File

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

View File

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

View File

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="assets_backend" name="account spread" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link 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"></script>
<link
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>
</template>
</odoo>

View File

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

View File

@ -3,123 +3,152 @@
import datetime
from odoo.tools import convert_file
from odoo.modules.module import get_resource_path
from odoo.exceptions import UserError, ValidationError
from odoo.modules.module import get_resource_path
from odoo.tests import common
from odoo.tools import convert_file
class TestAccountInvoiceSpread(common.TransactionCase):
def _load(self, module, *args):
convert_file(
self.cr,
'account_spread_cost_revenue',
"account_spread_cost_revenue",
get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report)
{},
"init",
False,
"test",
self.registry._assertion_report,
)
def setUp(self):
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_payable = self.env.ref('account.data_account_type_payable')
type_revenue = self.env.ref('account.data_account_type_revenue')
type_receivable = self.env.ref("account.data_account_type_receivable")
type_payable = self.env.ref("account.data_account_type_payable")
type_revenue = self.env.ref("account.data_account_type_revenue")
self.invoice_account = self.env['account.account'].create({
'name': 'test_account_receivable',
'code': '123',
'user_type_id': type_receivable.id,
'reconcile': True
})
self.invoice_account = self.env["account.account"].create(
{
"name": "test_account_receivable",
"code": "123",
"user_type_id": type_receivable.id,
"reconcile": True,
}
)
self.account_payable = self.env['account.account'].create({
'name': 'test_account_payable',
'code': '321',
'user_type_id': type_payable.id,
'reconcile': True
})
self.account_payable = self.env["account.account"].create(
{
"name": "test_account_payable",
"code": "321",
"user_type_id": type_payable.id,
"reconcile": True,
}
)
self.account_revenue = self.env['account.account'].create({
'name': 'test_account_revenue',
'code': '864',
'user_type_id': type_revenue.id,
'reconcile': True
})
self.account_revenue = self.env["account.account"].create(
{
"name": "test_account_revenue",
"code": "864",
"user_type_id": type_revenue.id,
"reconcile": True,
}
)
self.invoice_line_account = self.account_payable
self.spread_account = self.env['account.account'].create({
'name': 'test spread account_payable',
'code': '765',
'user_type_id': type_payable.id,
'reconcile': True
})
self.spread_account = self.env["account.account"].create(
{
"name": "test spread account_payable",
"code": "765",
"user_type_id": type_payable.id,
"reconcile": True,
}
)
partner = self.env['res.partner'].create({
'name': 'Partner Name',
'supplier': True,
})
self.invoice = self.env['account.invoice'].create({
'partner_id': partner.id,
'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,
'invoice_id': self.invoice.id,
'name': 'product that cost 1000',
'account_id': self.invoice_account.id,
})
partner = self.env["res.partner"].create(
{"name": "Partner Name", "supplier": True,}
)
self.invoice = self.env["account.invoice"].create(
{
"partner_id": partner.id,
"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,
"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)]
self.analytic_account = self.env['account.analytic.account'].create({
'name': 'test account',
})
self.spread = self.env['account.spread'].with_context(
mail_create_nosubscribe=True
).create([{
'name': 'test',
'debit_account_id': self.spread_account.id,
'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.journal_id.id,
'invoice_type': 'in_invoice',
'account_analytic_id': self.analytic_account.id,
'analytic_tag_ids': analytic_tags,
}])
analytic_tags = [(6, 0, self.env.ref("analytic.tag_contract").ids)]
self.analytic_account = self.env["account.analytic.account"].create(
{"name": "test account",}
)
self.spread = (
self.env["account.spread"]
.with_context(mail_create_nosubscribe=True)
.create(
[
{
"name": "test",
"debit_account_id": self.spread_account.id,
"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.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({
'partner_id': partner.id,
'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,
'invoice_id': self.invoice_2.id,
'name': 'product that cost 1000',
'account_id': self.invoice_line_account.id,
})
self.spread2 = self.env['account.spread'].create([{
'name': 'test2',
'debit_account_id': self.spread_account.id,
'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',
}])
self.invoice_2 = self.env["account.invoice"].create(
{
"partner_id": partner.id,
"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,
"invoice_id": self.invoice_2.id,
"name": "product that cost 1000",
"account_id": self.invoice_line_account.id,
}
)
self.spread2 = self.env["account.spread"].create(
[
{
"name": "test2",
"debit_account_id": self.spread_account.id,
"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):
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(
default_invoice_line_id=self.invoice_line.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.invoice_id, self.invoice)
self.assertEqual(wizard1.invoice_type, 'in_invoice')
self.assertEqual(wizard1.invoice_type, "in_invoice")
self.assertFalse(wizard1.spread_id)
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_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.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.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_journal_id)
def test_02_wizard_defaults(self):
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_payable = self.account_payable
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal')
sales_journal = self.ref('account_spread_cost_revenue.sales_journal')
exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = account_payable
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.invoice_id, self.invoice)
self.assertEqual(wizard1.invoice_type, 'in_invoice')
self.assertEqual(wizard1.invoice_type, "in_invoice")
self.assertFalse(wizard1.spread_id)
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_journal_id)
res_onchange = wizard1.onchange_invoice_type()
self.assertTrue(res_onchange)
self.assertTrue(res_onchange.get('domain'))
self.assertTrue(res_onchange.get("domain"))
wizard1._onchange_spread_journal_account()
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.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.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_journal_id)
res_onchange = wizard2.onchange_invoice_type()
self.assertTrue(res_onchange)
self.assertTrue(res_onchange.get('domain'))
self.assertTrue(res_onchange.get("domain"))
wizard2._onchange_spread_journal_account()
self.assertTrue(wizard2.spread_account_id)
@ -219,22 +248,23 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_03_link_invoice_line_with_spread_sheet(self):
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(
default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id,
allow_spread_planning=True,
).create({})
self.assertEqual(wizard1.spread_action_type, 'link')
self.assertEqual(wizard1.spread_action_type, "link")
wizard1.spread_account_id = self.account_revenue
wizard1.spread_journal_id = self.ref(
'account_spread_cost_revenue.expenses_journal')
"account_spread_cost_revenue.expenses_journal"
)
wizard1.spread_id = self.spread
res_action = wizard1.confirm()
self.assertTrue(isinstance(res_action, dict))
self.assertTrue(res_action.get('res_id'))
self.assertEqual(res_action.get('res_id'), self.spread.id)
self.assertTrue(res_action.get("res_id"))
self.assertEqual(res_action.get("res_id"), self.spread.id)
self.assertTrue(self.spread.invoice_line_id)
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)
for ml in line.move_id.line_ids:
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_tag_ids, analytic_tag)
@ -268,35 +298,34 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_04_new_spread_sheet(self):
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_journal_id = self.ref(
'account_spread_cost_revenue.expenses_journal')
spread_journal_id = self.ref("account_spread_cost_revenue.expenses_journal")
wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id,
).create({
'spread_action_type': 'new',
})
self.assertEqual(wizard1.spread_action_type, 'new')
).create({"spread_action_type": "new",})
self.assertEqual(wizard1.spread_action_type, "new")
wizard1.write({
'spread_account_id': spread_account.id,
'spread_journal_id': spread_journal_id,
})
wizard1.write(
{
"spread_account_id": spread_account.id,
"spread_journal_id": spread_journal_id,
}
)
res_action = wizard1.confirm()
self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id'))
self.assertTrue(res_action.get('context'))
res_context = res_action.get('context')
self.assertTrue(res_context.get('default_name'))
self.assertTrue(res_context.get('default_invoice_type'))
self.assertTrue(res_context.get('default_invoice_line_id'))
self.assertTrue(res_context.get('default_debit_account_id'))
self.assertTrue(res_context.get('default_credit_account_id'))
self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get("context"))
res_context = res_action.get("context")
self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread.line_ids
for line in spread_lines:
@ -311,26 +340,26 @@ class TestAccountInvoiceSpread(common.TransactionCase):
wizard2 = Wizard.with_context(
default_invoice_line_id=self.invoice_line_2.id,
default_company_id=my_company.id,
).create({
'spread_action_type': 'new',
})
self.assertEqual(wizard2.spread_action_type, 'new')
).create({"spread_action_type": "new",})
self.assertEqual(wizard2.spread_action_type, "new")
wizard2.write({
'spread_account_id': spread_account.id,
'spread_journal_id': spread_journal_id,
})
wizard2.write(
{
"spread_account_id": spread_account.id,
"spread_journal_id": spread_journal_id,
}
)
res_action = wizard2.confirm()
self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id'))
self.assertTrue(res_action.get('context'))
res_context = res_action.get('context')
self.assertTrue(res_context.get('default_name'))
self.assertTrue(res_context.get('default_invoice_type'))
self.assertTrue(res_context.get('default_invoice_line_id'))
self.assertTrue(res_context.get('default_debit_account_id'))
self.assertTrue(res_context.get('default_credit_account_id'))
self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get("context"))
res_context = res_action.get("context")
self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread2.line_ids
for line in spread_lines:
@ -344,34 +373,32 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_05_new_spread_sheet_from_template(self):
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
self.assertTrue(spread_account)
spread_journal_id = self.ref(
'account_spread_cost_revenue.expenses_journal')
spread_journal_id = self.ref("account_spread_cost_revenue.expenses_journal")
template = self.env['account.spread.template'].create({
'name': 'test',
'spread_type': 'purchase',
'period_number': 5,
'period_type': 'month',
'spread_account_id': spread_account.id,
'spread_journal_id': spread_journal_id,
})
template = self.env["account.spread.template"].create(
{
"name": "test",
"spread_type": "purchase",
"period_number": 5,
"period_type": "month",
"spread_account_id": spread_account.id,
"spread_journal_id": spread_journal_id,
}
)
wizard1 = Wizard.with_context(
default_invoice_line_id=self.invoice_line.id,
default_company_id=my_company.id,
).create({
'spread_action_type': 'template',
'template_id': template.id,
})
self.assertEqual(wizard1.spread_action_type, 'template')
).create({"spread_action_type": "template", "template_id": template.id,})
self.assertEqual(wizard1.spread_action_type, "template")
res_action = wizard1.confirm()
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
for line in spread_lines:
@ -386,26 +413,26 @@ class TestAccountInvoiceSpread(common.TransactionCase):
wizard2 = Wizard.with_context(
default_invoice_line_id=self.invoice_line_2.id,
default_company_id=my_company.id,
).create({
'spread_action_type': 'new',
})
self.assertEqual(wizard2.spread_action_type, 'new')
).create({"spread_action_type": "new",})
self.assertEqual(wizard2.spread_action_type, "new")
wizard2.write({
'spread_account_id': spread_account.id,
'spread_journal_id': spread_journal_id,
})
wizard2.write(
{
"spread_account_id": spread_account.id,
"spread_journal_id": spread_journal_id,
}
)
res_action = wizard2.confirm()
self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id'))
self.assertTrue(res_action.get('context'))
res_context = res_action.get('context')
self.assertTrue(res_context.get('default_name'))
self.assertTrue(res_context.get('default_invoice_type'))
self.assertTrue(res_context.get('default_invoice_line_id'))
self.assertTrue(res_context.get('default_debit_account_id'))
self.assertTrue(res_context.get('default_credit_account_id'))
self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get("context"))
res_context = res_action.get("context")
self.assertTrue(res_context.get("default_name"))
self.assertTrue(res_context.get("default_invoice_type"))
self.assertTrue(res_context.get("default_invoice_line_id"))
self.assertTrue(res_context.get("default_debit_account_id"))
self.assertTrue(res_context.get("default_credit_account_id"))
spread_lines = self.spread2.line_ids
for line in spread_lines:
@ -420,8 +447,8 @@ class TestAccountInvoiceSpread(common.TransactionCase):
res_action = self.invoice_line.spread_details()
self.assertTrue(isinstance(res_action, dict))
self.assertFalse(res_action.get('res_id'))
self.assertTrue(res_action.get('context'))
self.assertFalse(res_action.get("res_id"))
self.assertTrue(res_action.get("context"))
def test_07_unlink_invoice_line_and_spread_sheet(self):
@ -465,7 +492,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice
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)
for invoice_ml in invoice_mls:
if invoice_ml.debit:
@ -474,15 +501,17 @@ class TestAccountInvoiceSpread(common.TransactionCase):
def test_10_link_vendor_bill_line_with_spread_sheet(self):
copied_line = self.invoice_line.copy()
copied_line.name = 'new test line'
self.spread.write({
'estimated_amount': 1000.0,
'period_number': 12,
'period_type': 'month',
'spread_date': datetime.date(2017, 1, 7),
'invoice_line_id': self.invoice_line.id,
'move_line_auto_post': False,
})
copied_line.name = "new test line"
self.spread.write(
{
"estimated_amount": 1000.0,
"period_number": 12,
"period_type": "month",
"spread_date": datetime.date(2017, 1, 7),
"invoice_line_id": self.invoice_line.id,
"move_line_auto_post": False,
}
)
spread_lines = self.spread.line_ids
for line in spread_lines:
@ -498,7 +527,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.credit_account_id
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)
for spread_ml in spread_mls:
if spread_ml.debit:
@ -509,16 +538,17 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice
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)
count_balance_sheet = len(invoice_mls.filtered(
lambda x: x.account_id == balance_sheet))
count_balance_sheet = len(
invoice_mls.filtered(lambda x: x.account_id == balance_sheet)
)
self.assertEqual(count_balance_sheet, 1)
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)
for spread_ml in spread_mls:
if spread_ml.debit:
@ -528,19 +558,21 @@ class TestAccountInvoiceSpread(common.TransactionCase):
action_reconcile_view = self.spread2.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertFalse(action_reconcile_view.get('domain')[0][2])
self.assertTrue(action_reconcile_view.get('context'))
self.assertFalse(action_reconcile_view.get("domain")[0][2])
self.assertTrue(action_reconcile_view.get("context"))
def test_11_link_vendor_bill_line_with_spread_sheet(self):
self.invoice_line.copy()
self.spread.write({
'estimated_amount': 1000.0,
'period_number': 12,
'period_type': 'month',
'spread_date': datetime.date(2017, 1, 7),
'invoice_line_id': self.invoice_line.id,
'move_line_auto_post': False,
})
self.spread.write(
{
"estimated_amount": 1000.0,
"period_number": 12,
"period_type": "month",
"spread_date": datetime.date(2017, 1, 7),
"invoice_line_id": self.invoice_line.id,
"move_line_auto_post": False,
}
)
spread_lines = self.spread.line_ids
for line in spread_lines:
@ -556,7 +588,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.credit_account_id
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)
for spread_ml in spread_mls:
if spread_ml.debit:
@ -567,40 +599,43 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice
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)
count_balance_sheet = len(invoice_mls.filtered(
lambda x: x.account_id == balance_sheet))
count_balance_sheet = len(
invoice_mls.filtered(lambda x: x.account_id == balance_sheet)
)
self.assertEqual(count_balance_sheet, 1)
self.spread.company_id.force_move_auto_post = True
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)
for spread_ml in spread_mls:
self.assertFalse(spread_ml.full_reconcile_id)
action_reconcile_view = self.spread.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertTrue(action_reconcile_view.get('domain')[0][2])
self.assertTrue(action_reconcile_view.get('context'))
self.assertTrue(action_reconcile_view.get("domain")[0][2])
self.assertTrue(action_reconcile_view.get("context"))
action_spread_details = self.invoice_line.spread_details()
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):
self.spread2.write({
'estimated_amount': 1000.0,
'period_number': 12,
'period_type': 'month',
'spread_date': datetime.date(2017, 1, 7),
'invoice_line_id': self.invoice_line_2.id,
'move_line_auto_post': False,
})
self.spread2.write(
{
"estimated_amount": 1000.0,
"period_number": 12,
"period_type": "month",
"spread_date": datetime.date(2017, 1, 7),
"invoice_line_id": self.invoice_line_2.id,
"move_line_auto_post": False,
}
)
spread_lines = self.spread2.line_ids
for line in spread_lines:
@ -616,7 +651,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.debit_account_id
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)
for spread_ml in spread_mls:
if spread_ml.debit:
@ -627,7 +662,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice
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)
for invoice_ml in invoice_mls:
if invoice_ml.credit:
@ -635,7 +670,7 @@ class TestAccountInvoiceSpread(common.TransactionCase):
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)
for spread_ml in spread_mls:
if spread_ml.debit:
@ -645,22 +680,24 @@ class TestAccountInvoiceSpread(common.TransactionCase):
action_reconcile_view = self.spread2.open_reconcile_view()
self.assertTrue(isinstance(action_reconcile_view, dict))
self.assertTrue(action_reconcile_view.get('domain')[0][2])
self.assertFalse(action_reconcile_view.get('res_id'))
self.assertTrue(action_reconcile_view.get('context'))
self.assertTrue(action_reconcile_view.get("domain")[0][2])
self.assertFalse(action_reconcile_view.get("res_id"))
self.assertTrue(action_reconcile_view.get("context"))
action_spread_details = self.invoice_line_2.spread_details()
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):
self.spread2.write({
'estimated_amount': 1000.0,
'period_number': 12,
'period_type': 'month',
'spread_date': datetime.date(2017, 1, 7),
})
self.spread2.write(
{
"estimated_amount": 1000.0,
"period_number": 12,
"period_type": "month",
"spread_date": datetime.date(2017, 1, 7),
}
)
self.spread2.compute_spread_board()
spread_lines = self.spread2.line_ids
@ -674,10 +711,10 @@ class TestAccountInvoiceSpread(common.TransactionCase):
spread_lines[2]._create_moves().post()
spread_lines[3]._create_moves().post()
self.assertEqual(spread_lines[0].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[3].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[2].move_id.state, "posted")
self.assertEqual(spread_lines[3].move_id.state, "posted")
spread_mls = spread_lines[0].move_id.line_ids
self.assertTrue(spread_mls)
@ -694,14 +731,14 @@ class TestAccountInvoiceSpread(common.TransactionCase):
balance_sheet = self.spread.debit_account_id
self.assertTrue(balance_sheet.reconcile)
self.spread2.write({
'invoice_line_id': self.invoice_line_2.id,
})
self.spread2.write(
{"invoice_line_id": self.invoice_line_2.id,}
)
# Validate invoice
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)
for invoice_ml in invoice_mls:
if invoice_ml.credit:
@ -719,8 +756,9 @@ class TestAccountInvoiceSpread(common.TransactionCase):
self.assertFalse(spread_ml.matched_credit_ids)
self.assertFalse(spread_ml.full_reconcile_id)
other_journal = self.env['account.journal'].create({
'name': 'Other Journal', 'type': 'general', 'code': 'test2'})
other_journal = self.env["account.journal"].create(
{"name": "Other Journal", "type": "general", "code": "test2"}
)
with self.assertRaises(ValidationError):
self.spread2.journal_id = other_journal
@ -749,18 +787,19 @@ class TestAccountInvoiceSpread(common.TransactionCase):
# Validate invoice
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.
self.env['account.invoice.refund'].with_context({
'active_model': 'account.invoice',
'active_ids': [self.invoice.id],
'active_id': self.invoice.id
}).create(dict(
description='Invoice Refund',
filter_refund='refund',
)).invoice_refund()
self.env["account.invoice.refund"].with_context(
{
"active_model": "account.invoice",
"active_ids": [self.invoice.id],
"active_id": self.invoice.id,
}
).create(
dict(description="Invoice Refund", filter_refund="refund",)
).invoice_refund()
# Invoice lines do not contain the lint to the spread.
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 odoo.tools import convert_file, mute_logger
from odoo.modules.module import get_resource_path
from odoo.exceptions import ValidationError
from odoo.modules.module import get_resource_path
from odoo.tests import common
from odoo.tools import convert_file, mute_logger
class TestAccountSpreadCostRevenue(common.TransactionCase):
def _load(self, module, *args):
convert_file(
self.cr,
'account_spread_cost_revenue',
"account_spread_cost_revenue",
get_resource_path(module, *args),
{}, 'init', False, 'test', self.registry._assertion_report)
{},
"init",
False,
"test",
self.registry._assertion_report,
)
def setUp(self):
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_expenses = self.env.ref('account.data_account_type_expenses')
type_payable = self.env.ref('account.data_account_type_payable')
type_revenue = self.env.ref('account.data_account_type_revenue')
type_receivable = self.env.ref("account.data_account_type_receivable")
type_expenses = self.env.ref("account.data_account_type_expenses")
type_payable = self.env.ref("account.data_account_type_payable")
type_revenue = self.env.ref("account.data_account_type_revenue")
self.account_receivable = self.env['account.account'].create({
'name': 'test_account_receivable',
'code': '123',
'user_type_id': type_receivable.id,
'reconcile': True
})
self.account_receivable = self.env["account.account"].create(
{
"name": "test_account_receivable",
"code": "123",
"user_type_id": type_receivable.id,
"reconcile": True,
}
)
self.credit_account = self.account_receivable
self.account_expenses = self.env['account.account'].create({
'name': 'test account_expenses',
'code': '765',
'user_type_id': type_expenses.id,
'reconcile': True
})
self.account_expenses = self.env["account.account"].create(
{
"name": "test account_expenses",
"code": "765",
"user_type_id": type_expenses.id,
"reconcile": True,
}
)
self.debit_account = self.account_expenses
self.account_payable = self.env['account.account'].create({
'name': 'test_account_payable',
'code': '321',
'user_type_id': type_payable.id,
'reconcile': True
})
self.account_payable = self.env["account.account"].create(
{
"name": "test_account_payable",
"code": "321",
"user_type_id": type_payable.id,
"reconcile": True,
}
)
self.account_revenue = self.env['account.account'].create({
'name': 'test_account_revenue',
'code': '864',
'user_type_id': type_revenue.id,
'reconcile': True
})
self.account_revenue = self.env["account.account"].create(
{
"name": "test_account_revenue",
"code": "864",
"user_type_id": type_revenue.id,
"reconcile": True,
}
)
def test_01_account_spread_defaults(self):
this_year = datetime.date.today().year
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 = 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,
}
)
my_company = self.env.user.company_id
self.assertTrue(spread)
@ -77,21 +91,21 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertFalse(spread.account_analytic_id)
self.assertFalse(spread.analytic_tag_ids)
self.assertTrue(spread.move_line_auto_post)
self.assertEqual(spread.name, 'test')
self.assertEqual(spread.invoice_type, 'out_invoice')
self.assertEqual(spread.name, "test")
self.assertEqual(spread.invoice_type, "out_invoice")
self.assertEqual(spread.company_id, my_company)
self.assertEqual(spread.currency_id, my_company.currency_id)
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.credit_account_id, self.credit_account)
self.assertEqual(spread.unspread_amount, 0.)
self.assertEqual(spread.unposted_amount, 0.)
self.assertEqual(spread.total_amount, 0.)
self.assertEqual(spread.estimated_amount, 0.)
self.assertEqual(spread.unspread_amount, 0.0)
self.assertEqual(spread.unposted_amount, 0.0)
self.assertEqual(spread.total_amount, 0.0)
self.assertEqual(spread.estimated_amount, 0.0)
self.assertEqual(spread.spread_date, datetime.date(this_year, 1, 1))
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.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_expense_journal_id)
@mute_logger('odoo.sql_db')
@mute_logger("odoo.sql_db")
def test_03_no_defaults(self):
with self.assertRaises(IntegrityError):
self.env['account.spread'].create({
'name': 'test',
})
self.env["account.spread"].create(
{"name": "test",}
)
@mute_logger('odoo.sql_db')
@mute_logger("odoo.sql_db")
def test_04_no_defaults(self):
with self.assertRaises(IntegrityError):
self.env['account.spread'].create({
'name': 'test',
'invoice_type': 'out_invoice',
})
self.env["account.spread"].create(
{"name": "test", "invoice_type": "out_invoice",}
)
def test_05_config_settings(self):
my_company = self.env.user.company_id
account_revenue = self.account_revenue
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal')
sales_journal = self.ref('account_spread_cost_revenue.sales_journal')
exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = self.account_payable
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_expense_journal_id)
spread = self.env['account.spread'].new({
'name': 'test',
})
spread = self.env["account.spread"].new({"name": "test",})
self.assertTrue(spread)
self.assertFalse(spread.line_ids)
@ -148,66 +159,71 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
self.assertFalse(spread.analytic_tag_ids)
self.assertFalse(spread.move_line_auto_post)
defaults = (self.env['account.spread'].default_get([
'company_id',
'currency_id',
]))
defaults = self.env["account.spread"].default_get(
["company_id", "currency_id",]
)
self.assertEqual(defaults['company_id'], my_company.id)
self.assertEqual(defaults['currency_id'], my_company.currency_id.id)
self.assertEqual(defaults["company_id"], my_company.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.onchange_invoice_type()
self.assertEqual(spread.debit_account_id, account_revenue)
self.assertFalse(spread.credit_account_id)
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()
self.assertEqual(spread.credit_account_id, self.account_payable)
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):
invoice_account = self.account_receivable
invoice_line_account = self.account_expenses
invoice = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'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,
'price_unit': 100.0,
'invoice_id': invoice.id,
'name': 'product that cost 100',
'account_id': invoice_line_account.id,
})
invoice = self.env["account.invoice"].create(
{
"partner_id": self.env.ref("base.res_partner_2").id,
"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,
"price_unit": 100.0,
"invoice_id": invoice.id,
"name": "product that cost 100",
"account_id": invoice_line_account.id,
}
)
invoice_line2 = invoice_line.copy()
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({
'name': 'test',
'invoice_type': 'in_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": "in_invoice",
"debit_account_id": self.debit_account.id,
"credit_account_id": self.credit_account.id,
}
)
invoice_line.spread_id = spread
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.assertEqual(invoice_line2.spread_check, 'unlinked')
self.assertEqual(invoice_line2.spread_check, "unlinked")
invoice.action_invoice_open()
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.assertEqual(invoice_line2.spread_check, 'unavailable')
self.assertEqual(invoice_line2.spread_check, "unavailable")
self.assertTrue(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons)
@ -216,24 +232,26 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
def test_07_create_spread_template(self):
account_revenue = self.account_revenue
account_payable = self.account_payable
spread_template = self.env['account.spread.template'].create({
'name': 'test',
'spread_type': 'sale',
'spread_account_id': account_revenue.id,
})
spread_template = self.env["account.spread.template"].create(
{
"name": "test",
"spread_type": "sale",
"spread_account_id": account_revenue.id,
}
)
my_company = self.env.user.company_id
self.assertEqual(spread_template.company_id, my_company)
self.assertTrue(spread_template.spread_journal_id)
exp_journal = self.ref('account_spread_cost_revenue.expenses_journal')
sales_journal = self.ref('account_spread_cost_revenue.sales_journal')
exp_journal = self.ref("account_spread_cost_revenue.expenses_journal")
sales_journal = self.ref("account_spread_cost_revenue.sales_journal")
my_company.default_spread_revenue_account_id = account_revenue
my_company.default_spread_expense_account_id = account_payable
my_company.default_spread_revenue_journal_id = sales_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()
self.assertTrue(spread_template.spread_journal_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)
spread_vals = spread_template._prepare_spread_from_template()
self.assertTrue(spread_vals['name'])
self.assertTrue(spread_vals['template_id'])
self.assertTrue(spread_vals['journal_id'])
self.assertTrue(spread_vals['company_id'])
self.assertTrue(spread_vals['invoice_type'])
self.assertTrue(spread_vals['credit_account_id'])
self.assertTrue(spread_vals["name"])
self.assertTrue(spread_vals["template_id"])
self.assertTrue(spread_vals["journal_id"])
self.assertTrue(spread_vals["company_id"])
self.assertTrue(spread_vals["invoice_type"])
self.assertTrue(spread_vals["credit_account_id"])
spread_template.spread_type = 'sale'
spread_template.spread_type = "sale"
spread_template.onchange_spread_type()
self.assertTrue(spread_template.spread_journal_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)
spread_vals = spread_template._prepare_spread_from_template()
self.assertTrue(spread_vals['name'])
self.assertTrue(spread_vals['template_id'])
self.assertTrue(spread_vals['journal_id'])
self.assertTrue(spread_vals['company_id'])
self.assertTrue(spread_vals['invoice_type'])
self.assertTrue(spread_vals['debit_account_id'])
self.assertTrue(spread_vals["name"])
self.assertTrue(spread_vals["template_id"])
self.assertTrue(spread_vals["journal_id"])
self.assertTrue(spread_vals["company_id"])
self.assertTrue(spread_vals["invoice_type"])
self.assertTrue(spread_vals["debit_account_id"])
def test_08_check_template_invoice_type(self):
account_revenue = self.account_revenue
template_sale = self.env['account.spread.template'].create({
'name': 'test',
'spread_type': 'sale',
'spread_account_id': account_revenue.id,
})
template_purchase = self.env['account.spread.template'].create({
'name': 'test',
'spread_type': 'purchase',
'spread_account_id': self.account_payable.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,
})
template_sale = self.env["account.spread.template"].create(
{
"name": "test",
"spread_type": "sale",
"spread_account_id": account_revenue.id,
}
)
template_purchase = self.env["account.spread.template"].create(
{
"name": "test",
"spread_type": "purchase",
"spread_account_id": self.account_payable.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
self.assertEqual(spread.template_id, template_sale)
with self.assertRaises(ValidationError):
spread.template_id = template_purchase
self.assertEqual(spread.invoice_type, 'out_invoice')
self.assertEqual(spread.invoice_type, "out_invoice")
spread.onchange_template()
self.assertEqual(spread.invoice_type, 'in_invoice')
self.assertEqual(spread.invoice_type, "in_invoice")
spread.template_id = False
spread.invoice_type = 'in_invoice'
spread.invoice_type = "in_invoice"
spread.template_id = template_purchase
self.assertEqual(spread.template_id, template_purchase)
with self.assertRaises(ValidationError):
spread.template_id = template_sale
self.assertEqual(spread.invoice_type, 'in_invoice')
self.assertEqual(spread.invoice_type, "in_invoice")
spread.onchange_template()
self.assertEqual(spread.invoice_type, 'out_invoice')
self.assertEqual(spread.invoice_type, "out_invoice")
spread.template_id = False
spread.invoice_type = 'out_invoice'
spread.invoice_type = "out_invoice"
spread.template_id = template_sale
self.assertEqual(spread.template_id, template_sale)
with self.assertRaises(ValidationError):
spread.invoice_type = 'in_invoice'
self.assertEqual(spread.invoice_type, 'in_invoice')
spread.invoice_type = "in_invoice"
self.assertEqual(spread.invoice_type, "in_invoice")
spread.onchange_template()
self.assertEqual(spread.invoice_type, 'out_invoice')
self.assertEqual(spread.invoice_type, "out_invoice")
spread.template_id = False
spread.invoice_type = 'in_invoice'
spread.invoice_type = "in_invoice"
spread.template_id = template_purchase
self.assertEqual(spread.template_id, template_purchase)
with self.assertRaises(ValidationError):
spread.invoice_type = 'out_invoice'
self.assertEqual(spread.invoice_type, 'out_invoice')
spread.invoice_type = "out_invoice"
self.assertEqual(spread.invoice_type, "out_invoice")
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.assertTrue(spread.display_recompute_buttons)
@ -326,80 +350,96 @@ class TestAccountSpreadCostRevenue(common.TransactionCase):
def test_09_wrong_invoice_type(self):
invoice_account = self.account_receivable
invoice_line_account = self.account_expenses
invoice = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'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,
'price_unit': 100.0,
'invoice_id': invoice.id,
'name': 'product that cost 100',
'account_id': invoice_line_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,
})
invoice = self.env["account.invoice"].create(
{
"partner_id": self.env.ref("base.res_partner_2").id,
"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,
"price_unit": 100.0,
"invoice_id": invoice.id,
"name": "product that cost 100",
"account_id": invoice_line_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):
invoice_line.spread_id = spread
def test_10_account_spread_unlink(self):
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 = 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.unlink()
def test_11_compute_display_fields(self):
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 = 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.company_id.allow_spread_planning = True
self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons)
self.assertTrue(spread.display_move_line_auto_post)
def test_12_compute_display_fields(self):
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 = 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.company_id.allow_spread_planning = False
self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons)
self.assertTrue(spread.display_move_line_auto_post)
def test_13_compute_display_fields(self):
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 = 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.company_id.force_move_auto_post = True
self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons)
self.assertFalse(spread.display_move_line_auto_post)
def test_14_compute_display_fields(self):
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 = 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.company_id.force_move_auto_post = False
self.assertFalse(spread.display_create_all_moves)
self.assertTrue(spread.display_recompute_buttons)

View File

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

View File

@ -1,24 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_supplier_invoice_spread" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form" />
<field name="arch" type="xml">
<xpath 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
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>
</field>
</record>
<record id="view_customer_invoice_spread" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form" />
<field name="arch" type="xml">
<xpath 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
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>
</field>
</record>
</odoo>

View File

@ -1,39 +1,79 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_account_spread" model="ir.ui.view">
<field name="model">account.spread</field>
<field name="arch" type="xml">
<form>
<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 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" />
<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
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>
<sheet>
<div class="oe_button_box">
<button name="open_reconcile_view"
<button
name="open_reconcile_view"
class="oe_stat_button"
icon="fa-bars"
type="object"
string="Reconciled entries">
string="Reconciled entries"
>
</button>
<button name="toggle_active" type="object"
<button
name="toggle_active"
type="object"
attrs="{'invisible': [('all_posted','=',False)]}"
class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"
options='{"terminology": "archive"}'/>
class="oe_stat_button"
icon="fa-archive"
>
<field
name="active"
widget="boolean_button"
options='{"terminology": "archive"}'
/>
</button>
</div>
<div class="oe_title">
<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>
<group name="header_info">
<group name="spread_definitions">
<field name="template_id" />
<field name="invoice_type" attrs="{'readonly':[('invoice_line_id','!=',False)]}"/>
<field
name="invoice_type"
attrs="{'readonly':[('invoice_line_id','!=',False)]}"
/>
<field name="display_recompute_buttons" invisible="1" />
<field name="display_move_line_auto_post" invisible="1" />
<field name="all_posted" invisible="1" />
@ -43,82 +83,178 @@
<group name="accounts">
<group name="debits">
<field name="is_debit_account_deprecated" invisible="1" />
<label for="debit_account_id" colspan="3" string="Balance sheet account / Spread account"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"/>
<label 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.
<label
for="debit_account_id"
colspan="3"
string="Balance sheet account / Spread account"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
/>
<label
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 class="help-block" 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
class="help-block"
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>
</div>
<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.<br/>This is the account in the invoice line.
<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.<br
/>This is the account in the invoice line.
</span>
<span class="help-block" 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
class="help-block"
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>
</div>
<field name="debit_account_id" 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)]}">
<field
name="debit_account_id"
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.
</span>
</group>
<group name="credits">
<field name="is_credit_account_deprecated" invisible="1" />
<label for="credit_account_id" colspan="3" string="Revenue account"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"/>
<label 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.
<label
for="credit_account_id"
colspan="3"
string="Revenue account"
attrs="{'invisible':[('invoice_type','not in',('out_invoice','in_refund'))]}"
/>
<label
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 class="help-block" 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
class="help-block"
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>
</div>
<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 used for the spreading.<br/>This account is the counterpart of the account of the invoice line.
<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 used for the spreading.<br
/>This account is the counterpart of the account of the invoice line.
</span>
<span class="help-block" 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
class="help-block"
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>
</div>
<field name="credit_account_id" 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)]}">
<field
name="credit_account_id"
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.
</span>
</group>
</group>
<group name="main_info">
<group>
<field name="invoice_id" attrs="{'invisible':[('invoice_id','=',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)]}"/>
<field
name="invoice_id"
attrs="{'invisible':[('invoice_id','=',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>
<field name="period_number" />
<field name="period_type" />
<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>
<notebook name="notebook">
@ -126,39 +262,94 @@
<field name="line_ids" readonly="1">
<tree>
<field name="name" readonly="1" />
<field name="amount" attrs="{'readonly':[('move_id','!=',False)]}" sum="Total"/>
<field
name="amount"
attrs="{'readonly':[('move_id','!=',False)]}"
sum="Total"
/>
<field name="date" readonly="1" />
<field name="move_id" readonly="1" />
<button 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)]}"/>
<button
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>
</field>
<group name="extension">
<group name="extension_left">
</group>
<group name="extension_right">
<field name="display_create_all_moves" invisible="1"/>
<button 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)]}" />
<field
name="display_create_all_moves"
invisible="1"
/>
<button
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>
</page>
<page name="details" string="Details">
<group name="extra_details">
<group>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field
name="company_id"
groups="base.group_multi_company"
options="{'no_create': True}"
/>
<field
name="currency_id"
groups="base.group_multi_currency"
/>
</group>
<group>
<field 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"/>
<field
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>
</page>
@ -171,7 +362,6 @@
</form>
</field>
</record>
<record id="view_account_spread_account_manager" model="ir.ui.view">
<field name="model">account.spread</field>
<field name="inherit_id" ref="view_account_spread" />
@ -188,7 +378,6 @@
</field>
</field>
</record>
<record id="view_account_spread_tree" model="ir.ui.view">
<field name="model">account.spread</field>
<field name="arch" type="xml">
@ -198,16 +387,18 @@
</tree>
</field>
</record>
<record id="view_account_spread_search" model="ir.ui.view">
<field name="model">account.spread</field>
<field name="arch" type="xml">
<search>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<filter
string="Archived"
name="inactive"
domain="[('active','=',False)]"
/>
</search>
</field>
</record>
<record id="action_account_spread_form" model="ir.actions.act_window">
<field name="name">Spread Costs/Revenues</field>
<field name="res_model">account.spread</field>
@ -215,10 +406,10 @@
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_account_spread_tree" />
</record>
<menuitem id="menu_action_account_spread_form"
<menuitem
id="menu_action_account_spread_form"
parent="account.menu_finance_entries_accounting_entries"
action="action_account_spread_form"
groups="account.group_account_user,account.group_account_manager"/>
groups="account.group_account_user,account.group_account_manager"
/>
</odoo>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_account_spread_template" model="ir.ui.view">
<field name="model">account.spread.template</field>
<field name="arch" type="xml">
@ -10,22 +9,43 @@
<sheet>
<div class="oe_title">
<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>
<group name="main_info">
<group>
<field name="spread_type" />
<field name="company_id" groups="base.group_multi_company"/>
<field
name="company_id"
groups="base.group_multi_company"
/>
<field name="period_number" />
<field name="period_type" />
<field name="start_date" />
</group>
<group>
<field name="use_invoice_line_account" />
<field name="spread_account_id" domain="[('company_id', '=', company_id), ('deprecated', '=', False)]" 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"/>
<field
name="spread_account_id"
domain="[('company_id', '=', company_id), ('deprecated', '=', False)]"
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>
<div>
@ -35,19 +55,25 @@
<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,
</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">
<field name="name" />
<field name="product_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>
</field>
</sheet>
</form>
</field>
</record>
<record id="view_account_spread_template_tree" model="ir.ui.view">
<field name="model">account.spread.template</field>
<field name="arch" type="xml">
@ -59,7 +85,6 @@
</tree>
</field>
</record>
<record id="action_account_spread_template_form" model="ir.actions.act_window">
<field name="name">Spread Templates</field>
<field name="res_model">account.spread.template</field>
@ -67,10 +92,10 @@
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_account_spread_template_tree" />
</record>
<menuitem id="menu_action_account_spread_template_form"
<menuitem
id="menu_action_account_spread_template_form"
parent="account.account_account_menu"
action="action_account_spread_template_form"
groups="account.group_account_manager"/>
groups="account.group_account_manager"
/>
</odoo>

View File

@ -1,18 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_company_form" model="ir.ui.view">
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" />
<field name="arch" type="xml">
<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 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_expense_account_id" />
</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_expense_journal_id" />
</group>
@ -30,5 +39,4 @@
</xpath>
</field>
</record>
</odoo>

View File

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

View File

@ -1,13 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<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="arch" type="xml">
<form>
<group name="main_info">
<group>
<field name="company_id" readonly="1" groups="base.group_multi_company"/>
<field
name="company_id"
readonly="1"
groups="base.group_multi_company"
/>
<field name="invoice_type" readonly="1" />
<field name="spread_type" invisible="1" />
<field name="invoice_id" readonly="1" />
@ -15,20 +18,52 @@
</group>
<group>
<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 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}"/>
<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
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>
<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" />
</footer>
</form>
</field>
</record>
</odoo>