first push message
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from . import account_common_partner_report
|
||||
from . import account_aged_trial_balance
|
||||
from . import account_balance_report
|
||||
from . import account_bank_book_report
|
||||
from . import account_cash_book_report
|
||||
from . import account_day_book_report
|
||||
from . import account_lock_date
|
||||
from . import account_print_journal
|
||||
from . import account_report_general_ledger
|
||||
from . import account_report_partner_ledger
|
||||
from . import asset_depreciation_confirmation
|
||||
from . import asset_modify
|
||||
from . import cash_flow_report
|
||||
from . import financial_report
|
||||
from . import import_bank_statement
|
||||
from . import kit_account_tax_report
|
||||
@@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
import time
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo import fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountAgedTrialBalance(models.TransientModel):
|
||||
_name = 'account.aged.trial.balance'
|
||||
_inherit = 'account.common.partner.report'
|
||||
_description = 'Account Aged Trial balance Report'
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_aged_trail_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_aged_trail_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="Account Aged Trial balance Report", default="Account Aged Trial balance Report", required=True, translate=True)
|
||||
|
||||
journal_ids = fields.Many2many('account.journal', string='Journals',
|
||||
required=True)
|
||||
period_length = fields.Integer(string='Period Length (days)',
|
||||
required=True, default=30)
|
||||
date_from = fields.Date(default=lambda *a: time.strftime('%Y-%m-%d'))
|
||||
|
||||
def _print_report(self, data):
|
||||
res = {}
|
||||
data = self.pre_print_report(data)
|
||||
data['form'].update(self.read(['period_length'])[0])
|
||||
period_length = data['form']['period_length']
|
||||
if period_length <= 0:
|
||||
raise UserError(_('You must set a period length greater than 0.'))
|
||||
if not data['form']['date_from']:
|
||||
raise UserError(_('You must set a start date.'))
|
||||
|
||||
start = data['form']['date_from']
|
||||
|
||||
for i in range(5)[::-1]:
|
||||
stop = start - relativedelta(days=period_length - 1)
|
||||
res[str(i)] = {
|
||||
'name': (i != 0 and (
|
||||
str((5 - (i + 1)) * period_length) + '-' + str(
|
||||
(5 - i) * period_length)) or (
|
||||
'+' + str(4 * period_length))),
|
||||
'stop': start.strftime('%Y-%m-%d'),
|
||||
'start': (i != 0 and stop.strftime('%Y-%m-%d') or False),
|
||||
}
|
||||
start = stop - relativedelta(days=1)
|
||||
data['form'].update(res)
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_aged_partner_balance').with_context(
|
||||
landscape=True).report_action(self, data=data)
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Aged Trial Balance Form View-->
|
||||
<record id="account_aged_trial_balance_view_form" model="ir.ui.view">
|
||||
<field name="name">account.aged.trial.balance.view.form</field>
|
||||
<field name="model">account.aged.trial.balance</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Report Options">
|
||||
<group col="4">
|
||||
<field name="date_from"/>
|
||||
<field name="period_length"/>
|
||||
<newline/>
|
||||
<field name="result_selection" widget="radio"/>
|
||||
<field name="target_move" widget="radio"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="check_report" string="Print" type="object" default_focus="1" class="oe_highlight"/>
|
||||
<button string="Cancel" class="btn btn-default" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Aged Trial Balance-->
|
||||
<record id="action_account_aged_balance_view" model="ir.actions.act_window">
|
||||
<field name="name">Aged Partner Balance</field>
|
||||
<field name="res_model">account.aged.trial.balance</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="account_aged_trial_balance_view_form"/>
|
||||
<field name="context">{}</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Aged Partner Balance-->
|
||||
<menuitem id="menu_aged_trial_balance"
|
||||
name="Aged Partner Balance"
|
||||
sequence="2"
|
||||
action="action_account_aged_balance_view"
|
||||
parent="account.menu_finance_reports"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class AccountBalanceReport(models.TransientModel):
|
||||
_name = 'account.balance.report'
|
||||
_inherit = "account.common.account.report"
|
||||
_description = 'Trial Balance Report'
|
||||
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_balance_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_balance_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
name = fields.Char(string="Trial Balance", default="Trial Balance", required=True, translate=True)
|
||||
journal_ids = fields.Many2many('account.journal',
|
||||
'account_balance_report_journal_rel',
|
||||
'account_id', 'journal_id',
|
||||
string='Journals', required=True,
|
||||
default=[])
|
||||
|
||||
@api.model
|
||||
def _get_report_name(self):
|
||||
period_id = self._get_selected_period_id()
|
||||
return self.env['consolidation.period'].browse(period_id)['display_name'] or _("Trial Balance")
|
||||
|
||||
def _print_report(self, data):
|
||||
data = self.pre_print_report(data)
|
||||
records = self.env[data['model']].browse(data.get('ids', []))
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_trial_balance').report_action(
|
||||
records, data=data)
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Balance Report Form View-->
|
||||
<record id="account_report_balance_view" model="ir.ui.view">
|
||||
<field name="name">account.balance.report.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">account.balance.report</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="journal_ids" position="replace"/>
|
||||
<xpath expr="//field[@name='target_move']" position="after">
|
||||
<field name="display_account" widget="radio"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Balance Report-->
|
||||
<record id="action_account_balance_menu" model="ir.actions.act_window">
|
||||
<field name="name">Trial Balance</field>
|
||||
<field name="res_model">account.balance.report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account_report_balance_view"/>
|
||||
<field name="target">new</field>
|
||||
<field name="binding_model_id" ref="account.model_account_account"/>
|
||||
</record>
|
||||
<!--Menu Trial Balance-->
|
||||
<menuitem id="menu_Balance_report"
|
||||
name="Trial Balance"
|
||||
sequence="7"
|
||||
action="action_account_balance_menu"
|
||||
parent="base_accounting_kit.account_reports_audit"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,112 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from datetime import date
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class BankBookWizard(models.TransientModel):
|
||||
_name = 'account.bank.book.report'
|
||||
_description = 'Account Bank Book Report'
|
||||
|
||||
company_id = fields.Many2one('res.company', string='Company',
|
||||
readonly=True,
|
||||
default=lambda self: self.env.company)
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries')],
|
||||
string='Target Moves', required=True,
|
||||
default='posted')
|
||||
date_from = fields.Date(string='Start Date', default=date.today(),
|
||||
required=True)
|
||||
date_to = fields.Date(string='End Date', default=date.today(),
|
||||
required=True)
|
||||
display_account = fields.Selection(
|
||||
[('all', 'All'), ('movement', 'With movements'),
|
||||
('not_zero', 'With balance is not equal to 0')],
|
||||
string='Display Accounts', required=True, default='movement')
|
||||
sortby = fields.Selection(
|
||||
[('sort_date', 'Date'), ('sort_journal_partner', 'Journal & Partner')],
|
||||
string='Sort by', required=True, default='sort_date')
|
||||
initial_balance = fields.Boolean(string='Include Initial Balances',
|
||||
help='If you selected date, this field allow you to add a '
|
||||
'row to display the amount of debit/credit/balance that '
|
||||
'precedes the filter you\'ve set.')
|
||||
|
||||
def _get_default_account_ids(self):
|
||||
journals = self.env['account.journal'].search([('type', '=', 'bank')])
|
||||
accounts = []
|
||||
for journal in journals:
|
||||
accounts.append(journal.default_account_id.id)
|
||||
return accounts
|
||||
|
||||
account_ids = fields.Many2many('account.account',
|
||||
'account_report_bankbook_account_rel',
|
||||
'report_id', 'account_id',
|
||||
'Accounts',
|
||||
default=_get_default_account_ids)
|
||||
journal_ids = fields.Many2many('account.journal',
|
||||
'account_report_bankbook_journal_rel',
|
||||
'account_id', 'journal_id',
|
||||
string='Journals', required=True,
|
||||
default=lambda self: self.env[
|
||||
'account.journal'].search([]))
|
||||
|
||||
@api.onchange('account_ids')
|
||||
def onchange_account_ids(self):
|
||||
if self.account_ids:
|
||||
journals = self.env['account.journal'].search(
|
||||
[('type', '=', 'bank')])
|
||||
accounts = []
|
||||
for journal in journals:
|
||||
accounts.append(journal.default_account_id.id)
|
||||
domain = {'account_ids': [('id', 'in', accounts)]}
|
||||
return {'domain': domain}
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
return result
|
||||
|
||||
def check_report(self):
|
||||
self.ensure_one()
|
||||
if self.initial_balance and not self.date_from:
|
||||
raise UserError(_("You must choose a Start Date"))
|
||||
data = {}
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = self.read(
|
||||
['date_from', 'date_to', 'journal_ids', 'target_move',
|
||||
'display_account',
|
||||
'account_ids', 'sortby', 'initial_balance'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(used_context,
|
||||
lang=self.env.context.get(
|
||||
'lang') or 'en_US')
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_bank_book').report_action(self,
|
||||
data=data)
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!-- Account Bank Book Report Form View-->
|
||||
<record id="account_bank_book_report_view_form" model="ir.ui.view">
|
||||
<field name="name">account.bank.book.report.view.form</field>
|
||||
<field name="model">account.bank.book.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Bank Book Report">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<group col="4">
|
||||
<field name="target_move" widget="radio"/>
|
||||
<field name="sortby" widget="radio"/>
|
||||
<field name="initial_balance"/>
|
||||
<newline/>
|
||||
<newline/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="account_ids" widget="many2many_tags"/>
|
||||
<field name="journal_ids" widget="many2many_tags" options="{'no_create': True}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="check_report" string="Print" type="object" default_focus="1" class="oe_highlight"/>
|
||||
<button string="Cancel" class="btn btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Bank Book Report-->
|
||||
<record id="action_account_bank_book_view" model="ir.actions.act_window">
|
||||
<field name="name">Bank Book Report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.bank.book.report</field>
|
||||
<field name="view_id" ref="account_bank_book_report_view_form"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Bank Book-->
|
||||
<menuitem id="account_bank_book_menu" name="Bank Book" action="action_account_bank_book_view"
|
||||
parent="base_accounting_kit.account_reports_daily_reports"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,110 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from datetime import date
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class CashBookWizard(models.TransientModel):
|
||||
_name = 'account.cash.book.report'
|
||||
_description = 'Account Cash Book Report'
|
||||
|
||||
company_id = fields.Many2one('res.company', string='Company',
|
||||
readonly=True,
|
||||
default=lambda self: self.env.company)
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries')], string='Target Moves', required=True,
|
||||
default='posted')
|
||||
date_from = fields.Date(string='Start Date', default=date.today(),
|
||||
required=True)
|
||||
date_to = fields.Date(string='End Date', default=date.today(),
|
||||
required=True)
|
||||
display_account = fields.Selection(
|
||||
[('all', 'All'), ('movement', 'With movements'),
|
||||
('not_zero', 'With balance is not equal to 0')],
|
||||
string='Display Accounts', required=True, default='movement')
|
||||
sortby = fields.Selection(
|
||||
[('sort_date', 'Date'), ('sort_journal_partner', 'Journal & Partner')],
|
||||
string='Sort by',
|
||||
required=True, default='sort_date')
|
||||
initial_balance = fields.Boolean(string='Include Initial Balances',
|
||||
help='If you selected date, this field allow you to add a row to display the amount of debit/credit/balance that precedes the filter you\'ve set.')
|
||||
|
||||
def _get_default_account_ids(self):
|
||||
journals = self.env['account.journal'].search([('type', '=', 'cash')])
|
||||
accounts = []
|
||||
for journal in journals:
|
||||
accounts.append(journal.default_account_id.id)
|
||||
return accounts
|
||||
|
||||
account_ids = fields.Many2many('account.account',
|
||||
'account_report_cashbook_account_rel',
|
||||
'report_id', 'account_id',
|
||||
'Accounts',
|
||||
default=_get_default_account_ids)
|
||||
journal_ids = fields.Many2many('account.journal',
|
||||
'account_report_cashbook_journal_rel',
|
||||
'account_id', 'journal_id',
|
||||
string='Journals', required=True,
|
||||
default=lambda self: self.env[
|
||||
'account.journal'].search([]))
|
||||
|
||||
@api.onchange('account_ids')
|
||||
def onchange_account_ids(self):
|
||||
if self.account_ids:
|
||||
journals = self.env['account.journal'].search(
|
||||
[('type', '=', 'cash')])
|
||||
accounts = []
|
||||
for journal in journals:
|
||||
accounts.append(journal.default_account_id.id)
|
||||
domain = {'account_ids': [('id', 'in', accounts)]}
|
||||
return {'domain': domain}
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
return result
|
||||
|
||||
def check_report(self):
|
||||
self.ensure_one()
|
||||
if self.initial_balance and not self.date_from:
|
||||
raise UserError(_("You must choose a Start Date"))
|
||||
data = {}
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = self.read(
|
||||
['date_from', 'date_to', 'journal_ids', 'target_move',
|
||||
'display_account',
|
||||
'account_ids', 'sortby', 'initial_balance'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(used_context,
|
||||
lang=self.env.context.get(
|
||||
'lang') or 'en_US')
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_cash_book').report_action(self,
|
||||
data=data)
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!-- Account Cash Book Report Form View-->
|
||||
<record id="account_cash_book_report_view_form" model="ir.ui.view">
|
||||
<field name="name">account.cash.book.report.view.form</field>
|
||||
<field name="model">account.cash.book.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Cash Book Report">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<group col="4">
|
||||
<field name="target_move" widget="radio"/>
|
||||
<field name="sortby" widget="radio"/>
|
||||
<field name="initial_balance"/>
|
||||
<newline/>
|
||||
<newline/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="account_ids" widget="many2many_tags"/>
|
||||
<field name="journal_ids" widget="many2many_tags" options="{'no_create': True}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="check_report" string="Print" type="object" default_focus="1" class="oe_highlight"/>
|
||||
<button string="Cancel" class="btn btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Cash Book Report-->
|
||||
<record id="action_account_cash_book_view" model="ir.actions.act_window">
|
||||
<field name="name">Cash Book Report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.cash.book.report</field>
|
||||
<field name="view_id" ref="account_cash_book_report_view_form"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Cash Book-->
|
||||
<menuitem id="account_cash_book_menu" name="Cash Book" action="action_account_cash_book_view"
|
||||
parent="base_accounting_kit.account_reports_daily_reports"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models
|
||||
from odoo.tools.misc import get_lang
|
||||
|
||||
|
||||
class AccountingCommonPartnerReport(models.TransientModel):
|
||||
_name = 'account.common.partner.report'
|
||||
_inherit = "account.report"
|
||||
_description = 'Account Common Partner Report'
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_common_parnter_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_common_parnter_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True,
|
||||
default=lambda self: self.env.company)
|
||||
journal_ids = fields.Many2many(
|
||||
comodel_name='account.journal',
|
||||
string='Journals',
|
||||
required=True,
|
||||
default=lambda self: self.env['account.journal'].search([('company_id', '=', self.company_id.id)]),
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
)
|
||||
date_from = fields.Date(string='Start Date')
|
||||
date_to = fields.Date(string='End Date')
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries'),
|
||||
], string='Target Moves', required=True, default='posted')
|
||||
|
||||
result_selection = fields.Selection([('customer', 'Receivable Accounts'),
|
||||
('supplier', 'Payable Accounts'),
|
||||
('customer_supplier',
|
||||
'Receivable and Payable Accounts')
|
||||
], string="Partner's", required=True,
|
||||
default='customer')
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
return result
|
||||
|
||||
def check_report(self):
|
||||
self.ensure_one()
|
||||
data = {}
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = self.read(['date_from', 'date_to', 'journal_ids', 'target_move', 'company_id'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(used_context, lang=get_lang(self.env).code)
|
||||
return self.with_context(discard_logo_check=True)._print_report(data)
|
||||
|
||||
def _print_report(self, data):
|
||||
data['form'].update(self.read(
|
||||
['date_from_cmp', 'debit_credit', 'date_to_cmp', 'filter_cmp',
|
||||
'account_report_id', 'enable_filter', 'label_filter',
|
||||
'target_move'])[0])
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_cash_flow').report_action(self,
|
||||
data=data,
|
||||
config=False)
|
||||
|
||||
def pre_print_report(self, data):
|
||||
data['form'].update(self.read(['result_selection'])[0])
|
||||
return data
|
||||
@@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from datetime import date
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class DayBookWizard(models.TransientModel):
|
||||
_name = 'account.day.book.report'
|
||||
_description = 'Account Day Book Report'
|
||||
|
||||
company_id = fields.Many2one('res.company', string='Company',
|
||||
readonly=True,
|
||||
default=lambda self: self.env.company)
|
||||
journal_ids = fields.Many2many('account.journal', string='Journals',
|
||||
required=True,
|
||||
default=lambda self: self.env[
|
||||
'account.journal'].search([]))
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries')], string='Target Moves', required=True,
|
||||
default='posted')
|
||||
|
||||
account_ids = fields.Many2many('account.account',
|
||||
'account_report_daybook_account_rel',
|
||||
'report_id', 'account_id',
|
||||
'Accounts')
|
||||
|
||||
date_from = fields.Date(string='Start Date', default=date.today(),
|
||||
required=True)
|
||||
date_to = fields.Date(string='End Date', default=date.today(),
|
||||
required=True)
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
return result
|
||||
|
||||
def check_report(self):
|
||||
self.ensure_one()
|
||||
data = {}
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = \
|
||||
self.read(['date_from', 'date_to', 'journal_ids', 'target_move',
|
||||
'account_ids'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(used_context,
|
||||
lang=self.env.context.get(
|
||||
'lang') or 'en_US')
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.day_book_pdf_report').report_action(self,
|
||||
data=data)
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Day Book Report View Form-->
|
||||
<record id="account_day_book_report_view_form" model="ir.ui.view">
|
||||
<field name="name">account.day.book.report.view.form</field>
|
||||
<field name="model">account.day.book.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Cash Book Report">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<group col="4">
|
||||
<field name="target_move" widget="radio"/>
|
||||
<newline/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="account_ids" widget="many2many_tags"/>
|
||||
<field name="journal_ids" widget="many2many_tags" options="{'no_create': True}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="check_report" string="Print" type="object" default_focus="1" class="oe_highlight"/>
|
||||
<button string="Cancel" class="btn btn-default" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Day Book Report-->
|
||||
<record id="action_account_day_book_view" model="ir.actions.act_window">
|
||||
<field name="name">Day Book Report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.day.book.report</field>
|
||||
<field name="view_id" ref="account_day_book_report_view_form"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Day Book-->
|
||||
<menuitem id="account_day_book_menu" name="Day Book" action="action_account_day_book_view"
|
||||
parent="base_accounting_kit.account_reports_daily_reports"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountUpdateLockDate(models.TransientModel):
|
||||
_name = 'account.lock.date'
|
||||
_description = 'Lock date for accounting'
|
||||
|
||||
company_id = fields.Many2one(comodel_name='res.company', string="Company",
|
||||
required=True)
|
||||
sale_lock_date = fields.Date(string="Sales Lock Date", help='Prevents creating and modifying invoices up to the date.')
|
||||
purchase_lock_date = fields.Date(string="Purchase Lock date", help='Prevents creating and modifying bills up to the date.')
|
||||
hard_lock_date = fields.Date(string="Lock Everyone",
|
||||
help="No users, including Advisers, can edit accounts prior to and "
|
||||
"inclusive of this date. Use it for fiscal year locking for "
|
||||
"example.")
|
||||
@api.model
|
||||
def default_get(self, field_list):
|
||||
res = super(AccountUpdateLockDate, self).default_get(field_list)
|
||||
company = self.env.company
|
||||
res.update({
|
||||
'company_id': company.id,
|
||||
'sale_lock_date': company.sale_lock_date,
|
||||
'purchase_lock_date': company.purchase_lock_date,
|
||||
'hard_lock_date': company.hard_lock_date,
|
||||
})
|
||||
return res
|
||||
|
||||
def _check_execute_allowed(self):
|
||||
self.ensure_one()
|
||||
has_adviser_group = self.env.user.has_group(
|
||||
'account.group_account_manager')
|
||||
if not (has_adviser_group or self.env.uid == SUPERUSER_ID):
|
||||
raise UserError(_("You are not allowed to execute this action."))
|
||||
|
||||
def execute(self):
|
||||
self.ensure_one()
|
||||
self._check_execute_allowed()
|
||||
self.company_id.sudo().write({
|
||||
'sale_lock_date': self.sale_lock_date,
|
||||
'purchase_lock_date': self.purchase_lock_date,
|
||||
'hard_lock_date': self.hard_lock_date,
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Lock Date Form View-->
|
||||
<record model="ir.ui.view" id="account_lock_date_view_form">
|
||||
<field name="name">account.lock.date.view.form</field>
|
||||
<field name="model">account.lock.date</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<label for="sale_lock_date"/>
|
||||
<div class="d-flex">
|
||||
<field name="sale_lock_date" class="oe_inline"/><span class="text-muted"><i>to lock invoices</i></span>
|
||||
</div>
|
||||
<label for="purchase_lock_date"/>
|
||||
<div class="d-flex">
|
||||
<field name="purchase_lock_date" class="oe_inline"/><span class="text-muted"><i>to lock bills</i></span>
|
||||
</div>
|
||||
<field name="hard_lock_date" class="oe_inline"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Update" name="execute" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Lock Date-->
|
||||
<record model="ir.actions.act_window" id="account_update_lock_date_act_window">
|
||||
<field name="name">Lock your Fiscal Period</field>
|
||||
<field name="res_model">account.lock.date</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Lock Dates-->
|
||||
<menuitem id="actions_menu"
|
||||
name="Actions"
|
||||
sequence="500"
|
||||
parent="account.menu_finance_entries"
|
||||
groups="base_accounting_kit.group_account_chief"/>
|
||||
<menuitem id="menu_lock_dates"
|
||||
name="Lock Dates"
|
||||
action="account_update_lock_date_act_window"
|
||||
parent="base_accounting_kit.actions_menu"
|
||||
groups="base_accounting_kit.group_account_chief"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountPrintJournal(models.TransientModel):
|
||||
_name = "account.print.journal"
|
||||
_inherit = "account.common.journal.report"
|
||||
_description = "Account Print Journal"
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_common_print_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_common_print_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="Journal Audit", default="Journal Audit", required=True, translate=True)
|
||||
sort_selection = fields.Selection(
|
||||
[('date', 'Date'), ('move_name', 'Journal Entry Number')],
|
||||
'Entries Sorted by', required=True, default='move_name')
|
||||
journal_ids = fields.Many2many('account.journal', string='Journals',
|
||||
required=True,
|
||||
default=lambda self: self.env[
|
||||
'account.journal'].search(
|
||||
[('type', 'in', ['sale', 'purchase'])]))
|
||||
|
||||
def _print_report(self, data):
|
||||
data = self.pre_print_report(data)
|
||||
data['form'].update({'sort_selection': self.sort_selection})
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_journal').with_context(
|
||||
landscape=True).report_action(self, data=data)
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Print Journal Form View-->
|
||||
<record id="account_common_report_inherited" model="ir.ui.view">
|
||||
<field name="name">account.print.journal.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">account.print.journal</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='target_move']" position="after">
|
||||
<field name="amount_currency" groups="base.group_multi_currency"/>
|
||||
<field name="sort_selection" widget="radio"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Print Journal-->
|
||||
<record id="action_account_print_journal_menu" model="ir.actions.act_window">
|
||||
<field name="name">Journals Audit</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.print.journal</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account_common_report_inherited"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Journals Audit-->
|
||||
<menuitem id="menu_print_journal"
|
||||
name="Journals Audit"
|
||||
sequence="9"
|
||||
action="action_account_print_journal_menu"
|
||||
parent="base_accounting_kit.account_reports_audit"
|
||||
groups="base_accounting_kit.group_account_chief,account.group_account_user"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,65 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountReportGeneralLedger(models.TransientModel):
|
||||
_name = "account.report.general.ledger"
|
||||
_inherit = "account.common.account.report"
|
||||
_description = "General Ledger Report"
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_report_general_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_report_general_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="General Ledger", default="General Ledger", required=True, translate=True)
|
||||
initial_balance = fields.Boolean(string='Include Initial Balances',
|
||||
help='If you selected date, this field '
|
||||
'allow you to add a row to display '
|
||||
'the amount of debit/credit/balance '
|
||||
'that precedes the filter you\'ve '
|
||||
'set.')
|
||||
sortby = fields.Selection(
|
||||
[('sort_date', 'Date'), ('sort_journal_partner', 'Journal & Partner')],
|
||||
string='Sort by', required=True, default='sort_date')
|
||||
journal_ids = fields.Many2many('account.journal',
|
||||
'account_report_general_ledger_journal_rel',
|
||||
'account_id', 'journal_id',
|
||||
string='Journals', required=True)
|
||||
|
||||
def _print_report(self, data):
|
||||
data = self.pre_print_report(data)
|
||||
data['form'].update(self.read(['initial_balance', 'sortby'])[0])
|
||||
if data['form'].get('initial_balance') and not data['form'].get(
|
||||
'date_from'):
|
||||
raise UserError(_("You must define a Start Date"))
|
||||
records = self.env[data['model']].browse(data.get('ids', []))
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_general_ledger').with_context(
|
||||
landscape=True).report_action(records, data=data)
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Report General Ledger Form View-->
|
||||
<record id="account_report_general_ledger_view" model="ir.ui.view">
|
||||
<field name="name">account.report.general.ledger.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">account.report.general.ledger</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='target_move']" position="after">
|
||||
<field name="sortby" widget="radio"/>
|
||||
<field name="display_account" widget="radio"/>
|
||||
<field name="initial_balance"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Report General Ledger-->
|
||||
<record id="action_account_general_ledger_menu" model="ir.actions.act_window">
|
||||
<field name="name">General Ledger</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">account.report.general.ledger</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account_report_general_ledger_view"/>
|
||||
<field name="target">new</field>
|
||||
<field name="binding_model_id" ref="account.model_account_account"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
<!--Menu General Ledger-->
|
||||
<menuitem
|
||||
id="menu_general_ledger"
|
||||
name="General Ledger"
|
||||
sequence="3"
|
||||
parent="base_accounting_kit.account_reports_audit"
|
||||
action="action_account_general_ledger_menu"
|
||||
groups="account.group_account_user,base_accounting_kit.group_account_chief"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountPartnerLedger(models.TransientModel):
|
||||
_name = "account.report.partner.ledger"
|
||||
_inherit = "account.common.partner.report"
|
||||
_description = "Account Partner Ledger"
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_report_partner_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_report_partner_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="Partner Ledger Report", default="Partner Ledger Report", required=True, translate=True)
|
||||
amount_currency = fields.Boolean("With Currency",
|
||||
help="It adds the currency column on report if the "
|
||||
"currency differs from the company currency.")
|
||||
reconciled = fields.Boolean('Reconciled Entries')
|
||||
|
||||
def _print_report(self, data):
|
||||
data = self.pre_print_report(data)
|
||||
data['form'].update({'reconciled': self.reconciled,
|
||||
'amount_currency': self.amount_currency})
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_partnerledger').report_action(
|
||||
self, data=data)
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Account Report Partner Ledger Form View-->
|
||||
<record id="account_report_partner_ledger_view" model="ir.ui.view">
|
||||
<field name="name">account.report.partner.ledger.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">account.report.partner.ledger</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='target_move']" position="after">
|
||||
<field name="result_selection"/>
|
||||
<field name="amount_currency" groups="base.group_multi_currency"/>
|
||||
<newline/>
|
||||
<field name="reconciled"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Account Report Partner Ledger-->
|
||||
<record id="action_partner_leadger" model="ir.actions.act_window">
|
||||
<field name="name">Partner Ledger</field>
|
||||
<field name="res_model">account.report.partner.ledger</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="account_report_partner_ledger_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Partner Ledger-->
|
||||
<menuitem name="Partner Ledger"
|
||||
id="menu_partner_ledger" sequence="1"
|
||||
parent="base_accounting_kit.account_reports_partner"
|
||||
action="action_partner_leadger"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class AssetDepreciationConfirmationWizard(models.TransientModel):
|
||||
_name = "asset.depreciation.confirmation"
|
||||
_description = "Asset Depreciation Confirmation"
|
||||
|
||||
date = fields.Date('Account Date', required=True,
|
||||
help="Choose the period for which you want to automatically "
|
||||
"post the depreciation lines of running assets",
|
||||
default=fields.Date.context_today)
|
||||
|
||||
def asset_compute(self):
|
||||
self.ensure_one()
|
||||
context = self._context
|
||||
created_move_ids = self.env['account.asset.asset'].sudo().compute_generated_entries(self.date, asset_type=context.get('asset_type'))
|
||||
moves = self.env['account.move'].browse(created_move_ids)
|
||||
auto_post_draft_moves = moves.filtered(lambda move: move.state == 'draft' and move.auto_post)
|
||||
auto_post_draft_moves.write({'auto_post': 'at_date'})
|
||||
return {
|
||||
'name': _('Created Asset Moves') if context.get('asset_type') == 'purchase' else _('Created Revenue Moves'),
|
||||
'view_mode': 'list,form',
|
||||
'res_model': 'account.move',
|
||||
'view_id': False,
|
||||
'domain': "[('id','in',[" + ','.join(str(id) for id in created_move_ids) + "])]",
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Asset Depreciation Confirmation Form View-->
|
||||
<record id="asset_depreciation_confirmation_view_form" model="ir.ui.view">
|
||||
<field name="name">asset.depreciation.confirmation.view.form</field>
|
||||
<field name="model">asset.depreciation.confirmation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Compute Asset">
|
||||
<div>
|
||||
<p>
|
||||
This wizard will post installment/depreciation lines for the selected month.<br/>
|
||||
This will generate journal entries for all related installment lines on this period of asset/revenue recognition as well.
|
||||
</p>
|
||||
</div>
|
||||
<group>
|
||||
<field name="date"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Generate Entries" name="asset_compute" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Asset Depreciation Confirmation-->
|
||||
<record id="action_asset_depreciation_confirmation_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Post Depreciation Lines</field>
|
||||
<field name="res_model">asset.depreciation.confirmation</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="asset_depreciation_confirmation_view_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'asset_type': 'purchase'}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from lxml import etree
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class AssetModify(models.TransientModel):
|
||||
_name = 'asset.modify'
|
||||
_description = 'Modify Asset'
|
||||
|
||||
name = fields.Text(string='Reason', required=True)
|
||||
method_number = fields.Integer(string='Number of Depreciations', required=True)
|
||||
method_period = fields.Integer(string='Period Length')
|
||||
method_end = fields.Date(string='Ending date')
|
||||
asset_method_time = fields.Char(compute='_get_asset_method_time',
|
||||
string='Asset Method Time', readonly=True)
|
||||
|
||||
def _get_asset_method_time(self):
|
||||
if self.env.context.get('active_id'):
|
||||
asset = self.env['account.asset.asset'].browse(self.env.context.get('active_id'))
|
||||
self.asset_method_time = asset.method_time
|
||||
|
||||
@api.model
|
||||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
|
||||
result = super(AssetModify, self).fields_view_get(view_id, view_type, toolbar=toolbar, submenu=submenu)
|
||||
asset_id = self.env.context.get('active_id')
|
||||
active_model = self.env.context.get('active_model')
|
||||
if active_model == 'account.asset.asset' and asset_id:
|
||||
asset = self.env['account.asset.asset'].browse(asset_id)
|
||||
doc = etree.XML(result['arch'])
|
||||
if asset.method_time == 'number' and doc.xpath("//field[@name='method_end']"):
|
||||
node = doc.xpath("//field[@name='method_end']")[0]
|
||||
node.set('invisible', '1')
|
||||
# setup_modifiers(node, result['fields']['method_end'])
|
||||
elif asset.method_time == 'end' and doc.xpath("//field[@name='method_number']"):
|
||||
node = doc.xpath("//field[@name='method_number']")[0]
|
||||
node.set('invisible', '1')
|
||||
# setup_modifiers(node, result['fields']['method_number'])
|
||||
result['arch'] = etree.tostring(doc, encoding='unicode')
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(AssetModify, self).default_get(fields)
|
||||
asset_id = self.env.context.get('active_id')
|
||||
asset = self.env['account.asset.asset'].browse(asset_id)
|
||||
if 'name' in fields:
|
||||
res.update({'name': asset.name})
|
||||
if 'method_number' in fields and asset.method_time == 'number':
|
||||
res.update({'method_number': asset.method_number})
|
||||
if 'method_period' in fields:
|
||||
res.update({'method_period': asset.method_period})
|
||||
if 'method_end' in fields and asset.method_time == 'end':
|
||||
res.update({'method_end': asset.method_end})
|
||||
if self.env.context.get('active_id'):
|
||||
active_asset = self.env['account.asset.asset'].browse(self.env.context.get('active_id'))
|
||||
res['asset_method_time'] = active_asset.method_time
|
||||
return res
|
||||
|
||||
def modify(self):
|
||||
""" Modifies the duration of asset for calculating depreciation
|
||||
and maintains the history of old values, in the chatter.
|
||||
"""
|
||||
asset_id = self.env.context.get('active_id', False)
|
||||
asset = self.env['account.asset.asset'].browse(asset_id)
|
||||
old_values = {
|
||||
'method_number': asset.method_number,
|
||||
'method_period': asset.method_period,
|
||||
'method_end': asset.method_end,
|
||||
}
|
||||
asset_vals = {
|
||||
'method_number': self.method_number,
|
||||
'method_period': self.method_period,
|
||||
'method_end': self.method_end,
|
||||
}
|
||||
asset.write(asset_vals)
|
||||
asset.compute_depreciation_board()
|
||||
tracked_fields = self.env['account.asset.asset'].fields_get(['method_number', 'method_period', 'method_end'])
|
||||
changes, tracking_value_ids = asset._mail_track(tracked_fields, old_values)
|
||||
if changes:
|
||||
asset.message_post(subject=_('Depreciation board modified'), body=self.name, tracking_value_ids=tracking_value_ids)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Asset Modify Form View-->
|
||||
<record model="ir.ui.view" id="asset_modify_view_form">
|
||||
<field name="name">asset.modify.view.form</field>
|
||||
<field name="model">asset.modify</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Modify Asset">
|
||||
<field name="asset_method_time" invisible="1"/>
|
||||
<group string="Asset Durations to Modify" col="4">
|
||||
<group colspan="2" col="2">
|
||||
<field name="name"/>
|
||||
<field name="method_number" invisible="asset_method_time in 'end'"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<field name="method_end" invisible="asset_method_time in 'number'"/>
|
||||
<label for="method_period"/>
|
||||
<div>
|
||||
<field name="method_period" class="oe_inline"/> months
|
||||
</div>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="modify" string="Modify" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-default" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Asset Modify-->
|
||||
<record id="action_asset_modify" model="ir.actions.act_window">
|
||||
<field name="name">Modify Asset</field>
|
||||
<field name="res_model">asset.modify</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="asset_modify_view_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,128 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountingReport(models.TransientModel):
|
||||
_name = "cash.flow.report"
|
||||
_inherit = "account.report"
|
||||
_description = "Cash Flow Report"
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_cash_flow_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_cash_flow_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="Cash Flow Report", default="Cash Flow Report", required=True, translate=True)
|
||||
date_from = fields.Date(string='Start Date')
|
||||
date_to = fields.Date(string='End Date')
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, default=lambda self: self.env.company)
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries'),
|
||||
], string='Target Moves', required=True, default='posted')
|
||||
journal_ids = fields.Many2many(
|
||||
comodel_name='account.journal',
|
||||
string='Journals',
|
||||
required=True,
|
||||
default=lambda self: self.env['account.journal'].search([('company_id', '=', self.company_id.id)]),
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _get_account_report(self):
|
||||
reports = []
|
||||
if self._context.get('active_id'):
|
||||
menu = self.env['ir.ui.menu'].browse(
|
||||
self._context.get('active_id')).name
|
||||
reports = self.env['account.financial.report'].search(
|
||||
[('name', 'ilike', menu)])
|
||||
return reports and reports[0] or False
|
||||
|
||||
enable_filter = fields.Boolean(string='Enable Comparison')
|
||||
account_report_id = fields.Many2one('account.financial.report',
|
||||
string='Account Reports',
|
||||
required=True,
|
||||
default=_get_account_report)
|
||||
label_filter = fields.Char(string='Column Label',
|
||||
help="This label will be displayed on report to show the balance"
|
||||
" computed for the given comparison filter.")
|
||||
filter_cmp = fields.Selection(
|
||||
[('filter_no', 'No Filters'), ('filter_date', 'Date')],
|
||||
string='Filter by', required=True, default='filter_no')
|
||||
date_from_cmp = fields.Date(string='Date Start')
|
||||
date_to_cmp = fields.Date(string='Date End')
|
||||
debit_credit = fields.Boolean(string='Display Debit/Credit Columns',
|
||||
help="This option allows you to get more details about the way your balances are computed. Because it is space consuming, we do not allow to use it while doing a comparison.")
|
||||
|
||||
def _build_comparison_context(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
if data['form']['filter_cmp'] == 'filter_date':
|
||||
result['date_from'] = data['form']['date_from_cmp']
|
||||
result['date_to'] = data['form']['date_to_cmp']
|
||||
result['strict_range'] = True
|
||||
return result
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form']['journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form']['target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
result['company_id'] = data['form']['company_id'][0] or False
|
||||
return result
|
||||
|
||||
# @api.multi
|
||||
def check_report(self):
|
||||
res = super(AccountingReport, self).check_report()
|
||||
data = {}
|
||||
data['form'] = self.read(
|
||||
['account_report_id', 'date_from_cmp', 'date_to_cmp',
|
||||
'journal_ids', 'filter_cmp', 'target_move'])[0]
|
||||
for field in ['account_report_id']:
|
||||
if isinstance(data['form'][field], tuple):
|
||||
data['form'][field] = data['form'][field][0]
|
||||
comparison_context = self._build_comparison_context(data)
|
||||
res['data']['form']['comparison_context'] = comparison_context
|
||||
return res
|
||||
|
||||
def _print_report(self, data):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _print_report(self, data):
|
||||
data['form'].update(self.read(
|
||||
['date_from_cmp', 'debit_credit', 'date_to_cmp', 'filter_cmp',
|
||||
'account_report_id', 'enable_filter', 'label_filter',
|
||||
'target_move'])[0])
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_cash_flow').report_action(self,
|
||||
data=data,
|
||||
config=False)
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Cash Flow Report Form View-->
|
||||
<record id="cash_flow_report_view" model="ir.ui.view">
|
||||
<field name="name">cash.flow.report.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">cash.flow.report</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="replace"/>
|
||||
<field name="target_move" position="before">
|
||||
<field name="account_report_id" domain="[('parent_id','=',False)]" readonly="1" invisible="1"/>
|
||||
<field name="enable_filter"/>
|
||||
</field>
|
||||
<field name="target_move" position="after">
|
||||
<field name="debit_credit"/>
|
||||
</field>
|
||||
<field name="journal_ids" position="after">
|
||||
<group>
|
||||
<field name="company_id" position="replace" invisible="1"/>
|
||||
</group>
|
||||
<notebook tabpos="up" colspan="4" invisible="not enable_filter">
|
||||
<page string="Comparison" name="comparison">
|
||||
<group>
|
||||
<field name="label_filter" required="enable_filter"/>
|
||||
<field name="filter_cmp"/>
|
||||
</group>
|
||||
<group string="Dates" invisible="filter_cmp != 'filter_date'">
|
||||
<field name="date_from_cmp" required="filter_cmp in 'filter_date'"/>
|
||||
<field name="date_to_cmp" required="filter_cmp in 'filter_date'"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
<field name="journal_ids" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Cash Flow Report-->
|
||||
<record id="action_cash_flow_report" model="ir.actions.act_window">
|
||||
<field name="name">Cash Flow Statement</field>
|
||||
<field name="res_model">cash.flow.report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="cash_flow_report_view"/>
|
||||
<field name="target">new</field>
|
||||
<field name="context"
|
||||
eval="{'default_account_report_id':ref('base_accounting_kit.account_financial_report_cash_flow0')}"/>
|
||||
</record>
|
||||
<!--Menu Cash Flow Statement-->
|
||||
<menuitem id="menu_account_cash_flow_report"
|
||||
name="Cash Flow Statement"
|
||||
sequence="5"
|
||||
action="action_cash_flow_report"
|
||||
parent="base_accounting_kit.account_reports_generic_statements"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,438 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
import re
|
||||
from odoo import api, models, fields
|
||||
|
||||
|
||||
class FinancialReport(models.TransientModel):
|
||||
_name = "financial.report"
|
||||
_inherit = "account.report"
|
||||
_description = "Financial Reports"
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_financial_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_financial_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
name = fields.Char(string="Financial Report", default="Financial Report", required=True, translate=True)
|
||||
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries'),
|
||||
], string='Target Moves', required=True, default='posted')
|
||||
|
||||
view_format = fields.Selection([
|
||||
('vertical', 'Vertical'),
|
||||
('horizontal', 'Horizontal')],
|
||||
default='vertical',
|
||||
string="Format")
|
||||
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form'][
|
||||
'journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form'][
|
||||
'target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def _get_account_report(self):
|
||||
reports = []
|
||||
if self._context.get('active_id'):
|
||||
menu = self.env['ir.ui.menu'].browse(
|
||||
self._context.get('active_id')).name
|
||||
reports = self.env['account.financial.report'].search([
|
||||
('name', 'ilike', menu)])
|
||||
return reports and reports[0] or False
|
||||
|
||||
enable_filter = fields.Boolean(
|
||||
string='Enable Comparison',
|
||||
default=False)
|
||||
account_report_id = fields.Many2one(
|
||||
'account.financial.report',
|
||||
string='Account Reports',
|
||||
required=True)
|
||||
|
||||
date_from = fields.Date(string='Start Date')
|
||||
date_to = fields.Date(string='End Date')
|
||||
debit_credit = fields.Boolean(
|
||||
string='Display Debit/Credit Columns',
|
||||
default=True,
|
||||
help="This option allows you to"
|
||||
" get more details about the "
|
||||
"way your balances are computed."
|
||||
" Because it is space consuming,"
|
||||
" we do not allow to use it "
|
||||
"while doing a comparison.")
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
index=True,
|
||||
default=lambda self: self.env.company.id)
|
||||
|
||||
def view_report_pdf(self):
|
||||
"""This function will be executed when we click the view button
|
||||
from the wizard. Based on the values provided in the wizard, this
|
||||
function will print pdf report"""
|
||||
self.ensure_one()
|
||||
data = dict()
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = self.read(
|
||||
['date_from', 'enable_filter', 'debit_credit', 'date_to',
|
||||
'account_report_id', 'target_move', 'view_format',
|
||||
'company_id'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(
|
||||
used_context,
|
||||
lang=self.env.context.get('lang') or 'en_US')
|
||||
|
||||
report_lines = self.get_account_lines(data['form'])
|
||||
# find the journal items of these accounts
|
||||
journal_items = self.find_journal_items(report_lines, data['form'])
|
||||
|
||||
def set_report_level(rec):
|
||||
"""This function is used to set the level of each item.
|
||||
This level will be used to set the alignment in the dynamic reports."""
|
||||
level = 1
|
||||
if not rec['parent']:
|
||||
return level
|
||||
else:
|
||||
for line in report_lines:
|
||||
key = 'a_id' if line['type'] == 'account' else 'id'
|
||||
if line[key] == rec['parent']:
|
||||
return level + set_report_level(line)
|
||||
|
||||
# finding the root
|
||||
for item in report_lines:
|
||||
item['balance'] = round(item['balance'], 2)
|
||||
if not item['parent']:
|
||||
item['level'] = 1
|
||||
parent = item
|
||||
report_name = item['name']
|
||||
id = item['id']
|
||||
report_id = item['r_id']
|
||||
else:
|
||||
item['level'] = set_report_level(item)
|
||||
currency = self._get_currency()
|
||||
data['currency'] = currency
|
||||
data['journal_items'] = journal_items
|
||||
data['report_lines'] = report_lines
|
||||
# checking view type
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.financial_report_pdf').report_action(self,
|
||||
data)
|
||||
|
||||
def _compute_account_balance(self, accounts):
|
||||
""" compute the balance, debit
|
||||
and credit for the provided accounts
|
||||
"""
|
||||
mapping = {
|
||||
'balance':
|
||||
"COALESCE(SUM(debit),0) - COALESCE(SUM(credit), 0)"
|
||||
" as balance",
|
||||
'debit': "COALESCE(SUM(debit), 0) as debit",
|
||||
'credit': "COALESCE(SUM(credit), 0) as credit",
|
||||
}
|
||||
|
||||
res = {}
|
||||
for account in accounts:
|
||||
res[account.id] = dict((fn, 0.0)
|
||||
for fn in mapping.keys())
|
||||
if accounts:
|
||||
tables, where_clause, where_params = (
|
||||
self.env['account.move.line']._query_get())
|
||||
tables = tables.replace(
|
||||
'"', '') if tables else "account_move_line"
|
||||
wheres = [""]
|
||||
if where_clause.strip():
|
||||
wheres.append(where_clause.strip())
|
||||
filters = " AND ".join(wheres)
|
||||
request = ("SELECT account_id as id, " +
|
||||
', '.join(mapping.values()) +
|
||||
" FROM " + tables +
|
||||
" WHERE account_id IN %s " +
|
||||
filters +
|
||||
" GROUP BY account_id")
|
||||
params = (tuple(accounts._ids),) + tuple(where_params)
|
||||
self.env.cr.execute(request, params)
|
||||
for row in self.env.cr.dictfetchall():
|
||||
res[row['id']] = row
|
||||
return res
|
||||
|
||||
def _compute_report_balance(self, reports):
|
||||
"""returns a dictionary with key=the ID of a record and
|
||||
value=the credit, debit and balance amount
|
||||
computed for this record. If the record is of type :
|
||||
'accounts' : it's the sum of the linked accounts
|
||||
'account_type' : it's the sum of leaf accounts with
|
||||
such an account_type
|
||||
'account_report' : it's the amount of the related report
|
||||
'sum' : it's the sum of the children of this record
|
||||
(aka a 'view' record)"""
|
||||
res = {}
|
||||
fields = ['credit', 'debit', 'balance']
|
||||
for report in reports:
|
||||
if report.id in res:
|
||||
continue
|
||||
res[report.id] = dict((fn, 0.0) for fn in fields)
|
||||
if report.type == 'accounts':
|
||||
# it's the sum of the linked accounts
|
||||
res[report.id]['account'] = self._compute_account_balance(
|
||||
report.account_ids
|
||||
)
|
||||
for value in \
|
||||
res[report.id]['account'].values():
|
||||
for field in fields:
|
||||
res[report.id][field] += value.get(field)
|
||||
elif report.type == 'account_type':
|
||||
# it's the sum the leaf accounts
|
||||
# with such an account type
|
||||
accounts = self.env['account.account'].search([
|
||||
('account_type', '=', report.account_type_ids)
|
||||
])
|
||||
if report.name == "Expenses":
|
||||
accounts = self.env['account.account'].search([
|
||||
('account_type', 'in', ["expense","expense_depreciation","expense_direct_cost"])
|
||||
])
|
||||
if report.name == "Liability":
|
||||
accounts = self.env['account.account'].search([
|
||||
('account_type', 'in', ["liability_payable","equity","liability_current","liability_non_current"])
|
||||
])
|
||||
if report.name == "Assets":
|
||||
accounts = self.env['account.account'].search([
|
||||
('account_type', 'in', ["asset_receivable","asset_cash","asset_current","asset_non_current","asset_prepayments","asset_fixed"])
|
||||
])
|
||||
|
||||
res[report.id]['account'] = self._compute_account_balance(
|
||||
accounts)
|
||||
|
||||
for value in res[report.id]['account'].values():
|
||||
for field in fields:
|
||||
res[report.id][field] += value.get(field)
|
||||
elif report.type == 'account_report' and report.account_report_id:
|
||||
# it's the amount of the linked report
|
||||
res2 = self._compute_report_balance(report.account_report_id)
|
||||
for key, value in res2.items():
|
||||
for field in fields:
|
||||
res[report.id][field] += value[field]
|
||||
elif report.type == 'sum':
|
||||
# it's the sum of the children of this account.report
|
||||
res2 = self._compute_report_balance(report.children_ids)
|
||||
for key, value in res2.items():
|
||||
for field in fields:
|
||||
res[report.id][field] += value[field]
|
||||
return res
|
||||
|
||||
def get_account_lines(self, data):
|
||||
lines = []
|
||||
account_report = self.env['account.financial.report'].search([
|
||||
('id', '=', data['account_report_id'][0])
|
||||
])
|
||||
child_reports = account_report._get_children_by_order()
|
||||
res = self.with_context(
|
||||
data.get('used_context'))._compute_report_balance(child_reports)
|
||||
if data['enable_filter']:
|
||||
comparison_res = self._compute_report_balance(child_reports)
|
||||
for report_id, value in comparison_res.items():
|
||||
res[report_id]['comp_bal'] = value['balance']
|
||||
report_acc = res[report_id].get('account')
|
||||
if report_acc:
|
||||
for account_id, val in \
|
||||
comparison_res[report_id].get('account').items():
|
||||
report_acc[account_id]['comp_bal'] = val['balance']
|
||||
|
||||
for report in child_reports:
|
||||
r_name = str(report.name)
|
||||
r_name = re.sub('[^0-9a-zA-Z]+', '', r_name)
|
||||
if report.parent_id:
|
||||
p_name = str(report.parent_id.name)
|
||||
p_name = re.sub('[^0-9a-zA-Z]+', '', p_name) + str(
|
||||
report.parent_id.id)
|
||||
else:
|
||||
p_name = False
|
||||
vals = {
|
||||
'r_id': report.id,
|
||||
'id': r_name + str(report.id),
|
||||
'sequence': report.sequence,
|
||||
'parent': p_name,
|
||||
'name': report.name,
|
||||
'balance': res[report.id]['balance'] * int(report.sign),
|
||||
'type': 'report',
|
||||
'level': bool(
|
||||
report.style_overwrite) and report.style_overwrite or
|
||||
report.level,
|
||||
'account_type': report.type or False,
|
||||
# used to underline the financial report balances
|
||||
}
|
||||
if data['debit_credit']:
|
||||
vals['debit'] = res[report.id]['debit']
|
||||
vals['credit'] = res[report.id]['credit']
|
||||
|
||||
if data['enable_filter']:
|
||||
vals['balance_cmp'] = res[report.id]['comp_bal'] * int(
|
||||
report.sign)
|
||||
|
||||
lines.append(vals)
|
||||
if report.display_detail == 'no_detail':
|
||||
# the rest of the loop is
|
||||
# used to display the details of the
|
||||
# financial report, so it's not needed here.
|
||||
continue
|
||||
|
||||
if res[report.id].get('account'):
|
||||
sub_lines = []
|
||||
for account_id, value \
|
||||
in res[report.id]['account'].items():
|
||||
# if there are accounts to display,
|
||||
# we add them to the lines with a level equals
|
||||
# to their level in
|
||||
# the COA + 1 (to avoid having them with a too low level
|
||||
# that would conflicts with the level of data
|
||||
# financial reports for Assets, liabilities...)
|
||||
flag = False
|
||||
account = self.env['account.account'].browse(account_id)
|
||||
# new_r_name = str(report.name)
|
||||
# new_r_name = new_r_name.replace(" ", "-") + "-"
|
||||
vals = {
|
||||
'account': account.id,
|
||||
'a_id': account.code + re.sub('[^0-9a-zA-Z]+', 'acnt',
|
||||
account.name) + str(
|
||||
account.id),
|
||||
'name': account.code + '-' + account.name,
|
||||
'balance': value['balance'] * int(report.sign) or 0.0,
|
||||
'type': 'account',
|
||||
'parent': r_name + str(report.id),
|
||||
'level': (
|
||||
report.display_detail == 'detail_with_hierarchy' and
|
||||
4),
|
||||
'account_type': account.account_type,
|
||||
}
|
||||
if data['debit_credit']:
|
||||
vals['debit'] = value['debit']
|
||||
vals['credit'] = value['credit']
|
||||
for company in account.company_ids:
|
||||
if not company.currency_id.is_zero(
|
||||
vals['debit']) or \
|
||||
not company.currency_id.is_zero(
|
||||
vals['credit']):
|
||||
flag = True
|
||||
for company in account.company_ids:
|
||||
if not company.currency_id.is_zero(
|
||||
vals['balance']):
|
||||
flag = True
|
||||
if data['enable_filter']:
|
||||
vals['balance_cmp'] = value['comp_bal'] * int(
|
||||
report.sign)
|
||||
for company in account.company_ids:
|
||||
if not company.currency_id.is_zero(
|
||||
vals['balance_cmp']):
|
||||
flag = True
|
||||
if flag:
|
||||
sub_lines.append(vals)
|
||||
lines += sorted(sub_lines,
|
||||
key=lambda sub_line: sub_line['name'])
|
||||
return lines
|
||||
|
||||
def find_journal_items(self, report_lines, form):
|
||||
cr = self.env.cr
|
||||
journal_items = []
|
||||
for i in report_lines:
|
||||
if i['type'] == 'account':
|
||||
account = i['account']
|
||||
if form['target_move'] == 'posted':
|
||||
search_query = ("select aml.id, am.id as j_id, "
|
||||
"aml.account_id, aml.date, aml.name as "
|
||||
"label, am.name, (aml.debit-aml.credit) as "
|
||||
"balance, aml.debit, aml.credit, "
|
||||
"aml.partner_id from "
|
||||
"account_move_line aml "
|
||||
"join account_move am on (aml.move_id=am.id"
|
||||
" and am.state=%s) where aml.account_id=%s")
|
||||
vals = [form['target_move']]
|
||||
else:
|
||||
search_query = ("select aml.id, am.id as j_id, "
|
||||
"aml.account_id, aml.date, aml.name as "
|
||||
"label, am.name, (aml.debit-aml.credit) as "
|
||||
"balance, aml.debit, aml.credit, "
|
||||
"aml.partner_id from account_move_line aml"
|
||||
" join account_move am on "
|
||||
"(aml.move_id=am.id) where "
|
||||
"aml.account_id=%s")
|
||||
vals = []
|
||||
if form['date_from'] and form['date_to']:
|
||||
search_query += " and aml.date>=%s and aml.date<=%s"
|
||||
vals += [account, form['date_from'], form['date_to']]
|
||||
elif form['date_from']:
|
||||
search_query += " and aml.date>=%s"
|
||||
vals += [account, form['date_from']]
|
||||
elif form['date_to']:
|
||||
search_query += " and aml.date<=%s"
|
||||
vals += [account, form['date_to']]
|
||||
else:
|
||||
vals += [account]
|
||||
cr.execute(search_query, tuple(vals))
|
||||
items = cr.dictfetchall()
|
||||
|
||||
for j in items:
|
||||
temp = j['id']
|
||||
j['id'] = re.sub('[^0-9a-zA-Z]+', '', i['name']) + str(
|
||||
temp)
|
||||
j['p_id'] = str(i['a_id'])
|
||||
j['type'] = 'journal_item'
|
||||
journal_items.append(j)
|
||||
return journal_items
|
||||
|
||||
@api.model
|
||||
def _get_currency(self):
|
||||
journal = self.env['account.journal'].browse(
|
||||
self.env.context.get('default_journal_id', False))
|
||||
if journal.currency_id:
|
||||
return journal.currency_id.id
|
||||
return self.env.company.currency_id.symbol
|
||||
|
||||
|
||||
class ProfitLossPdf(models.AbstractModel):
|
||||
""" Abstract model for generating PDF report value and send to template """
|
||||
|
||||
_name = 'report.base_accounting_kit.report_financial'
|
||||
_description = 'Financial Report'
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
""" Provide report values to template """
|
||||
ctx = {
|
||||
'data': data,
|
||||
'journal_items': data['journal_items'],
|
||||
'report_lines': data['report_lines'],
|
||||
'account_report': data['form']['account_report_id'][1],
|
||||
'currency': data['currency'],
|
||||
}
|
||||
return ctx
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<!-- Financial report common form view -->
|
||||
<record id="financial_report_view_form" model="ir.ui.view">
|
||||
<field name="name">financial.report.view.form</field>
|
||||
<field name="model">financial.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group>
|
||||
<group string="Dates">
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</group>
|
||||
<group string="Type">
|
||||
<field name="target_move" widget="radio"/>
|
||||
<field name="view_format" widget="radio" invisible="1"/>
|
||||
<field name="enable_filter" invisible="1"/>
|
||||
<field name="debit_credit"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Print" name="view_report_pdf" type="object"
|
||||
class="btn-primary"/>
|
||||
<button string="Discard" class="btn-secondary"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Action for profit and loss -->
|
||||
<record id="action_profit_and_loss_report" model="ir.actions.act_window">
|
||||
<field name="name">Profit and Loss</field>
|
||||
<field name="res_model">financial.report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="financial_report_view_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="context"
|
||||
eval="{'default_account_report_id':ref('base_accounting_kit.account_financial_report_profitandloss0')}"/>
|
||||
</record>
|
||||
<!-- Action for balance sheet -->
|
||||
<record id="action_balance_sheet_report" model="ir.actions.act_window">
|
||||
<field name="name">Balance Sheet</field>
|
||||
<field name="res_model">financial.report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="financial_report_view_form"/>
|
||||
<field name="target">new</field>
|
||||
<field name="context"
|
||||
eval="{'default_account_report_id':ref('base_accounting_kit.account_financial_report_balancesheet0')}"/>
|
||||
</record>
|
||||
<!--Menu Balance Sheet And Profit and Loss-->
|
||||
<menuitem id="account_financial_reports_profit_loss" sequence="1"
|
||||
name="Profit and Loss" parent="base_accounting_kit.account_reports_generic_statements"
|
||||
action="action_profit_and_loss_report"/>
|
||||
<menuitem id="_account_financial_reports_balance_sheet" sequence="2"
|
||||
name="Balance Sheet" parent="base_accounting_kit.account_reports_generic_statements"
|
||||
action="action_balance_sheet_report"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1,446 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Akhil Ashok (odoo@cybrosys.com)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###############################################################################
|
||||
import base64
|
||||
import codecs
|
||||
import csv
|
||||
import openpyxl
|
||||
import os
|
||||
import io
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from odoo import fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from ofxparse import OfxParser
|
||||
from qifparse.parser import QifParser
|
||||
|
||||
|
||||
class ImportBankStatement(models.TransientModel):
|
||||
""" A class to import files as bank statement """
|
||||
_name = "import.bank.statement"
|
||||
_description = "Import button"
|
||||
_rec_name = "file_name"
|
||||
|
||||
attachment = fields.Binary(string="File", required=True,
|
||||
help="Choose the file to import")
|
||||
file_name = fields.Char(string="File Name", help="Name of the file")
|
||||
journal_id = fields.Many2one('account.journal', string="Journal ID",
|
||||
help="Journal in which the file importing")
|
||||
|
||||
def _parse_date(self, date_str):
|
||||
""" Helper to parse date from string """
|
||||
if not date_str:
|
||||
return fields.Date.today()
|
||||
|
||||
if isinstance(date_str, datetime):
|
||||
return date_str.date()
|
||||
|
||||
# Remove potential quotes and whitespace
|
||||
date_str = str(date_str).strip().strip('"').strip("'")
|
||||
if not date_str:
|
||||
return fields.Date.today()
|
||||
|
||||
# Try common formats
|
||||
for fmt in ('%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%d-%m-%Y', '%Y/%m/%d'):
|
||||
try:
|
||||
return datetime.strptime(date_str, fmt).date()
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
|
||||
# Fallback to Odoo fields.Date.from_string
|
||||
try:
|
||||
res = fields.Date.from_string(date_str)
|
||||
if res:
|
||||
return res
|
||||
except:
|
||||
pass
|
||||
|
||||
return fields.Date.today()
|
||||
|
||||
def _parse_float(self, val):
|
||||
""" Helper to parse float from string with currency symbols and commas """
|
||||
if not val:
|
||||
return 0.0
|
||||
if isinstance(val, (int, float)):
|
||||
return float(val)
|
||||
|
||||
# Remove currency symbols, quotes, commas, spaces
|
||||
clean_val = str(val).strip().replace('"', '').replace("'", "").replace(',', '').replace(' ', '')
|
||||
for symbol in ('$', '€', '£', '¥', '₹'):
|
||||
clean_val = clean_val.replace(symbol, '')
|
||||
|
||||
# Handle accounting negative format (100.0) -> -100.0
|
||||
if clean_val.startswith('(') and clean_val.endswith(')'):
|
||||
clean_val = '-' + clean_val[1:-1]
|
||||
|
||||
try:
|
||||
return float(clean_val)
|
||||
except (ValueError, TypeError):
|
||||
return 0.0
|
||||
|
||||
def action_statement_import(self):
|
||||
"""Function to import csv, xlsx, ofx and qif file format"""
|
||||
split_tup = os.path.splitext(self.file_name)
|
||||
if split_tup[1] == '.csv' or split_tup[1] == '.xlsx' or split_tup[
|
||||
1] == '.ofx' or split_tup[1] == '.qif':
|
||||
if split_tup[1] == '.csv':
|
||||
try:
|
||||
file_data = base64.b64decode(self.attachment)
|
||||
file_string = file_data.decode('utf-8-sig')
|
||||
f = io.StringIO(file_string)
|
||||
reader = csv.DictReader(f)
|
||||
fieldnames = reader.fieldnames or []
|
||||
header_map = {f.strip().lower(): f for f in fieldnames}
|
||||
except Exception as e:
|
||||
raise ValidationError(_("Error reading CSV file: %s") % str(e))
|
||||
|
||||
statement_id = False
|
||||
for row in reader:
|
||||
if not any(row.values()):
|
||||
continue
|
||||
|
||||
def get_field(keys):
|
||||
for k in keys:
|
||||
if k.lower() in header_map:
|
||||
return row.get(header_map[k.lower()])
|
||||
return None
|
||||
|
||||
# Mappings for common Odoo and generic bank headers
|
||||
name = get_field(['name', 'label', 'description', 'reference', 'account', 'line_ids/payment_ref', 'payment_ref'])
|
||||
amount = get_field(['amount', 'value', 'price', 'total', 'line_ids/amount'])
|
||||
partner_name = get_field(['partner', 'partner_id/name', 'contact', 'payee', 'customer', 'supplier', 'line_ids/partner_id', 'partner_id'])
|
||||
date_str = get_field(['date', 'transaction date', 'time', 'line_ids/date'])
|
||||
starting_balance = get_field(['starting balance', 'start balance', 'opening balance', 'balance_start'])
|
||||
ending_balance = get_field(['ending balance', 'balance', 'real balance', 'end balance', 'balance_end_real'])
|
||||
|
||||
values = [v.strip() if v else '' for v in row.values()]
|
||||
keys = list(row.keys())
|
||||
mapped_indices = set()
|
||||
|
||||
def find_column(targets, is_numeric=False, is_date=False, exclude_indices=None):
|
||||
exclude_indices = exclude_indices or set()
|
||||
for k, v in header_map.items():
|
||||
if any(t in k for t in targets):
|
||||
idx = keys.index(v)
|
||||
if idx not in exclude_indices:
|
||||
return row.get(v), idx
|
||||
if is_numeric or is_date:
|
||||
for i, val in enumerate(values):
|
||||
if i in exclude_indices: continue
|
||||
if is_numeric:
|
||||
try:
|
||||
temp = val.replace('$', '').replace(',', '').strip()
|
||||
if temp:
|
||||
float(temp)
|
||||
return val, i
|
||||
except: pass
|
||||
if is_date:
|
||||
try:
|
||||
self._parse_date(val)
|
||||
return val, i
|
||||
except: pass
|
||||
return None, -1
|
||||
|
||||
# Heuristic backups for unmapped fields
|
||||
if amount is None:
|
||||
amount_val, idx = find_column(['amount', 'value', 'price', 'total'], is_numeric=True)
|
||||
if idx != -1:
|
||||
amount = amount_val
|
||||
mapped_indices.add(idx)
|
||||
|
||||
if date_str is None:
|
||||
date_val, idx = find_column(['date', 'time'], is_date=True, exclude_indices=mapped_indices)
|
||||
if idx != -1:
|
||||
date_str = date_val
|
||||
mapped_indices.add(idx)
|
||||
|
||||
if ending_balance is None:
|
||||
bal_val, idx = find_column(['balance', 'ending', 'real', 'end balance'], is_numeric=True, exclude_indices=mapped_indices)
|
||||
if idx != -1:
|
||||
ending_balance = bal_val
|
||||
mapped_indices.add(idx)
|
||||
|
||||
if starting_balance is None:
|
||||
# Attempt to find starting balance only if multiple numeric columns exist
|
||||
numeric_count = len([v for v in values if v.replace('$', '').replace(',', '').strip().replace('.', '').isdigit()])
|
||||
bal_val, idx = find_column(['starting', 'start balance', 'opening'], is_numeric=(numeric_count > 2), exclude_indices=mapped_indices)
|
||||
if idx != -1:
|
||||
starting_balance = bal_val
|
||||
mapped_indices.add(idx)
|
||||
|
||||
if name is None:
|
||||
for i, val in enumerate(values):
|
||||
if i in mapped_indices: continue
|
||||
try:
|
||||
float(val.replace('$', '').replace(',', '').strip())
|
||||
continue
|
||||
except:
|
||||
try:
|
||||
self._parse_date(val)
|
||||
continue
|
||||
except:
|
||||
name = val
|
||||
mapped_indices.add(i)
|
||||
break
|
||||
|
||||
if not name and values:
|
||||
name = values[0]
|
||||
|
||||
transaction_date = self._parse_date(date_str)
|
||||
clean_amount = self._parse_float(amount)
|
||||
clean_start_balance = self._parse_float(starting_balance)
|
||||
clean_end_balance = self._parse_float(ending_balance)
|
||||
|
||||
# Ensure statement is balanced (End = Start + Amount) to prevent red state
|
||||
if starting_balance is not None and ending_balance is not None:
|
||||
b_start, b_end = clean_start_balance, clean_end_balance
|
||||
clean_amount = b_end - b_start
|
||||
elif ending_balance is not None:
|
||||
b_end = clean_end_balance
|
||||
b_start = b_end - clean_amount
|
||||
elif starting_balance is not None:
|
||||
b_start = clean_start_balance
|
||||
b_end = b_start + clean_amount
|
||||
else:
|
||||
b_start, b_end = 0.0, clean_amount
|
||||
|
||||
partner = False
|
||||
if partner_name:
|
||||
partner_name = partner_name.strip()
|
||||
if partner_name.lower() in ('bank', 'cash', 'main', 'demo', 'yourcompany'):
|
||||
partner_name = False
|
||||
if partner_name:
|
||||
partner = self.env['res.partner'].search([('name', '=', partner_name)], limit=1)
|
||||
if not partner and len(partner_name) > 1 and not partner_name.isdigit():
|
||||
try:
|
||||
self._parse_date(partner_name)
|
||||
except:
|
||||
raise ValidationError(_("Partner '%s' does not exist") % partner_name)
|
||||
|
||||
statement = self.env['account.bank.statement'].create({
|
||||
'name': name,
|
||||
'journal_id': self.journal_id.id,
|
||||
'company_id': self.journal_id.company_id.id,
|
||||
'date': transaction_date,
|
||||
'balance_start': b_start,
|
||||
'balance_end_real': b_end,
|
||||
'line_ids': [(0, 0, {
|
||||
'date': transaction_date,
|
||||
'payment_ref': name or 'csv file',
|
||||
'partner_id': partner.id if partner else False,
|
||||
'journal_id': self.journal_id.id,
|
||||
'amount': clean_amount,
|
||||
})],
|
||||
})
|
||||
statement_id = statement.id
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Statements',
|
||||
'view_mode': 'list',
|
||||
'res_model': 'account.bank.statement',
|
||||
'res_id': statement.id,
|
||||
}
|
||||
elif split_tup[1] == '.xlsx':
|
||||
# Reading xlsx file
|
||||
try:
|
||||
order = openpyxl.load_workbook(
|
||||
filename=BytesIO(base64.b64decode(self.attachment)))
|
||||
xl_order = order.active
|
||||
except:
|
||||
raise ValidationError(_("Choose correct file"))
|
||||
for record in xl_order.iter_rows(min_row=2, max_row=None,
|
||||
min_col=None,
|
||||
max_col=None,
|
||||
values_only=True):
|
||||
line = list(record)
|
||||
# Reading the content from file
|
||||
if line[0] and line[1] and line[3]:
|
||||
partner = self.env['res.partner'].search(
|
||||
[('name', '=', line[3])])
|
||||
date_obj = self._parse_date(line[2])
|
||||
# Creating record
|
||||
if partner:
|
||||
statement = self.env[
|
||||
'account.bank.statement'].create({
|
||||
'name': line[0],
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': date_obj,
|
||||
'payment_ref': 'xlsx file',
|
||||
'partner_id': partner.id,
|
||||
'journal_id': self.journal_id.id,
|
||||
'amount': line[1],
|
||||
}),
|
||||
],
|
||||
})
|
||||
else:
|
||||
raise ValidationError(_("Partner not exist"))
|
||||
else:
|
||||
if not line[0]:
|
||||
raise ValidationError(
|
||||
_("Account name is not set"))
|
||||
elif not line[1]:
|
||||
raise ValidationError(
|
||||
_("Amount is not set"))
|
||||
elif not line[3]:
|
||||
date_obj = self._parse_date(line[2])
|
||||
# Creating record
|
||||
statement = self.env[
|
||||
'account.bank.statement'].create({
|
||||
'name': line[0],
|
||||
'line_ids': [
|
||||
(0, 0, {
|
||||
'date': date_obj,
|
||||
'payment_ref': 'xlsx file',
|
||||
'journal_id': self.journal_id.id,
|
||||
'amount': line[1],
|
||||
}),
|
||||
],
|
||||
})
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Statements',
|
||||
'view_mode': 'list',
|
||||
'res_model': 'account.bank.statement',
|
||||
'res_id': statement.id,
|
||||
}
|
||||
elif split_tup[1] == '.ofx':
|
||||
try:
|
||||
file_data = base64.b64decode(self.attachment)
|
||||
ofx_file = OfxParser.parse(io.BytesIO(file_data))
|
||||
except Exception as e:
|
||||
raise ValidationError(_("Wrong file format or parsing error: %s") % str(e))
|
||||
|
||||
if not ofx_file.account or not ofx_file.account.statement:
|
||||
raise ValidationError(_("No account information found in OFX file."))
|
||||
|
||||
statement_id = False
|
||||
stmt = ofx_file.account.statement
|
||||
|
||||
# Standardize balance extraction
|
||||
ledger_bal = getattr(stmt, 'balance', getattr(stmt, 'ledger_balance', None))
|
||||
final_balance = self._parse_float(ledger_bal) if ledger_bal is not None else 0.0
|
||||
|
||||
for transaction in stmt.transactions:
|
||||
amount = self._parse_float(transaction.amount)
|
||||
if amount == 0:
|
||||
continue
|
||||
|
||||
# Clean labels and match partners
|
||||
label = (transaction.memo or transaction.name or transaction.payee or 'ofx transaction').strip()
|
||||
payee_name = transaction.payee.strip() if transaction.payee else False
|
||||
|
||||
partner = False
|
||||
if payee_name:
|
||||
# Shared noise-filtering for partners
|
||||
if payee_name.lower() in ('bank', 'cash', 'main', 'demo', 'yourcompany'):
|
||||
payee_name = False
|
||||
if payee_name:
|
||||
partner = self.env['res.partner'].search([('name', '=', payee_name)], limit=1)
|
||||
|
||||
date = self._parse_date(transaction.date)
|
||||
b_end = final_balance
|
||||
b_start = b_end - amount
|
||||
|
||||
statement = self.env['account.bank.statement'].create({
|
||||
'name': label,
|
||||
'journal_id': self.journal_id.id,
|
||||
'company_id': self.journal_id.company_id.id,
|
||||
'date': date,
|
||||
'balance_start': b_start,
|
||||
'balance_end_real': b_end,
|
||||
'line_ids': [(0, 0, {
|
||||
'date': date,
|
||||
'payment_ref': label,
|
||||
'partner_id': partner.id if partner else False,
|
||||
'journal_id': self.journal_id.id,
|
||||
'amount': amount,
|
||||
})],
|
||||
})
|
||||
statement_id = statement.id
|
||||
|
||||
if not statement_id:
|
||||
raise ValidationError(_("No valid transactions found in the OFX file."))
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Statements',
|
||||
'view_mode': 'list',
|
||||
'res_model': 'account.bank.statement',
|
||||
'res_id': statement_id,
|
||||
}
|
||||
|
||||
elif split_tup[1] == '.qif':
|
||||
try:
|
||||
file_data = base64.b64decode(self.attachment)
|
||||
file_string = file_data.decode('utf-8-sig')
|
||||
qif = QifParser().parse(io.StringIO(file_string))
|
||||
except Exception as e:
|
||||
raise ValidationError(_("Error parsing QIF file: %s") % str(e))
|
||||
|
||||
statement_id = False
|
||||
for account in qif.get_accounts():
|
||||
for transaction in qif.get_transactions(account):
|
||||
amount = self._parse_float(transaction.amount)
|
||||
if amount == 0:
|
||||
continue
|
||||
|
||||
date = self._parse_date(transaction.date)
|
||||
label = (transaction.payee or transaction.memo or 'qif transaction').strip()
|
||||
payee_name = transaction.payee.strip() if transaction.payee else False
|
||||
|
||||
partner = False
|
||||
if payee_name:
|
||||
if payee_name.lower() in ('bank', 'cash', 'main', 'demo', 'yourcompany'):
|
||||
payee_name = False
|
||||
if payee_name:
|
||||
partner = self.env['res.partner'].search([('name', '=', payee_name)], limit=1)
|
||||
|
||||
statement = self.env['account.bank.statement'].create({
|
||||
'name': label,
|
||||
'journal_id': self.journal_id.id,
|
||||
'company_id': self.journal_id.company_id.id,
|
||||
'date': date,
|
||||
'balance_start': 0.0,
|
||||
'balance_end_real': amount,
|
||||
'line_ids': [(0, 0, {
|
||||
'date': date,
|
||||
'payment_ref': label,
|
||||
'partner_id': partner.id if partner else False,
|
||||
'journal_id': self.journal_id.id,
|
||||
'amount': amount,
|
||||
})],
|
||||
})
|
||||
statement_id = statement.id
|
||||
|
||||
if not statement_id:
|
||||
raise ValidationError(_("No valid transactions found in the QIF file."))
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Statements',
|
||||
'view_mode': 'list',
|
||||
'res_model': 'account.bank.statement',
|
||||
'res_id': statement_id,
|
||||
}
|
||||
else:
|
||||
raise ValidationError(_("Choose correct file"))
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<!-- Wizard view to upload files -->
|
||||
<record id="import_bank_statement_view_form" model="ir.ui.view">
|
||||
<field name="name">import.bank.statement.view.form</field>
|
||||
<field name="model">import.bank.statement</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<p>
|
||||
<center>
|
||||
<i>Upload csv or xlsx or ofx or qif file format</i>
|
||||
</center>
|
||||
</p>
|
||||
<group>
|
||||
<group>
|
||||
<field name="attachment" filename="file_name"/>
|
||||
<field name="file_name" invisible="1"/>
|
||||
<field name="journal_id" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_statement_import" class="oe_highlight"
|
||||
string="IMPORT" type="object"
|
||||
help="Import bank statement in CSV or XLSX format"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Wizard action record -->
|
||||
<record id="import_bank_statement_view_action"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">import.bank.statement.view.action</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">import.bank.statement</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_id" ref="base_accounting_kit.import_bank_statement_view_form"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#############################################################################
|
||||
#
|
||||
# Cybrosys Technologies Pvt. Ltd.
|
||||
#
|
||||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
||||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
|
||||
#
|
||||
# You can modify it under the terms of the GNU LESSER
|
||||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
# (LGPL v3) along with this program.
|
||||
# If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#############################################################################
|
||||
from odoo import fields, models
|
||||
from odoo.tools.misc import get_lang
|
||||
|
||||
|
||||
class AccountTaxReport(models.TransientModel):
|
||||
_name = 'kit.account.tax.report'
|
||||
_inherit = "account.report"
|
||||
_description = 'Tax Report'
|
||||
|
||||
section_main_report_ids = fields.Many2many(string="Section Of",
|
||||
comodel_name='account.report',
|
||||
relation="account_tax_report_section_rel",
|
||||
column1="sub_report_id",
|
||||
column2="main_report_id")
|
||||
section_report_ids = fields.Many2many(string="Sections",
|
||||
comodel_name='account.report',
|
||||
relation="account_tax_report_section_rel",
|
||||
column1="main_report_id",
|
||||
column2="sub_report_id")
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, default=lambda self: self.env.company)
|
||||
name = fields.Char(string="Tax Report", default="Tax Report",
|
||||
required=True, translate=True)
|
||||
date_from = fields.Date(string='Start Date')
|
||||
date_to = fields.Date(string='End Date')
|
||||
journal_ids = fields.Many2many(
|
||||
comodel_name='account.journal',
|
||||
string='Journals',
|
||||
required=True,
|
||||
default=lambda self: self.env['account.journal'].search([('company_id', '=', self.company_id.id)]),
|
||||
domain="[('company_id', '=', company_id)]",
|
||||
)
|
||||
target_move = fields.Selection([('posted', 'All Posted Entries'),
|
||||
('all', 'All Entries'),
|
||||
], string='Target Moves', required=True, default='posted')
|
||||
|
||||
def _build_contexts(self, data):
|
||||
result = {}
|
||||
result['journal_ids'] = 'journal_ids' in data['form'] and data['form']['journal_ids'] or False
|
||||
result['state'] = 'target_move' in data['form'] and data['form']['target_move'] or ''
|
||||
result['date_from'] = data['form']['date_from'] or False
|
||||
result['date_to'] = data['form']['date_to'] or False
|
||||
result['strict_range'] = True if result['date_from'] else False
|
||||
result['company_id'] = data['form']['company_id'][0] or False
|
||||
return result
|
||||
|
||||
def check_report(self):
|
||||
self.ensure_one()
|
||||
data = {}
|
||||
data['ids'] = self.env.context.get('active_ids', [])
|
||||
data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
|
||||
data['form'] = self.read(['date_from', 'date_to', 'journal_ids', 'target_move', 'company_id'])[0]
|
||||
used_context = self._build_contexts(data)
|
||||
data['form']['used_context'] = dict(used_context, lang=get_lang(self.env).code)
|
||||
return self.with_context(discard_logo_check=True)._print_report(data)
|
||||
|
||||
def pre_print_report(self, data):
|
||||
data['form'].update(self.read(['display_account'])[0])
|
||||
return data
|
||||
|
||||
def _print_report(self, data):
|
||||
return self.env.ref(
|
||||
'base_accounting_kit.action_report_account_tax').report_action(
|
||||
self, data=data)
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<!--Kit Account Tax Report Form View-->
|
||||
<record id="accounting_tax_report_view" model="ir.ui.view">
|
||||
<field name="name">kit.account.tax.report.view.form.inherit.base.accounting.kit</field>
|
||||
<field name="model">kit.account.tax.report</field>
|
||||
<field name="inherit_id" ref="base_accounting_kit.account_report_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="journal_ids" position="replace"/>
|
||||
<field name="target_move" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
<!--Action Kit Account Tax Report-->
|
||||
<record id="action_account_tax_report" model="ir.actions.act_window">
|
||||
<field name="name">Tax Reports</field>
|
||||
<field name="res_model">kit.account.tax.report</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="accounting_tax_report_view"/>
|
||||
<field name="context">{}</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
<!--Menu Tax Report-->
|
||||
<menuitem id="menu_tax_report"
|
||||
name="Tax Report"
|
||||
sequence="8"
|
||||
action="action_account_tax_report"
|
||||
parent="base_accounting_kit.account_reports_audit"
|
||||
groups="base_accounting_kit.group_account_chief,account.group_account_user"/>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user