summaryrefslogtreecommitdiff
path: root/account_reports_xlsx/wizard
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 17:14:58 +0700
commit1ca3b3df3421961caec3b747a364071c80f5c7da (patch)
tree6778a1f0f3f9b4c6e26d6d87ccde16e24da6c9d6 /account_reports_xlsx/wizard
parentb57188be371d36d96caac4b8d65a40745c0e972c (diff)
initial commit
Diffstat (limited to 'account_reports_xlsx/wizard')
-rw-r--r--account_reports_xlsx/wizard/__init__.py27
-rw-r--r--account_reports_xlsx/wizard/account_financial_report.py245
-rw-r--r--account_reports_xlsx/wizard/account_financial_report_view.xml63
-rw-r--r--account_reports_xlsx/wizard/account_report_aged_partner_balance.py209
-rw-r--r--account_reports_xlsx/wizard/account_report_aged_partner_balance_view.xml42
-rw-r--r--account_reports_xlsx/wizard/account_report_financial.py181
-rw-r--r--account_reports_xlsx/wizard/account_report_general_ledger.py240
-rw-r--r--account_reports_xlsx/wizard/account_report_general_ledger_view.xml39
-rw-r--r--account_reports_xlsx/wizard/account_report_partner_ledger.py265
-rw-r--r--account_reports_xlsx/wizard/partner_ledger_wizard_view.xml63
10 files changed, 1374 insertions, 0 deletions
diff --git a/account_reports_xlsx/wizard/__init__.py b/account_reports_xlsx/wizard/__init__.py
new file mode 100644
index 0000000..c94f568
--- /dev/null
+++ b/account_reports_xlsx/wizard/__init__.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2020-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies(odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+from . import account_report_partner_ledger
+from . import account_report_aged_partner_balance
+from . import account_report_general_ledger
+from . import account_financial_report
+from . import account_report_financial
diff --git a/account_reports_xlsx/wizard/account_financial_report.py b/account_reports_xlsx/wizard/account_financial_report.py
new file mode 100644
index 0000000..7ee7826
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_financial_report.py
@@ -0,0 +1,245 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies(odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+from datetime import datetime
+import json
+import datetime
+import io
+from odoo import api, fields, models, _
+from odoo.tools import date_utils
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AccountingReport(models.TransientModel):
+ _name = "accounting.report.xlsx"
+ _description = "Accounting Report"
+
+ @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=_('Start Date'))
+ date_to_cmp = fields.Date(string=_('End Date'))
+ 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 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):
+ 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('account.action_report_financial').report_action(self, data=data, config=False)
+
+ company_id = fields.Many2one('res.company', string=_('Company'), readonly=True,
+ default=lambda self: self.env.user.company_id)
+ journal_ids = fields.Many2many('account.journal', string=_('Journals'), required=True,
+ default=lambda self: self.env['account.journal'].search([]))
+ 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')
+
+ 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 _print_report(self, data):
+ # raise NotImplementedError()
+
+ 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'])[0]
+ used_context = self._build_contexts(data)
+ data['form']['used_context'] = dict(used_context, lang=self.env.context.get('lang') or 'en_US')
+ return {
+ 'type': 'ir.actions.report',
+ 'data': {'model': 'accounting.report.xlsx',
+ 'options': json.dumps(data, default=date_utils.json_default),
+ 'output_format': 'xlsx',
+ 'report_name': self.account_report_id.name,
+ },
+ 'report_type': 'xlsx'
+ }
+
+ def get_xlsx_report(self, options, response):
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ data = {}
+ obj = self.search([('id', '=', options['form']['id'])])
+ data['form'] = obj.read([])[0]
+ comp_dic = {}
+ env_obj = obj.env['report.account.report_financial']
+ data['form']['used_context'] = {}
+ data['form']['used_context']['date_to'] = data['form']['date_to']
+ data['form']['used_context']['date_from'] = data['form']['date_from']
+ data['form']['used_context']['journal_ids'] = data['form']['journal_ids']
+ data['form']['used_context']['state'] = 'posted'
+ data['form']['used_context']['strict_range'] = True
+ comp_dic['state'] = 'posted'
+ comp_dic['journal_ids'] = data['form']['journal_ids']
+ data['form']['comparison_context'] = comp_dic
+ data['account_report_id'] = data['form']['account_report_id']
+ accounting_data = env_obj.get_account_lines(data.get('form'))
+ sheet = workbook.add_worksheet()
+ format1 = workbook.add_format({'font_size': 16, 'align': 'center', 'bg_color': '#D3D3D3', 'bold': True})
+ format1.set_font_color('#000080')
+ format1.set_font_name('Times New Roman')
+ format2 = workbook.add_format({'font_size': 12, 'bold': True, 'bg_color': '#D3D3D3'})
+ format3 = workbook.add_format({'font_size': 10, 'bold': True})
+ format4 = workbook.add_format({'font_size': 10})
+ format6 = workbook.add_format({'font_size': 10, 'bold': True})
+ format7 = workbook.add_format({'font_size': 10})
+ format8 = workbook.add_format({'font_size': 12, 'bold': True, 'bg_color': '#D3D3D3'})
+ format1.set_align('center')
+ format2.set_align('center')
+ format3.set_align('center')
+ format4.set_align('center')
+ format8.set_align('left')
+ sheet.set_column('E:E', 10, format4)
+ sheet.set_column('H:H', 10, format4)
+ sheet.set_column('I:I', 10, format4)
+ sheet.set_column('J:J', 10, format4)
+ currency = self.env.user.company_id.currency_id.symbol
+ format7.set_num_format('0.00 ' + currency)
+ format6.set_num_format('0.00 ' + currency)
+ report_date = datetime.datetime.now().strftime("%Y-%m-%d")
+ sheet.merge_range('A1:B1', _("Report Date"), format6)
+ sheet.merge_range('C1:D1', report_date, format7)
+ if obj.account_report_id.name:
+ sheet.merge_range(3, 0, 4, 9, obj.account_report_id.name, format1)
+ if obj.target_move == 'all':
+ target_moves = 'All entries'
+ else:
+ target_moves = 'All posted entries'
+ sheet.merge_range('A7:B7', _("Target Moves:"), format6)
+ sheet.write('C7', target_moves, format7)
+ if obj.date_from:
+ sheet.write('E7', _("Date From:"), format6)
+ sheet.write('F7', str(obj.date_from), format7)
+ if obj.date_to:
+ sheet.write('H7', _("Date to:"), format6)
+ sheet.write('I7', str(obj.date_to), format7)
+ row_number = 9
+ col_number = 0
+ if obj.debit_credit == 1:
+ sheet.merge_range('A9:G9', _("Name"), format8)
+ sheet.write('H9', _("Debit"), format2)
+ sheet.write('I9', _("Credit"), format2)
+ sheet.write('J9', _("Balance"), format2)
+ for values in accounting_data:
+ if not self.env.user.company_id.parent_id:
+ if values['level'] != 0:
+ pass
+ else:
+ if values['level'] != 0:
+ if values['level'] == 1:
+ sheet.write(row_number, col_number, values['name'], format6)
+ sheet.write(row_number, col_number + 7, values['debit'], format6)
+ sheet.write(row_number, col_number + 8, values['credit'], format6)
+ sheet.write(row_number, col_number + 9, values['balance'], format6)
+ row_number += 1
+ elif not values['account_type'] == 'sum':
+ sheet.write(row_number, col_number, values['name'], format7)
+ sheet.write(row_number, col_number + 7, values['debit'], format7)
+ sheet.write(row_number, col_number + 8, values['credit'], format7)
+ sheet.write(row_number, col_number + 9, values['balance'], format7)
+ row_number += 1
+
+ if not obj.enable_filter and not obj.debit_credit:
+ sheet.merge_range('A9:I9', _("Name"), format8)
+ sheet.write('J9', _("Balance"), format2)
+ for values in accounting_data:
+ if values['level'] != 0:
+ if values['level'] == 1:
+ # assets and liabilities
+ sheet.write(row_number, col_number, values['name'], format6)
+ sheet.write(row_number, col_number + 9, values['balance'], format6)
+ row_number += 1
+ elif not values['account_type'] == 'sum':
+ sheet.write(row_number, col_number + 1, values['name'], format7)
+ # sheet.write(row_number, col_number, values['name'], format7)
+ sheet.write(row_number, col_number + 9, values['balance'], format7)
+ row_number += 1
+ if obj.enable_filter and not obj.debit_credit:
+ sheet.merge_range('A9:H9', _("Name"), format8)
+ sheet.write('I9', _("Balance"), format2)
+ sheet.write('J9', data['form']['label_filter'], format2)
+ for values in accounting_data:
+ if values['level'] != 0:
+ if values['level'] == 1:
+ sheet.write(row_number, col_number, values['name'], format6)
+ sheet.write(row_number, col_number + 8, values['balance'], format6)
+ sheet.write(row_number, col_number + 9, values['balance_cmp'], format6)
+ row_number += 1
+ elif not values['account_type'] == 'sum':
+ sheet.write(row_number, col_number, values['name'], format7)
+ sheet.write(row_number, col_number + 8, values['balance'], format7)
+ sheet.write(row_number, col_number + 9, values['balance_cmp'], format7)
+ row_number += 1
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/account_reports_xlsx/wizard/account_financial_report_view.xml b/account_reports_xlsx/wizard/account_financial_report_view.xml
new file mode 100644
index 0000000..6bdf685
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_financial_report_view.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <record id="accounting_report_view" model="ir.ui.view">
+ <field name="name">Accounting Report</field>
+ <field name="model">accounting.report.xlsx</field>
+ <field name="inherit_id" ref="account.account_common_report_view"/>
+ <field name="arch" type="xml">
+ <field name="target_move" position="before">
+ <field name="account_report_id" domain="[('parent_id','=',False)]"/>
+ </field>
+ <field name="target_move" position="after">
+ <field name="enable_filter"/>
+ <field name="debit_credit" attrs="{'invisible': [('enable_filter','=',True)]}"/>
+ </field>
+ <field name="journal_ids" position="after">
+ <notebook tabpos="up" colspan="4">
+ <page string="Comparison" name="comparison" attrs="{'invisible': [('enable_filter','=',False)]}">
+ <group>
+ <field name="label_filter" attrs="{'required': [('enable_filter', '=', True)]}"/>
+ <field name="filter_cmp"/>
+ </group>
+ <group string="Dates" attrs="{'invisible':[('filter_cmp', '!=', 'filter_date')]}">
+ <field name="date_from_cmp" attrs="{'required':[('filter_cmp', '=', 'filter_date')]}"/>
+ <field name="date_to_cmp" attrs="{'required':[('filter_cmp', '=', 'filter_date')]}"/>
+ </group>
+ </page>
+ </notebook>
+ </field>
+ <field name="journal_ids" position="replace"/>
+ </field>
+ </record>
+
+ <record id="action_account_report_bs" model="ir.actions.act_window">
+ <field name="name">Balance Sheet</field>
+ <field name="res_model">accounting.report.xlsx</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="accounting_report_view"/>
+ <field name="target">new</field>
+ </record>
+
+ <record id="action_account_report_pl" model="ir.actions.act_window">
+ <field name="name">Profit and Loss</field>
+ <field name="res_model">accounting.report.xlsx</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="accounting_report_view"/>
+ <field name="target">new</field>
+ </record>
+
+ <record id="action_account_report" model="ir.actions.act_window">
+ <field name="name">Financial Reports</field>
+ <field name="res_model">accounting.report.xlsx</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="accounting_report_view"/>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem id="menu_account_report" name="Financial Report" action="action_account_report" parent="account.account_reports_management_menu" sequence="2" groups="account.group_account_user"/>
+
+</odoo>
diff --git a/account_reports_xlsx/wizard/account_report_aged_partner_balance.py b/account_reports_xlsx/wizard/account_report_aged_partner_balance.py
new file mode 100644
index 0000000..4f41c44
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_aged_partner_balance.py
@@ -0,0 +1,209 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2020-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies (odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+import time
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from odoo.exceptions import UserError
+import json
+import datetime
+import io
+from odoo import api, fields, models, _
+from odoo.tools import date_utils
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AccountAgedTrialBalance(models.TransientModel):
+
+ _name = 'account.aged.trial.balance.xlsx'
+ _description = 'Account Aged Trial balance Report'
+
+ period_length = fields.Integer(string=_('Period Length (days)'), required=True, default=30)
+ journal_ids = fields.Many2many('account.journal', string=_('Journals'), required=True)
+ 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 = datetime.strptime(str(data['form']['date_from']), "%Y-%m-%d")
+
+ 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('account.action_report_aged_partner_balance').with_context(landscape=True).report_action(self, data=data)
+
+ def pre_print_report(self, data):
+ data['form'].update(self.read(['result_selection'])[0])
+ return data
+
+ result_selection = fields.Selection([('customer', _('Receivable Accounts')),
+ ('supplier', _('Payable Accounts')),
+ ('customer_supplier', _('Receivable and Payable Accounts'))
+ ], string=_("Partner's"), required=True, default='customer')
+
+ company_id = fields.Many2one('res.company', string=_('Company'), readonly=True,
+ default=lambda self: self.env.user.company_id)
+ journal_ids = fields.Many2many('account.journal', string=_('Journals'), required=True,
+ default=lambda self: self.env['account.journal'].search([]))
+ 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')
+
+ 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 _print_report(self, data):
+ # raise NotImplementedError()
+
+ 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'])[0]
+ used_context = self._build_contexts(data)
+ data['form']['used_context'] = dict(used_context, lang=self.env.context.get('lang') or 'en_US')
+ return {
+ 'type': 'ir.actions.report',
+ 'data': {'model': 'account.aged.trial.balance.xlsx',
+ 'options': json.dumps(data, default=date_utils.json_default),
+ 'output_format': 'xlsx',
+ 'report_name': 'aged partner report',
+ },
+ 'report_type': 'xlsx'
+ }
+
+ def get_xlsx_report(self, options, response):
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ env_obj = self.search([('id','=',options['form']['id'])]).env['report.account_reports_xlsx.report_agedpartnerbalance']
+ vals = self.search([('id','=',options['form']['id'])])
+ result_selection = vals.result_selection
+ if result_selection == 'customer':
+ account_type = ['receivable']
+ account_type_name = _("Receivable Accounts")
+ elif result_selection == 'supplier':
+ account_type = ['payable']
+ account_type_name = _("Payable Accounts")
+ else:
+ account_type = ['payable', 'receivable']
+ account_type_name = _("Receivable and Payable Accounts")
+ # sales_person_wise = vals.user_wise_report
+ date_from = options['form']['date_from']
+ target_move = options['form']['target_move']
+ if target_move == 'all':
+ target_move_name = _("All Entries")
+ else:
+ target_move_name = _("All Posted Entries")
+ period_length = vals.period_length
+ # # user_ids = vals.user_ids.ids
+ move_lines, total, dummy = env_obj._get_partner_move_lines(account_type, date_from, target_move, period_length)
+ sheet = workbook.add_worksheet()
+ format1 = workbook.add_format({'font_size': 16, 'align': 'center', 'bg_color': '#D3D3D3', 'bold': True})
+ format1.set_font_color('#000080')
+ format2 = workbook.add_format({'font_size': 10, 'bold': True})
+ format3 = workbook.add_format({'font_size': 10})
+ logged_users = self.env['res.company']._company_default_get('account.account')
+ sheet.write('A1', logged_users.name, format3)
+ sheet.write('A3', _('Start Date:'), format2)
+ sheet.write('B3', date_from, format3)
+ sheet.merge_range('E3:G3', _('Period Length (days):'), format2)
+ sheet.write('H3', period_length, format3)
+ sheet.write('A4', _("Partner's:"), format2)
+ sheet.merge_range('B4:C4', account_type_name, format3)
+ sheet.merge_range('E4:F4', _('Target Moves:'), format2)
+ sheet.merge_range('G4:H4', target_move_name, format3)
+ sheet.set_column(0, 0, 20)
+ # # if sales_person_wise:
+ # # sheet.set_column(1, 1, 20)
+ # # sheet.merge_range(5, 0, 7, 8, "Aged Partner Balance", format1)
+ # # else:
+ sheet.merge_range(5, 0, 7, 7, _("Aged Partner Balance"), format1)
+ row_value = 8
+ column_value = 0
+ # # if sales_person_wise:
+ # # sheet.write(row_value, column_value, "Sales Person", format2)
+ # # column_value += 1
+ sheet.write(row_value, column_value, _("Partners"), format2)
+ sheet.write(row_value, column_value + 1, _("Not due"), format2)
+ sheet.write(row_value, column_value + 2, "0-" + str(period_length), format2)
+ sheet.write(row_value, column_value + 3, str(period_length) + "-" + str(2 * period_length), format2)
+ sheet.write(row_value, column_value + 4, str(2 * period_length) + "-" + str(3 * period_length), format2)
+ sheet.write(row_value, column_value + 5, str(3 * period_length) + "-" + str(4 * period_length), format2)
+ sheet.write(row_value, column_value + 6, "+" + str(4 * period_length), format2)
+ sheet.write(row_value, column_value + 7, _("Total"), format2)
+ row_value += 1
+ column_value = 0
+ if move_lines:
+ sheet.write(row_value, column_value, _("Account Total"), format2)
+ sheet.write(row_value, column_value + 1, total[6], format2)
+ sheet.write(row_value, column_value + 2, total[4], format2)
+ sheet.write(row_value, column_value + 3, total[3], format2)
+ sheet.write(row_value, column_value + 4, total[2], format2)
+ sheet.write(row_value, column_value + 5, total[1], format2)
+ sheet.write(row_value, column_value + 6, total[0], format2)
+ sheet.write(row_value, column_value + 7, total[5], format2)
+ row_value += 1
+ for i in move_lines:
+ partner_ref = self.env['res.partner'].browse(i['partner_id']).ref
+ if partner_ref:
+ partner_ref = "[" + str(partner_ref) + "] "
+ partner_name = partner_ref + str(i['name'])
+ else:
+ partner_name = str(i['name'])
+ sheet.write(row_value, column_value, partner_name, format3)
+ sheet.write(row_value, column_value + 1, i['direction'], format3)
+ sheet.write(row_value, column_value + 2, i['4'], format3)
+ sheet.write(row_value, column_value + 3, i['3'], format3)
+ sheet.write(row_value, column_value + 4, i['2'], format3)
+ sheet.write(row_value, column_value + 5, i['1'], format3)
+ sheet.write(row_value, column_value + 6, i['0'], format3)
+ sheet.write(row_value, column_value + 7, i['total'], format3)
+ row_value += 1
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/account_reports_xlsx/wizard/account_report_aged_partner_balance_view.xml b/account_reports_xlsx/wizard/account_report_aged_partner_balance_view.xml
new file mode 100644
index 0000000..69d2298
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_aged_partner_balance_view.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <record id="account_aged_balance_view" model="ir.ui.view">
+ <field name="name">Aged Partner Balance</field>
+ <field name="model">account.aged.trial.balance.xlsx</field>
+ <field name="arch" type="xml">
+ <form string="Report Options">
+ <separator string="Aged Partner Balance"/>
+ <span> Aged Partner Balance is a more detailed report of your receivables by intervals. Odoo calculates a table of credit balance by start Date. So if you request an interval of 30 days Odoo generates an analysis of creditors for the past month, past two months, and so on. </span>
+ <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>
+ <field name="journal_ids" required="0" invisible="1"/>
+ <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>
+
+ <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.xlsx</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="view_mode">tree,form</field>
+ <field name="view_id" ref="account_aged_balance_view"/>
+ <field name="context">{}</field>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem id="menu_aged_trial_balance"
+ name="Aged Partner Balance"
+ action="action_account_aged_balance_view"
+ parent="account.account_reports_management_menu"/>
+
+</odoo>
diff --git a/account_reports_xlsx/wizard/account_report_financial.py b/account_reports_xlsx/wizard/account_report_financial.py
new file mode 100644
index 0000000..d42c4e6
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_financial.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2020-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies (odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+import time
+from odoo import api, models, _
+from odoo.exceptions import UserError
+
+
+class ReportFinancial(models.AbstractModel):
+ _name = 'report.account.report_financial'
+
+ 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.fromkeys(mapping, 0.0)
+ 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 accoutns 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([('user_type_id', 'in', report.account_type_ids.ids)])
+ 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.with_context(data.get('comparison_context'))._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:
+ vals = {
+ 'name': report.name,
+ 'balance': res[report.id]['balance'] * int(report.sign),
+ 'type': 'report',
+ 'level': bool(report.style_overwrite) and 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)
+ vals = {
+ 'name': account.code + ' ' + account.name,
+ 'balance': value['balance'] * int(report.sign) or 0.0,
+ 'type': 'account',
+ 'level': report.display_detail == 'detail_with_hierarchy' and 4,
+ 'account_type': account.internal_type,
+ }
+ if data['debit_credit']:
+ vals['debit'] = value['debit']
+ vals['credit'] = value['credit']
+ if not account.company_id.currency_id.is_zero(vals['debit']) or not account.company_id.currency_id.is_zero(vals['credit']):
+ flag = True
+ if not account.company_id.currency_id.is_zero(vals['balance']):
+ flag = True
+ if data['enable_filter']:
+ vals['balance_cmp'] = value['comp_bal'] * int(report.sign)
+ if not account.company_id.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
+
+ @api.model
+ def get_report_values(self, docids, data=None):
+ if not data.get('form') or not self.env.context.get('active_model') or not self.env.context.get('active_id'):
+ raise UserError(_("Form content is missing, this report cannot be printed."))
+
+ self.model = self.env.context.get('active_model')
+ docs = self.env[self.model].browse(self.env.context.get('active_id'))
+ report_lines = self.get_account_lines(data.get('form'))
+ return {
+ 'doc_ids': self.ids,
+ 'doc_model': self.model,
+ 'data': data['form'],
+ 'docs': docs,
+ 'time': time,
+ 'get_account_lines': report_lines,
+ }
diff --git a/account_reports_xlsx/wizard/account_report_general_ledger.py b/account_reports_xlsx/wizard/account_report_general_ledger.py
new file mode 100644
index 0000000..e74d815
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_general_ledger.py
@@ -0,0 +1,240 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2020-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies (odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from odoo.exceptions import UserError
+import json
+import datetime
+import io
+from odoo import api, fields, models, _
+from odoo.tools import date_utils
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AccountReportGeneralLedger(models.TransientModel):
+ _name = "account.report.general.ledger.xlsx"
+ _description = "General Ledger Report"
+
+ 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('account.action_report_general_ledger').with_context(landscape=True).report_action(records, data=data)
+
+ 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')
+
+ def pre_print_report(self, data):
+ data['form'].update(self.read(['display_account'])[0])
+ return data
+
+ company_id = fields.Many2one('res.company', string=_('Company'), readonly=True,
+ default=lambda self: self.env.user.company_id)
+ journal_ids = fields.Many2many('account.journal', string=_('Journals'), required=True,
+ default=lambda self: self.env['account.journal'].search([]))
+ 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')
+
+ 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 _print_report(self, data):
+ # raise NotImplementedError()
+
+ 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'])[0]
+ used_context = self._build_contexts(data)
+ data['form']['used_context'] = dict(used_context, lang=self.env.context.get('lang') or 'en_US')
+ return {
+ 'type': 'ir.actions.report',
+ 'data': {'model': 'account.report.general.ledger.xlsx',
+ 'options': json.dumps(data, default=date_utils.json_default),
+ 'output_format': 'xlsx',
+ 'report_name': 'general ledger report',
+ },
+ 'report_type': 'xlsx'
+ }
+
+ def get_xlsx_report(self, options, response):
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ data = {}
+ vals = self.search([('id', '=', options['form']['id'])])
+ data['form'] = vals.read([])[0]
+ data['model'] = 'ir.ui.menu'
+ data['ids'] = []
+ data['form']['used_context'] = {
+ 'date_to': vals.date_to,
+ 'date_from': vals.date_from,
+ 'strict_range': True,
+ 'state': vals.target_move,
+ # 'active_model': 'account.account' if vals.active_account else None,
+ # 'active_ids': [vals.active_account.id] if vals.active_account else None,
+ # 'active_id': vals.active_account.id if vals.active_account else None,
+ 'journal_ids': vals.journal_ids.ids,
+ }
+
+ env_obj = vals.env['report.account.report_generalledger']
+ sortby = data['form'].get('sortby', 'sort_date')
+ display_account = data['form']['display_account']
+ codes = []
+ if data['form'].get('journal_ids', False):
+ codes = [journal.code for journal in
+ self.env['account.journal'].search([('id', 'in', data['form']['journal_ids'])])]
+ # accounts = vals.active_account if vals.active_account else self.env['account.account'].search([])
+ accounts = self.env['account.account'].browse(options['ids']) or self.env['account.account'].search([])
+ init_balance = vals['initial_balance']
+ report_obj = env_obj.with_context(data['form'].get('used_context', {}))._get_account_move_entry(
+ accounts, init_balance, sortby, display_account)
+ sheet = workbook.add_worksheet()
+ format1 = workbook.add_format({'font_size': 16, 'align': 'center', 'bg_color': '#D3D3D3', 'bold': True})
+ format1.set_font_color('#000080')
+ format2 = workbook.add_format({'font_size': 12, 'bold': True, 'bg_color': '#D3D3D3'})
+ format3 = workbook.add_format({'font_size': 10, 'bold': True})
+ format4 = workbook.add_format({'font_size': 10})
+ format6 = workbook.add_format({'font_size': 10, 'bold': True})
+ format7 = workbook.add_format({'font_size': 10, 'align': 'center'})
+ format5 = workbook.add_format({'font_size': 10, 'align': 'right'})
+ format1.set_align('center')
+ format2.set_align('center')
+ format3.set_align('right')
+ format4.set_align('left')
+ codes = []
+ if data['form'].get('journal_ids', False):
+ codes = [journal.code for journal in
+ self.env['account.journal'].search([('id', 'in', data['form']['journal_ids'])])]
+ logged_users = self.env['res.company']._company_default_get('account.account')
+ report_date = datetime.datetime.now().strftime("%Y-%m-%d")
+ sheet.merge_range('M8:N8', _("Report Date"), format3)
+ sheet.merge_range('M9:N9', report_date, format4)
+ sheet.merge_range(1, 0, 1, 14, logged_users.name, format4)
+ sheet.merge_range(3, 0, 4, 14, _("General Ledger Report"), format1)
+ sheet.merge_range('A6:B6', _("Journals :"), format6)
+ row = 6
+ col = 0
+ i = 0
+ for values in codes:
+ sheet.write(row, col + i, values, format7)
+ i += 1
+ if data['form']['display_account'] == 'all':
+ display_account = _('All accounts')
+ elif data['form']['display_account'] == 'movement':
+ display_account = _('With movements')
+ else:
+ display_account = _('With balance not equal to zero')
+
+ if data['form']['target_move'] == 'all':
+ target_moves = _('All entries')
+ else:
+ target_moves = _('All posted entries')
+
+ if data['form']['sortby'] == 'sort_date':
+ sortby = 'Date'
+ else:
+ sortby = 'Journal and partners'
+ if data['form']['date_from']:
+ date_start = data['form']['date_from']
+ else:
+ date_start = ""
+ if data['form']['date_to']:
+ date_end = data['form']['date_to']
+ else:
+ date_end = ""
+ if sortby == 'Date':
+ sheet.write('G8', _("Start Date"), format3)
+ sheet.write('G9', date_start, format4)
+ sheet.write('J8', _("End Date"), format3)
+ sheet.write('J9', date_end, format4)
+ sheet.merge_range('C8:D8', _("Sorted By"), format3)
+ sheet.merge_range('C9:D9', sortby, format4)
+ sheet.merge_range('A8:B8', _("Display Account"), format6)
+ sheet.merge_range('A9:B9', display_account, format7)
+ sheet.merge_range('E8:F8', _("Target Moves"), format6)
+ sheet.merge_range('E9:F9', target_moves, format7)
+ sheet.write('A11', "Date ", format2)
+ sheet.write('B11', "JRNL", format2)
+ sheet.merge_range('C11:D11', _("Partner"), format2)
+ sheet.merge_range('E11:F11', _("Ref"), format2)
+ sheet.merge_range('G11:H11', _("Move"), format2)
+ sheet.merge_range('I11:L11', _("Entry Label"), format2)
+ sheet.write('M11', _("Debit"), format2)
+ sheet.write('N11', _("Credit"), format2)
+ sheet.write('O11', _("Balance"), format2)
+ accounts = self.env['account.account'].search([])
+ row_number = 11
+ col_number = 0
+ for datas in accounts:
+ for values in report_obj:
+ if datas['name'] == values['name'] and datas['company_id'].id == values['company_id']:
+ sheet.write(row_number, col_number, datas['code'], format3)
+ sheet.merge_range(row_number, col_number + 1, row_number, col_number + 11, datas['name'], format6)
+ sheet.write(row_number, col_number + 12,
+ logged_users.currency_id.symbol + ' ' + "{:,}".format(values['debit']), format3)
+ sheet.write(row_number, col_number + 13,
+ logged_users.currency_id.symbol + ' ' + "{:,}".format(values['credit']), format3)
+ sheet.write(row_number, col_number + 14,
+ logged_users.currency_id.symbol + ' ' + "{:,}".format(values['balance']), format3)
+ row_number += 1
+ for lines in values['move_lines']:
+ sheet.write(row_number, col_number, lines['ldate'], format4)
+ sheet.write(row_number, col_number + 1, lines['lcode'], format4)
+ sheet.merge_range(row_number, col_number + 2, row_number, col_number + 3, lines['partner_name'],
+ format4)
+ sheet.merge_range(row_number, col_number + 4, row_number, col_number + 5, lines['lref'],
+ format4)
+ sheet.merge_range(row_number, col_number + 6, row_number, col_number + 7, lines['move_name'],
+ format4)
+ sheet.merge_range(row_number, col_number + 8, row_number, col_number + 11, lines['lname'],
+ format4)
+ sheet.write(row_number, col_number + 12, "{:,}".format(lines['debit']), format5)
+ sheet.write(row_number, col_number + 13, "{:,}".format(lines['credit']), format5)
+ sheet.write(row_number, col_number + 14, "{:,}".format(lines['balance']), format5)
+ row_number += 1
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/account_reports_xlsx/wizard/account_report_general_ledger_view.xml b/account_reports_xlsx/wizard/account_report_general_ledger_view.xml
new file mode 100644
index 0000000..ca391d5
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_general_ledger_view.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <record id="account_report_general_ledger_view" model="ir.ui.view">
+ <field name="name">General Ledger</field>
+ <field name="model">account.report.general.ledger.xlsx</field>
+ <field name="inherit_id" ref="account_common_report_view"/>
+ <field name="arch" type="xml">
+ <data>
+ <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>
+ </data>
+ </field>
+ </record>
+
+ <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.xlsx</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>
+
+ <menuitem
+ id="menu_general_ledger"
+ name="General Ledger"
+ parent="account.account_reports_management_menu"
+ action="action_account_general_ledger_menu"
+ groups="account.group_account_user"
+ />
+
+</odoo>
diff --git a/account_reports_xlsx/wizard/account_report_partner_ledger.py b/account_reports_xlsx/wizard/account_report_partner_ledger.py
new file mode 100644
index 0000000..83ccffc
--- /dev/null
+++ b/account_reports_xlsx/wizard/account_report_partner_ledger.py
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+######################################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2020-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
+# Author: Cybrosys Technologies (odoo@cybrosys.com)
+#
+# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
+# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
+# or modified copies of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+########################################################################################
+
+from odoo import fields, models,api
+import json
+import datetime
+import io
+from odoo import api, fields, models, _
+from odoo.exceptions import ValidationError
+from odoo.tools import date_utils
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AccountPartnerLedger(models.TransientModel):
+ _name = "account.report.partner.ledger.xlsx"
+
+ partner_ids = fields.Many2many('res.partner', 'partner_ledger_partner_rel', 'id', 'partner_id', string=_('Partners'))
+
+ def pre_print_report(self, data):
+ data['form'].update(self.read(['result_selection'])[0])
+ return data
+
+ company_id = fields.Many2one('res.company', string=_('Company'), readonly=True,
+ default=lambda self: self.env.user.company_id)
+ journal_ids = fields.Many2many('account.journal', string=_('Journals'), required=True,
+ default=lambda self: self.env['account.journal'].search([]))
+ 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')
+
+ def _print_report(self, data):
+ context = self._context
+ data = self.pre_print_report(data)
+ data['form'].update({'reconciled': self.reconciled, 'amount_currency': self.amount_currency,
+ 'partner_ids': self.partner_ids.ids})
+
+ if context.get('xls_export'):
+ return {
+ 'type': 'ir.actions.report',
+ 'data': {'model': 'account.report.partner.ledger.xlsx',
+ 'options': json.dumps(data, default=date_utils.json_default),
+ 'output_format': 'xlsx',
+ 'report_name': 'maintenance_report',
+ },
+ 'report_type': 'xlsx'
+ }
+ # return self.env.ref('account_reports_xlsx.partner_ledger_xlsx').report_action(self, data=data)
+ else:
+ return self.env.ref('account.action_report_partnerledger').report_action(self, data=data)
+
+ 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('partner_report.action_report_partnerledger').report_action(self, data=data)
+ #
+ 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 _print_report(self, data):
+ # raise NotImplementedError()
+
+ 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'])[0]
+ context = self._context
+ data = self.pre_print_report(data)
+ data['form'].update({'reconciled': self.reconciled, 'amount_currency': self.amount_currency,
+ 'partner_ids': self.partner_ids.ids})
+ # # ..........................
+ # data = self.pre_print_report(data)
+ # data['form'].update({'reconciled': self.reconciled, 'amount_currency': self.amount_currency})
+ # # ...............................................................
+ used_context = self._build_contexts(data)
+ data['form']['used_context'] = dict(used_context, lang=self.env.context.get('lang') or 'en_US')
+ # return self.with_context(discard_logo_check=True)._print_report(data)
+ return {
+ 'type': 'ir.actions.report',
+ 'data': {'model': 'account.report.partner.ledger.xlsx',
+ 'options': json.dumps(data, default=date_utils.json_default),
+ 'output_format': 'xlsx',
+ 'report_name': 'partner ledger report',
+ },
+ 'report_type': 'xlsx'
+ }
+
+ def get_xlsx_report(self, options, response):
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ data = {}
+ data['form'] = options
+ # data['form'] = vals.read([])[0]
+ data['model'] = 'ir.ui.menu'
+ data['ids'] = []
+ data['form']['used_context'] = {}
+ data['form']['used_context']['date_to'] = options['form']['date_to']
+ data['form']['used_context']['date_from'] = options['form']['date_from']
+ data['form']['used_context']['journal_ids'] = options['form']['journal_ids']
+ data['form']['used_context']['state'] = 'posted'
+ data['form']['used_context']['strict_range'] = True
+ env_obj = self.search([('id','=',options['form']['id'])]).env['report.account_reports_xlsx.report_partnerledger']
+ data['computed'] = {}
+ obj_partner = env_obj.env['res.partner']
+ query_get_data = env_obj.env['account.move.line'].with_context(
+ data['form'].get('used_context', {}))._query_get()
+ data['computed']['move_state'] = ['draft', 'posted']
+ if data['form'].get('target_move', 'all') == 'posted':
+ data['computed']['move_state'] = ['posted']
+ result_selection = data['form'].get('result_selection', 'customer')
+ if result_selection == 'supplier':
+ data['computed']['ACCOUNT_TYPE'] = ['payable']
+ elif result_selection == 'customer':
+ data['computed']['ACCOUNT_TYPE'] = ['receivable']
+ else:
+ data['computed']['ACCOUNT_TYPE'] = ['payable', 'receivable']
+ env_obj.env.cr.execute("""
+ SELECT a.id
+ FROM account_account a
+ WHERE a.internal_type IN %s
+ AND NOT a.deprecated""", (tuple(data['computed']['ACCOUNT_TYPE']),))
+ data['computed']['account_ids'] = [a for (a,) in env_obj.env.cr.fetchall()]
+ params = [tuple(data['computed']['move_state']), tuple(data['computed']['account_ids'])] + query_get_data[2]
+ reconcile_clause = "" if data['form']['form']['reconciled'] else ' AND "account_move_line".full_reconcile_id IS NULL '
+ query = """
+ SELECT DISTINCT "account_move_line".partner_id
+ FROM """ + query_get_data[0] + """, account_account AS account, account_move AS am
+ WHERE "account_move_line".partner_id IS NOT NULL
+ AND "account_move_line".account_id = account.id
+ AND am.id = "account_move_line".move_id
+ AND am.state IN %s
+ AND "account_move_line".account_id IN %s
+ AND NOT account.deprecated
+ AND """ + query_get_data[1] + reconcile_clause
+ env_obj.env.cr.execute(query, tuple(params))
+ # # ---------------------Taking only selected partners---------------------------
+ if data['form']['form']['partner_ids']:
+ partner_ids = data['form']['form']['partner_ids']
+ else:
+ partner_ids = [res['partner_id'] for res in env_obj.env.cr.dictfetchall()]
+ # # -----------------------------------------------------------------------------
+ # partner_ids = [res['partner_id'] for res in self.env.cr.dictfetchall()]
+ partners = obj_partner.browse(partner_ids)
+ partners = sorted(partners, key=lambda x: (x.name or ''))
+ # partners = sorted(partners, key=lambda x: (x.uniqueid or '', x.name or ''))
+ for items in partners:
+ partner_currency_balance = 0
+ sheet = workbook.add_worksheet(str(items.name))
+ format1 = workbook.add_format({'font_size': 16, 'align': 'center', 'bg_color': '#D3D3D3', 'bold': True})
+ format1.set_font_color('#000080')
+ format2 = workbook.add_format({'font_size': 12, 'bold': True})
+ format3 = workbook.add_format({'font_size': 10, 'bold': True})
+ format4 = workbook.add_format({'font_size': 10})
+ format5 = workbook.add_format({'font_size': 10})
+ format6 = workbook.add_format({'font_size': 10, 'bold': True})
+ format7 = workbook.add_format({'font_size': 10, 'bold': True})
+ format8 = workbook.add_format({'font_size': 10})
+ format9 = workbook.add_format({'font_size': 10})
+ format10 = workbook.add_format({'font_size': 10, 'bold': True})
+ format1.set_align('center')
+ format3.set_align('center')
+ format4.set_align('center')
+ format6.set_align('right')
+ currency = self.env.user.company_id.currency_id.symbol
+ format7.set_num_format('0.00 ' + currency)
+ format8.set_num_format('0.00 ' + currency)
+ logged_users = self.env['res.company']._company_default_get('account.account')
+ sheet.merge_range('A1:B1', logged_users.name, format4)
+ if data['form']['form']['date_from']:
+ sheet.write('E2', _('Date from:'), format6)
+ sheet.write('F2', data['form']['form']['date_from'], format5)
+ if data['form']['form']['date_to']:
+ sheet.write('E3', _('Date to:'), format6)
+ sheet.write('F3', data['form']['form']['date_to'], format5)
+ sheet.merge_range('I2:J2', _('Target Moves:'), format6)
+ if data['form']['form']['target_move'] == 'all':
+ sheet.merge_range('K2:L2', _('All Entries'), format4)
+ if data['form']['form']['target_move'] == 'posted':
+ sheet.merge_range('K2:L2', _('All Posted Entries'), format4)
+ sheet.merge_range(5, 0, 5, 1, _("Date"), format3)
+ sheet.merge_range(5, 2, 5, 3, _("JRNL"), format3)
+ sheet.merge_range(5, 4, 5, 5, _("Account"), format3)
+ sheet.merge_range(5, 6, 5, 7, _("Ref"), format3)
+ sheet.merge_range(5, 8, 5, 9, _("Debit"), format3)
+ sheet.merge_range(5, 10, 5, 11, _("Credit"), format3)
+ sheet.merge_range(5, 12, 5, 13, _("Balance"), format3)
+ if data['form']['form']['amount_currency']:
+ sheet.merge_range(5, 14, 5, 15, _("Currency"), format3)
+ sheet.merge_range(3, 0, 4, 15, _("Partner Ledger Report"), format1)
+ else:
+ sheet.merge_range(3, 0, 4, 13, _("Partner Ledger Report"), format1)
+ partner_name = ''
+ # if items.uniqueid:
+ # partner_name = str(items.uniqueid)
+ if items.name:
+ partner_name = partner_name + str(items.name)
+ sheet.merge_range(6, 0, 6, 6, partner_name, format2)
+ debit = env_obj._sum_partner(data, items, 'debit')
+ credit = env_obj._sum_partner(data, items, 'credit')
+ balance = env_obj._sum_partner(data, items, 'debit - credit')
+ sheet.merge_range(6, 8, 6, 9, debit, format7)
+ sheet.merge_range(6, 10, 6, 11, credit, format7)
+ sheet.merge_range(6, 12, 6, 13, balance, format7)
+ row_value = 7
+ for values in env_obj._lines(data, items):
+ sheet.merge_range(row_value, 0, row_value, 1, values['date'], format4)
+ sheet.merge_range(row_value, 2, row_value, 3, values['code'], format4)
+ sheet.merge_range(row_value, 4, row_value, 5, values['a_code'], format4)
+ sheet.merge_range(row_value, 6, row_value, 7, values['displayed_name'], format4)
+ sheet.merge_range(row_value, 8, row_value, 9, values['debit'], format8)
+ sheet.merge_range(row_value, 10, row_value, 11, values['credit'], format8)
+ sheet.merge_range(row_value, 12, row_value, 13, values['progress'], format8)
+ if data['form']['form']['amount_currency']:
+ if values['currency_id']:
+ partner_currency = values['currency_id'].symbol
+ format9.set_num_format('0.00 ' + partner_currency)
+ format10.set_num_format('0.00 ' + partner_currency)
+ sheet.merge_range(row_value, 14, row_value, 15, values['amount_currency'], format9)
+ partner_currency_balance += values['amount_currency']
+ sheet.merge_range(6, 14, 6, 15, partner_currency_balance, format10)
+ row_value += 1
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/account_reports_xlsx/wizard/partner_ledger_wizard_view.xml b/account_reports_xlsx/wizard/partner_ledger_wizard_view.xml
new file mode 100644
index 0000000..d4d9bf9
--- /dev/null
+++ b/account_reports_xlsx/wizard/partner_ledger_wizard_view.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="account_common_report_view" model="ir.ui.view">
+ <field name="name">Common Report</field>
+ <field name="model">account.common.report</field>
+ <field name="arch" type="xml">
+ <form string="Report Options">
+ <field name="company_id" invisible="1"/>
+ <group col="4">
+ <field name="target_move" widget="radio"/>
+ <field name="date_from"/>
+ <field name="date_to"/>
+ </group>
+ <group>
+ <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>
+
+ <record id="action_account_common_menu" model="ir.actions.act_window">
+ <field name="name">Common Report</field>
+ <field name="res_model">account.common.report</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="account_common_report_view"/>
+ <field name="target">new</field>
+ </record>
+
+ <record id="account_report_partner_ledger_view" model="ir.ui.view">
+ <field name="name">Partner Ledger</field>
+ <field name="model">account.report.partner.ledger.xlsx</field>
+ <field name="inherit_id" ref="account.account_common_report_view"/>
+ <field name="arch" type="xml">
+ <data>
+ <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>
+ </data>
+ </field>
+ </record>
+
+ <record id="action_view_partner_report" model="ir.actions.act_window">
+ <field name="name">Partner Ledger</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">account.report.partner.ledger.xlsx</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="account_report_partner_ledger_view"/>
+ <field name="target">new</field>
+ <field name="binding_model_id" ref="account.model_account_account" />
+ <field name="binding_type">report</field>
+ </record>
+
+
+<menuitem id="partner_report_child_menu" name="Partner Ledger" action="action_view_partner_report" parent="account.account_reports_management_menu" sequence="100"/>
+</odoo> \ No newline at end of file