Initial commit
This commit is contained in:
194
Fusion Accounting/models/account_transfer.py
Normal file
194
Fusion Accounting/models/account_transfer.py
Normal file
@@ -0,0 +1,194 @@
|
||||
# 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"),
|
||||
}
|
||||
Reference in New Issue
Block a user