mirror of
https://github.com/bringout/oca-financial.git
synced 2026-04-25 09:01:59 +02:00
Initial commit: OCA Financial packages (186 packages)
This commit is contained in:
commit
3e0e8473fb
8757 changed files with 947473 additions and 0 deletions
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright 2015 Pedro M. Baeza
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from . import account_move_make_netting
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
# Copyright 2015 Pedro M. Baeza
|
||||
# Copyright 2017 Tecnativa - Vicent Cubells
|
||||
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountMoveMakeNetting(models.TransientModel):
|
||||
_name = "account.move.make.netting"
|
||||
_description = "Wizard to generate account moves for netting"
|
||||
_check_company_auto = True
|
||||
|
||||
company_id = fields.Many2one("res.company", required=True)
|
||||
journal_id = fields.Many2one(
|
||||
comodel_name="account.journal",
|
||||
required=True,
|
||||
domain="[('type', '=', 'general'), ('company_id', '=', company_id)]",
|
||||
check_company=True,
|
||||
)
|
||||
move_line_ids = fields.Many2many(
|
||||
comodel_name="account.move.line",
|
||||
check_company=True,
|
||||
string="Journal Items to Compensate",
|
||||
)
|
||||
partner_id = fields.Many2one("res.partner", readonly=True)
|
||||
company_currency_id = fields.Many2one(related="company_id.currency_id")
|
||||
balance = fields.Monetary(readonly=True, currency_field="company_currency_id")
|
||||
balance_type = fields.Selection(
|
||||
selection=[("pay", "To pay"), ("receive", "To receive")],
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
if len(self.env.context.get("active_ids", [])) < 2:
|
||||
raise UserError(_("You should select at least 2 journal items."))
|
||||
move_lines = self.env["account.move.line"].browse(
|
||||
self.env.context["active_ids"]
|
||||
)
|
||||
partners = self.env["res.partner"]
|
||||
for line in move_lines:
|
||||
if line.parent_state != "posted":
|
||||
raise UserError(_("Line '%s' is not posted.") % line.display_name)
|
||||
if line.account_id.account_type not in (
|
||||
"liability_payable",
|
||||
"asset_receivable",
|
||||
):
|
||||
raise UserError(
|
||||
_(
|
||||
"Line '%(line)s' has account '%(account)s' which is not "
|
||||
"a payable nor a receivable account."
|
||||
)
|
||||
% {
|
||||
"line": line.display_name,
|
||||
"account": line.account_id.display_name,
|
||||
}
|
||||
)
|
||||
if line.reconciled:
|
||||
raise UserError(
|
||||
_("Line '%s' is already reconciled.") % line.display_name
|
||||
)
|
||||
if not line.partner_id:
|
||||
raise UserError(
|
||||
_("Line '%s' doesn't have a partner.") % line.display_name
|
||||
)
|
||||
partners |= line.partner_id
|
||||
|
||||
if len(move_lines.account_id) == 1:
|
||||
raise UserError(
|
||||
_(
|
||||
"The 'Compensate' function is intended to balance "
|
||||
"operations on different accounts for the same partner. "
|
||||
"The selected journal items have the same "
|
||||
"account '%s', so you should use the 'Reconcile' function instead."
|
||||
)
|
||||
% move_lines.account_id.display_name
|
||||
)
|
||||
if len(partners) != 1:
|
||||
raise UserError(
|
||||
_(
|
||||
"The selected journal items have different partners: %s. "
|
||||
"All the selected journal items must have the same partner."
|
||||
)
|
||||
% ", ".join([p.display_name for p in partners])
|
||||
)
|
||||
res = super().default_get(fields_list)
|
||||
company = self.env.company
|
||||
ccur = company.currency_id
|
||||
debit_move_lines_debit = move_lines.filtered("debit")
|
||||
credit_move_lines_debit = move_lines.filtered("credit")
|
||||
balance = ccur.round(
|
||||
abs(sum(debit_move_lines_debit.mapped("amount_residual")))
|
||||
- abs(sum(credit_move_lines_debit.mapped("amount_residual")))
|
||||
)
|
||||
res.update(
|
||||
{
|
||||
"balance": abs(balance),
|
||||
"balance_type": "pay"
|
||||
if ccur.compare_amounts(balance, 0) < 0
|
||||
else "receive",
|
||||
"company_id": company.id,
|
||||
"move_line_ids": move_lines.ids,
|
||||
"partner_id": partners.id,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
def _prepare_account_move(self):
|
||||
# Group amounts by account
|
||||
account_groups = self.move_line_ids.read_group(
|
||||
[("id", "in", self.move_line_ids.ids)],
|
||||
["account_id", "amount_residual"],
|
||||
["account_id"],
|
||||
)
|
||||
debtors = []
|
||||
creditors = []
|
||||
total_debtors = 0.0
|
||||
total_creditors = 0.0
|
||||
ccur = self.company_id.currency_id
|
||||
for account_group in account_groups:
|
||||
balance = account_group["amount_residual"]
|
||||
group_vals = {
|
||||
"account_id": account_group["account_id"][0],
|
||||
"balance": abs(balance),
|
||||
}
|
||||
if ccur.compare_amounts(balance, 0) > 0:
|
||||
debtors.append(group_vals)
|
||||
total_debtors += balance
|
||||
else:
|
||||
creditors.append(group_vals)
|
||||
total_creditors += abs(balance)
|
||||
# Compute move lines
|
||||
netting_amount = min(total_creditors, total_debtors)
|
||||
field_map = {1: "debit", 0: "credit"}
|
||||
move_lines = []
|
||||
for i, group in enumerate([debtors, creditors]):
|
||||
available_amount = netting_amount
|
||||
for account_group in group:
|
||||
move_line_vals = {
|
||||
field_map[i]: min(available_amount, account_group["balance"]),
|
||||
"partner_id": self.partner_id.id,
|
||||
"account_id": account_group["account_id"],
|
||||
}
|
||||
move_lines.append((0, 0, move_line_vals))
|
||||
available_amount -= account_group["balance"]
|
||||
if ccur.compare_amounts(available_amount, 0) <= 0:
|
||||
break
|
||||
vals = {
|
||||
"ref": _("AR/AP netting"),
|
||||
"journal_id": self.journal_id.id,
|
||||
"company_id": self.company_id.id,
|
||||
"line_ids": move_lines,
|
||||
}
|
||||
return vals
|
||||
|
||||
def button_compensate(self):
|
||||
self.ensure_one()
|
||||
# Create account move
|
||||
move = self.env["account.move"].create(self._prepare_account_move())
|
||||
move.action_post()
|
||||
# Make reconciliation
|
||||
for move_line in move.line_ids:
|
||||
to_reconcile = move_line + self.move_line_ids.filtered(
|
||||
lambda x: x.account_id == move_line.account_id
|
||||
)
|
||||
to_reconcile.reconcile()
|
||||
# Open created move
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
"account.action_move_journal_line"
|
||||
)
|
||||
action.update(
|
||||
{
|
||||
"view_mode": "form",
|
||||
"views": False,
|
||||
"view_id": False,
|
||||
"res_id": move.id,
|
||||
}
|
||||
)
|
||||
return action
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="act_account_move_make_netting" model="ir.actions.act_window">
|
||||
<field name="name">Compensate</field>
|
||||
<field name="res_model">account.move.make.netting</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="binding_model_id" ref="account.model_account_move_line" />
|
||||
<field name="binding_view_types">list</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_move_make_netting_form" model="ir.ui.view">
|
||||
<field name="name">Compensate entries</field>
|
||||
<field name="model">account.move.make.netting</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<p
|
||||
>This operation will generate a journal entry whose lines are counterpart of the receivable/payable accounts selected, and reconcile each other, letting this balance in the partner.</p>
|
||||
<group>
|
||||
<field name="company_id" invisible="1" />
|
||||
<field name="company_currency_id" invisible="1" />
|
||||
<field name="partner_id" />
|
||||
<field name="balance" />
|
||||
<field
|
||||
name="balance_type"
|
||||
attrs="{'invisible': [('balance', '=', 0)]}"
|
||||
/>
|
||||
<field name="journal_id" />
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
name="button_compensate"
|
||||
string="Compensate"
|
||||
type="object"
|
||||
default_focus="1"
|
||||
class="btn-primary"
|
||||
/>
|
||||
<button string="Cancel" class="btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue