195 lines
6.8 KiB
Python
195 lines
6.8 KiB
Python
# Fusion Accounting - Account Transfer Wizard
|
|
# Copyright (C) 2026 Nexa Systems Inc. (https://nexasystems.ca)
|
|
# Original implementation for the Fusion Accounting module.
|
|
#
|
|
# Provides a transient model that creates a journal entry to move
|
|
# a balance from one account to another within the same company.
|
|
|
|
import logging
|
|
from datetime import date
|
|
|
|
from odoo import api, fields, models, Command, _
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FusionAccountTransfer(models.TransientModel):
|
|
"""Wizard for transferring balances between two accounts.
|
|
|
|
Creates a balanced journal entry with one debit line and one credit
|
|
line, effectively moving a specified amount from the source account
|
|
to the destination account.
|
|
"""
|
|
|
|
_name = 'fusion.account.transfer'
|
|
_description = 'Account Balance Transfer'
|
|
|
|
# =====================================================================
|
|
# Fields
|
|
# =====================================================================
|
|
|
|
company_id = fields.Many2one(
|
|
comodel_name='res.company',
|
|
string="Company",
|
|
required=True,
|
|
default=lambda self: self.env.company,
|
|
readonly=True,
|
|
)
|
|
currency_id = fields.Many2one(
|
|
comodel_name='res.currency',
|
|
string="Currency",
|
|
related='company_id.currency_id',
|
|
readonly=True,
|
|
)
|
|
source_account_id = fields.Many2one(
|
|
comodel_name='account.account',
|
|
string="Source Account",
|
|
required=True,
|
|
domain="[('company_ids', 'in', company_id)]",
|
|
help="The account to transfer funds FROM (will be credited).",
|
|
)
|
|
destination_account_id = fields.Many2one(
|
|
comodel_name='account.account',
|
|
string="Destination Account",
|
|
required=True,
|
|
domain="[('company_ids', 'in', company_id)]",
|
|
help="The account to transfer funds TO (will be debited).",
|
|
)
|
|
amount = fields.Monetary(
|
|
string="Amount",
|
|
required=True,
|
|
currency_field='currency_id',
|
|
help="Amount to transfer between the accounts.",
|
|
)
|
|
journal_id = fields.Many2one(
|
|
comodel_name='account.journal',
|
|
string="Journal",
|
|
required=True,
|
|
domain="[('type', '=', 'general'), ('company_id', '=', company_id)]",
|
|
help="Miscellaneous journal to record the transfer entry.",
|
|
)
|
|
date = fields.Date(
|
|
string="Date",
|
|
required=True,
|
|
default=fields.Date.context_today,
|
|
help="Date of the transfer journal entry.",
|
|
)
|
|
memo = fields.Char(
|
|
string="Memo",
|
|
help="Optional description for the journal entry.",
|
|
)
|
|
partner_id = fields.Many2one(
|
|
comodel_name='res.partner',
|
|
string="Partner",
|
|
help="Optional partner for the journal entry lines.",
|
|
)
|
|
|
|
# =====================================================================
|
|
# Constraints
|
|
# =====================================================================
|
|
|
|
@api.constrains('source_account_id', 'destination_account_id')
|
|
def _check_different_accounts(self):
|
|
for record in self:
|
|
if record.source_account_id == record.destination_account_id:
|
|
raise ValidationError(
|
|
_("Source and destination accounts must be different.")
|
|
)
|
|
|
|
@api.constrains('amount')
|
|
def _check_positive_amount(self):
|
|
for record in self:
|
|
if record.amount <= 0:
|
|
raise ValidationError(
|
|
_("Transfer amount must be greater than zero.")
|
|
)
|
|
|
|
# =====================================================================
|
|
# Default Values
|
|
# =====================================================================
|
|
|
|
@api.model
|
|
def default_get(self, fields_list):
|
|
"""Set default journal to the company's miscellaneous journal."""
|
|
defaults = super().default_get(fields_list)
|
|
if 'journal_id' not in defaults:
|
|
misc_journal = self.env['account.journal'].search([
|
|
('type', '=', 'general'),
|
|
('company_id', '=', self.env.company.id),
|
|
], limit=1)
|
|
if misc_journal:
|
|
defaults['journal_id'] = misc_journal.id
|
|
return defaults
|
|
|
|
# =====================================================================
|
|
# Action
|
|
# =====================================================================
|
|
|
|
def action_transfer(self):
|
|
"""Create a journal entry moving balance between accounts.
|
|
|
|
Generates a balanced journal entry:
|
|
- Credit line on the source account
|
|
- Debit line on the destination account
|
|
|
|
:returns: action dict pointing to the created journal entry
|
|
:raises UserError: if required fields are missing or invalid
|
|
"""
|
|
self.ensure_one()
|
|
|
|
if not self.source_account_id or not self.destination_account_id:
|
|
raise UserError(_("Both source and destination accounts are required."))
|
|
|
|
if self.amount <= 0:
|
|
raise UserError(_("The transfer amount must be positive."))
|
|
|
|
ref = self.memo or _("Account Transfer: %s → %s",
|
|
self.source_account_id.display_name,
|
|
self.destination_account_id.display_name)
|
|
|
|
move_vals = {
|
|
'journal_id': self.journal_id.id,
|
|
'date': self.date,
|
|
'ref': ref,
|
|
'company_id': self.company_id.id,
|
|
'move_type': 'entry',
|
|
'line_ids': [
|
|
# Credit the source account
|
|
Command.create({
|
|
'account_id': self.source_account_id.id,
|
|
'name': ref,
|
|
'debit': 0.0,
|
|
'credit': self.amount,
|
|
'partner_id': self.partner_id.id if self.partner_id else False,
|
|
}),
|
|
# Debit the destination account
|
|
Command.create({
|
|
'account_id': self.destination_account_id.id,
|
|
'name': ref,
|
|
'debit': self.amount,
|
|
'credit': 0.0,
|
|
'partner_id': self.partner_id.id if self.partner_id else False,
|
|
}),
|
|
],
|
|
}
|
|
|
|
move = self.env['account.move'].create(move_vals)
|
|
|
|
_logger.info(
|
|
"Fusion Account Transfer: created journal entry %s (id=%s) "
|
|
"for %.2f from %s to %s",
|
|
move.name, move.id, self.amount,
|
|
self.source_account_id.code,
|
|
self.destination_account_id.code,
|
|
)
|
|
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'account.move',
|
|
'res_id': move.id,
|
|
'view_mode': 'form',
|
|
'target': 'current',
|
|
'name': _("Transfer Entry"),
|
|
}
|