summaryrefslogtreecommitdiff
path: root/dynamic_accounts_report/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 /dynamic_accounts_report/wizard
parentb57188be371d36d96caac4b8d65a40745c0e972c (diff)
initial commit
Diffstat (limited to 'dynamic_accounts_report/wizard')
-rw-r--r--dynamic_accounts_report/wizard/__init__.py8
-rw-r--r--dynamic_accounts_report/wizard/ageing.py682
-rw-r--r--dynamic_accounts_report/wizard/balance_sheet.py611
-rw-r--r--dynamic_accounts_report/wizard/balance_sheet_config.py305
-rw-r--r--dynamic_accounts_report/wizard/cash_flow.py604
-rw-r--r--dynamic_accounts_report/wizard/daybook.py320
-rw-r--r--dynamic_accounts_report/wizard/general_ledger.py477
-rw-r--r--dynamic_accounts_report/wizard/partner_leadger.py456
-rw-r--r--dynamic_accounts_report/wizard/trial_balance.py324
9 files changed, 3787 insertions, 0 deletions
diff --git a/dynamic_accounts_report/wizard/__init__.py b/dynamic_accounts_report/wizard/__init__.py
new file mode 100644
index 0000000..2f21060
--- /dev/null
+++ b/dynamic_accounts_report/wizard/__init__.py
@@ -0,0 +1,8 @@
+from . import general_ledger
+from . import trial_balance
+from . import cash_flow
+from . import balance_sheet
+from . import balance_sheet_config
+from . import partner_leadger
+from . import ageing
+from . import daybook
diff --git a/dynamic_accounts_report/wizard/ageing.py b/dynamic_accounts_report/wizard/ageing.py
new file mode 100644
index 0000000..652ff29
--- /dev/null
+++ b/dynamic_accounts_report/wizard/ageing.py
@@ -0,0 +1,682 @@
+import time
+from datetime import datetime
+
+from dateutil.relativedelta import relativedelta
+from odoo import fields, models, api, _
+from odoo.tools import float_is_zero
+
+import io
+import json
+
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AgeingView(models.TransientModel):
+ _inherit = "account.common.report"
+ _name = 'account.partner.ageing'
+
+ period_length = fields.Integer(string='Period Length (days)',
+ required=True, default=30)
+ date_from = fields.Date(default=lambda *a: time.strftime('%Y-%m-%d'))
+ result_selection = fields.Selection([('customer', 'Receivable Accounts'),
+ ('supplier', 'Payable Accounts'),
+ ('customer_supplier',
+ 'Receivable and Payable Accounts')
+ ], string="Partner's", required=True,
+ default='customer')
+
+ partner_ids = fields.Many2many(
+ 'res.partner', string='Partner'
+ )
+ partner_category_ids = fields.Many2many(
+ 'res.partner.category', string='Partner Tag',
+ )
+
+ @api.model
+ def view_report(self, option):
+ r = self.env['account.partner.ageing'].search([('id', '=', option[0])])
+
+ data = {
+ 'result_selection': r.result_selection,
+ 'model': self,
+ 'journals': r.journal_ids,
+ 'target_move': r.target_move,
+ 'period_length': r.period_length,
+ 'partners': r.partner_ids,
+ 'partner_tags': r.partner_category_ids,
+
+ }
+ if r.date_from:
+ data.update({
+ 'date_from': r.date_from,
+ })
+
+ filters = self.get_filter(option)
+
+ records = self._get_report_values(data)
+
+ currency = self._get_currency()
+
+ return {
+ 'name': "Partner Ageing",
+ 'type': 'ir.actions.client',
+ 'tag': 'p_a',
+ 'filters': filters,
+ 'report_lines': records['Partners'],
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('result_selection') == 'customer':
+ filters['result_selection'] = 'Receivable'
+ elif data.get('result_selection') == 'supplier':
+ filters['result_selection'] = 'Payable'
+ else:
+ filters['result_selection'] = 'Receivable and Payable'
+
+ if data.get('partners'):
+ filters['partners'] = self.env['res.partner'].browse(
+ data.get('partners')).mapped('name')
+ else:
+ filters['partners'] = ['All']
+
+ if data.get('partner_tags', []):
+ filters['partner_tags'] = self.env['res.partner.category'].browse(
+ data.get('partner_tags', [])).mapped('name')
+ else:
+ filters['partner_tags'] = ['All']
+
+ filters['company_id'] = ''
+ filters['company_name'] = data.get('company_name')
+ filters['partners_list'] = data.get('partners_list')
+ filters['category_list'] = data.get('category_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+
+
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.partner.ageing'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ partner = r.partner_ids if r.partner_ids else self.env[
+ 'res.partner'].search([])
+ categories = r.partner_category_ids if r.partner_category_ids \
+ else self.env['res.partner.category'].search([])
+
+ filter_dict = {
+ 'partners': r.partner_ids.ids,
+ 'partner_tags': r.partner_category_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+
+ 'target_move': r.target_move,
+ 'result_selection': r.result_selection,
+ 'partners_list': [(p.id, p.name) for p in partner],
+ 'category_list': [(c.id, c.name) for c in categories],
+ 'company_name': company_id and company_id.name,
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data):
+ docs = data['model']
+ date_from = data.get('date_from').strftime('%Y-%m-%d')
+ if data['result_selection'] == 'customer':
+ account_type = ['receivable']
+ elif data['result_selection'] == 'supplier':
+ account_type = ['payable']
+ else:
+ account_type = ['payable', 'receivable']
+ target_move = data['target_move']
+ partners = data.get('partners')
+ if data['partner_tags']:
+ partners = self.env['res.partner'].search(
+ [('category_id', 'in', data['partner_tags'].ids)])
+
+ account_res = self._get_partner_move_lines(data, partners, date_from,
+ target_move,
+ account_type,
+ data['period_length'])
+
+ return {
+ 'doc_ids': self.ids,
+ 'docs': docs,
+ 'time': time,
+ 'Partners': account_res,
+
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(AgeingView, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+
+ if vals.get('partner_ids'):
+ vals.update(
+ {'partner_ids': [(4, j) for j in vals.get('partner_ids')]})
+ if not vals.get('partner_ids'):
+ vals.update({'partner_ids': [(5,)]})
+ if vals.get('partner_category_ids'):
+ vals.update({'partner_category_ids': [(4, j) for j in vals.get(
+ 'partner_category_ids')]})
+ if not vals.get('partner_category_ids'):
+ vals.update({'partner_category_ids': [(5,)]})
+
+ res = super(AgeingView, self).write(vals)
+ return res
+
+ def _get_partner_move_lines(self, data, partners, date_from, target_move,
+ account_type,
+ period_length):
+
+ periods = {}
+ start = datetime.strptime(date_from, "%Y-%m-%d")
+ date_from = datetime.strptime(date_from, "%Y-%m-%d").date()
+ for i in range(5)[::-1]:
+ stop = start - relativedelta(days=period_length)
+ period_name = str((5 - (i + 1)) * period_length + 1) + '-' + str(
+ (5 - i) * period_length)
+ period_stop = (start - relativedelta(days=1)).strftime('%Y-%m-%d')
+ if i == 0:
+ period_name = '+' + str(4 * period_length)
+ periods[str(i)] = {
+ 'name': period_name,
+ 'stop': period_stop,
+ 'start': (i != 0 and stop.strftime('%Y-%m-%d') or False),
+ }
+ start = stop
+ res = []
+ total = []
+ cr = self.env.cr
+ user_company = self.env.company
+
+ user_currency = user_company.currency_id
+ ResCurrency = self.env['res.currency'].with_context(date=date_from)
+ company_ids = self._context.get('company_ids') or [user_company.id]
+ move_state = ['draft', 'posted']
+ if target_move == 'posted':
+ move_state = ['posted']
+ arg_list = (tuple(move_state), tuple(account_type))
+
+ reconciliation_clause = '(l.reconciled IS FALSE)'
+ cr.execute(
+ 'SELECT debit_move_id, credit_move_id FROM account_partial_reconcile where max_date > %s',
+ (date_from,))
+ reconciled_after_date = []
+ for row in cr.fetchall():
+ reconciled_after_date += [row[0], row[1]]
+ if reconciled_after_date:
+ reconciliation_clause = '(l.reconciled IS FALSE OR l.id IN %s)'
+ arg_list += (tuple(reconciled_after_date),)
+
+ arg_list += (date_from, tuple(company_ids),)
+ partner_list = '(l.partner_id IS NOT NULL)'
+ if partners:
+ list = tuple(partners.ids) + tuple([0])
+ if list:
+ partner_list = '(l.partner_id IS NULL OR l.partner_id IN %s)'
+ arg_list += (tuple(list),)
+ query = '''
+ SELECT DISTINCT l.partner_id, UPPER(res_partner.name)
+ FROM account_move_line AS l left join res_partner on l.partner_id = res_partner.id, account_account, account_move am
+ WHERE (l.account_id = account_account.id)
+ AND (l.move_id = am.id)
+ AND (am.state IN %s)
+ AND (account_account.internal_type IN %s)
+
+ AND ''' + reconciliation_clause + '''
+ AND (l.date <= %s)
+ AND l.company_id IN %s
+ AND ''' + partner_list + '''
+
+ ORDER BY UPPER(res_partner.name)'''
+ cr.execute(query, arg_list)
+
+
+ partners = cr.dictfetchall()
+
+ # put a total of 0
+ for i in range(7):
+ total.append(0)
+
+ # Build a string like (1,2,3) for easy use in SQL query
+ partner_ids = [partner['partner_id'] for partner in partners if
+ partner['partner_id']]
+
+ lines = dict(
+ (partner['partner_id'] or False, []) for partner in partners)
+ if not partner_ids:
+ return [], [], {}
+
+ # This dictionary will store the not due amount of all partners
+ undue_amounts = {}
+ query = '''SELECT l.id
+ FROM account_move_line AS l, account_account, account_move am
+ WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
+ AND (am.state IN %s)
+ AND (account_account.internal_type IN %s)
+ AND (COALESCE(l.date_maturity,l.date) >= %s)\
+ AND ((l.partner_id IN %s) OR (l.partner_id IS NULL))
+ AND (l.date <= %s)
+ AND l.company_id IN %s'''
+ cr.execute(query, (
+ tuple(move_state), tuple(account_type), date_from,
+ tuple(partner_ids), date_from, tuple(company_ids)))
+ aml_ids = cr.fetchall()
+ aml_ids = aml_ids and [x[0] for x in aml_ids] or []
+ for line in self.env['account.move.line'].browse(aml_ids):
+ partner_id = line.partner_id.id or False
+ move_id = line.move_id.id
+ move_name = line.move_id.name
+ date_maturity = line.date_maturity
+ account_id = line.account_id.name
+ account_code = line.account_id.code
+ jrnl_id = line.journal_id.name
+ currency_id = line.company_id.currency_id.position
+ currency_symbol = line.company_id.currency_id.symbol
+
+ if partner_id not in undue_amounts:
+ undue_amounts[partner_id] = 0.0
+ line_amount = ResCurrency._compute(line.company_id.currency_id,
+ user_currency, line.balance)
+ if user_currency.is_zero(line_amount):
+ continue
+ for partial_line in line.matched_debit_ids:
+ if partial_line.max_date <= date_from:
+ line_amount += ResCurrency._compute(
+ partial_line.company_id.currency_id, user_currency,
+ partial_line.amount)
+ for partial_line in line.matched_credit_ids:
+ if partial_line.max_date <= date_from:
+ line_amount -= ResCurrency._compute(
+ partial_line.company_id.currency_id, user_currency,
+ partial_line.amount)
+ if not self.env.company.currency_id.is_zero(line_amount):
+ undue_amounts[partner_id] += line_amount
+ lines[partner_id].append({
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'jrnl': jrnl_id,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'acc_name': account_id,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ 'period6': 6,
+ })
+
+ # Use one query per period and store results in history (a list variable)
+ # Each history will contain: history[1] = {'<partner_id>': <partner_debit-credit>}
+ history = []
+ for i in range(5):
+ args_list = (
+ tuple(move_state), tuple(account_type), tuple(partner_ids),)
+ dates_query = '(COALESCE(l.date_maturity,l.date)'
+
+ if periods[str(i)]['start'] and periods[str(i)]['stop']:
+ dates_query += ' BETWEEN %s AND %s)'
+
+ args_list += (
+ periods[str(i)]['start'], periods[str(i)]['stop'])
+ elif periods[str(i)]['start']:
+ dates_query += ' >= %s)'
+
+ args_list += (periods[str(i)]['start'],)
+ else:
+ dates_query += ' <= %s)'
+ args_list += (periods[str(i)]['stop'],)
+
+ args_list += (date_from, tuple(company_ids))
+
+ query = '''SELECT l.id
+ FROM account_move_line AS l, account_account, account_move am
+ WHERE (l.account_id = account_account.id) AND (l.move_id = am.id)
+ AND (am.state IN %s)
+ AND (account_account.internal_type IN %s)
+ AND ((l.partner_id IN %s) OR (l.partner_id IS NULL))
+ AND ''' + dates_query + '''
+
+
+ AND (l.date <= %s)
+ AND l.company_id IN %s'''
+ cr.execute(query, args_list)
+
+ partners_amount = {}
+ aml_ids = cr.fetchall()
+ aml_ids = aml_ids and [x[0] for x in aml_ids] or []
+ for line in self.env['account.move.line'].browse(aml_ids):
+ partner_id = line.partner_id.id or False
+ move_id = line.move_id.id
+ move_name = line.move_id.name
+ date_maturity = line.date_maturity
+ account_id = line.account_id.name
+ account_code = line.account_id.code
+ jrnl_id = line.journal_id.name
+ currency_id = line.company_id.currency_id.position
+ currency_symbol = line.company_id.currency_id.symbol
+ if partner_id not in partners_amount:
+ partners_amount[partner_id] = 0.0
+ line_amount = ResCurrency._compute(line.company_id.currency_id,
+ user_currency, line.balance)
+ if user_currency.is_zero(line_amount):
+ continue
+ for partial_line in line.matched_debit_ids:
+ if partial_line.max_date <= date_from:
+ line_amount += ResCurrency._compute(
+ partial_line.company_id.currency_id, user_currency,
+ partial_line.amount)
+ for partial_line in line.matched_credit_ids:
+ if partial_line.max_date <= date_from:
+ line_amount -= ResCurrency._compute(
+ partial_line.company_id.currency_id, user_currency,
+ partial_line.amount)
+
+ if not self.env.company.currency_id.is_zero(
+ line_amount):
+ partners_amount[partner_id] += line_amount
+ if i + 1 == 5:
+ period5 = i + 1
+ lines[partner_id].append({
+ 'period5': period5,
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'jrnl': jrnl_id,
+ 'acc_name': account_id,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ })
+ elif i + 1 == 4:
+ period4 = i + 1
+ lines[partner_id].append({
+
+ 'period4': period4,
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'jrnl': jrnl_id,
+ 'acc_name': account_id,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ })
+ elif i + 1 == 3:
+ period3 = i + 1
+ lines[partner_id].append({
+
+ 'period3': period3,
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'jrnl': jrnl_id,
+ 'acc_name': account_id,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ })
+ elif i + 1 == 2:
+ period2 = i + 1
+ lines[partner_id].append({
+
+ 'period2': period2,
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'jrnl': jrnl_id,
+ 'acc_name': account_id,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ })
+ else:
+ period1 = i + 1
+ lines[partner_id].append({
+
+ 'period1': period1,
+ 'line': line,
+ 'partner_id': partner_id,
+ 'move': move_name,
+ 'jrnl': jrnl_id,
+ 'acc_name': account_id,
+ 'currency': currency_id,
+ 'symbol': currency_symbol,
+ 'mov_id': move_id,
+ 'acc_code': account_code,
+ 'date': date_maturity,
+ 'amount': line_amount,
+ })
+
+ history.append(partners_amount)
+
+ for partner in partners:
+ if partner['partner_id'] is None:
+ partner['partner_id'] = False
+ at_least_one_amount = False
+ values = {}
+ undue_amt = 0.0
+ if partner[
+ 'partner_id'] in undue_amounts: # Making sure this partner actually was found by the query
+ undue_amt = undue_amounts[partner['partner_id']]
+
+ total[6] = total[6] + undue_amt
+ values['direction'] = undue_amt
+ for rec in lines:
+ if partner['partner_id'] == rec:
+ child_lines = lines[rec]
+ values['child_lines'] = child_lines
+ if not float_is_zero(values['direction'],
+ precision_rounding=self.env.company.currency_id.rounding):
+ at_least_one_amount = True
+
+ for i in range(5):
+ during = False
+ if partner['partner_id'] in history[i]:
+ during = [history[i][partner['partner_id']]]
+ # Adding counter
+ total[(i)] = total[(i)] + (during and during[0] or 0)
+ values[str(i)] = during and during[0] or 0.0
+ if not float_is_zero(values[str(i)],
+ precision_rounding=self.env.company.currency_id.rounding):
+ at_least_one_amount = True
+ values['total'] = sum(
+ [values['direction']] + [values[str(i)] for i in range(5)])
+ ## Add for total
+ total[(i + 1)] += values['total']
+ values['partner_id'] = partner['partner_id']
+ if partner['partner_id']:
+ browsed_partner = self.env['res.partner'].browse(
+ partner['partner_id'])
+ values['name'] = browsed_partner.name and len(
+ browsed_partner.name) >= 45 and browsed_partner.name[
+ 0:40] + '...' or browsed_partner.name
+ values['trust'] = browsed_partner.trust
+ else:
+ values['name'] = _('Unknown Partner')
+ values['trust'] = False
+
+ if at_least_one_amount or (
+ self._context.get('include_nullified_amount') and lines[
+ partner['partner_id']]):
+ res.append(values)
+
+ return res, total, lines
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position, lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response, report_data, dfr_data ):
+
+ report_data_main = json.loads(report_data)
+ output = io.BytesIO()
+
+ filters = json.loads(data)
+
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+ sub_heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 2,
+ 'border_color': 'black'})
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_l = workbook.add_format(
+ {'font_size': '10px', 'border': 1, 'bold': True})
+ txt_v = workbook.add_format(
+ {'align': 'right', 'font_size': '10px', 'border': 1})
+ sheet.merge_range('A2:H3',
+ filters.get('company_name') + ':' + ' Partner Ageing',
+ head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+ date_style = workbook.add_format({'align': 'center',
+ 'font_size': '10px'})
+ if filters.get('date_from'):
+ sheet.merge_range('A4:B4',
+ 'As On Date: ' + filters.get('date_from'),
+ date_head)
+ sheet.merge_range('C4:E4',
+ 'Account Type: ' + filters.get('result_selection'),
+ date_head)
+ sheet.merge_range('A5:B5',
+ 'Target Moves: ' + filters.get('target_move'),
+ date_head)
+ sheet.merge_range('D5:F5', ' Partners: ' + ', '.join(
+ [lt or '' for lt in
+ filters['partners']]), date_head)
+ sheet.merge_range('G5:H5', ' Partner Type: ' + ', '.join(
+ [lt or '' for lt in
+ filters['partner_tags']]),
+ date_head)
+
+ sheet.merge_range('A7:C7', 'Partner', heading)
+ sheet.write('D7', 'Total', heading)
+ sheet.write('E7', 'Not Due', heading)
+ sheet.write('F7', '0-30', heading)
+ sheet.write('G7', '30-60', heading)
+ sheet.write('H7', '60-90', heading)
+ sheet.write('I7', '90-120', heading)
+ sheet.write('J7', '120+', heading)
+
+ lst = []
+ for rec in report_data_main[0]:
+ lst.append(rec)
+ row = 6
+ col = 0
+ sheet.set_column(5, 0, 15)
+ sheet.set_column(6, 1, 15)
+ sheet.set_column(7, 2, 15)
+ sheet.set_column(8, 3, 15)
+ sheet.set_column(9, 4, 15)
+ sheet.set_column(10, 5, 15)
+ sheet.set_column(11, 6, 15)
+
+ for rec_data in report_data_main[0]:
+ one_lst = []
+ two_lst = []
+
+ row += 1
+ sheet.merge_range(row, col, row, col + 2, rec_data['name'], txt_l)
+ sheet.write(row, col + 3, rec_data['total'], txt_l)
+ sheet.write(row, col + 4, rec_data['direction'], txt_l)
+ sheet.write(row, col + 5, rec_data['4'], txt_l)
+ sheet.write(row, col + 6, rec_data['3'], txt_l)
+ sheet.write(row, col + 7, rec_data['2'], txt_l)
+ sheet.write(row, col + 8, rec_data['1'], txt_l)
+ sheet.write(row, col + 9, rec_data['0'], txt_l)
+ row += 1
+ sheet.write(row, col, 'Entry Label', sub_heading)
+ sheet.write(row, col + 1, 'Due Date', sub_heading)
+ sheet.write(row, col + 2, 'Journal', sub_heading)
+ sheet.write(row, col + 3, 'Account', sub_heading)
+ sheet.write(row, col + 4, 'Not Due', sub_heading)
+ sheet.write(row, col + 5, '0 - 30', sub_heading)
+ sheet.write(row, col + 6, '30 - 60', sub_heading)
+ sheet.write(row, col + 7, '60 - 90', sub_heading)
+ sheet.write(row, col + 8, '90 - 120', sub_heading)
+ sheet.write(row, col + 9, '120 +', sub_heading)
+
+ for line_data in rec_data['child_lines']:
+ row += 1
+ sheet.write(row, col, line_data.get('move'), txt)
+ sheet.write(row, col + 1, line_data.get('date'), txt)
+ sheet.write(row, col + 2, line_data.get('jrnl'), txt)
+ sheet.write(row, col + 3, line_data.get('acc_code'), txt)
+ if line_data.get('period6'):
+ sheet.write(row, col + 4, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 4, "0", txt_v)
+ if line_data.get('period5'):
+ sheet.write(row, col + 5, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 5, "0", txt_v)
+ if line_data.get('period4'):
+ sheet.write(row, col + 6, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 6, "0", txt_v)
+ if line_data.get('period3'):
+ sheet.write(row, col + 7, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 7, "0", txt_v)
+ if line_data.get('period2'):
+ sheet.write(row, col + 8, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 8, "0", txt_v)
+ if line_data.get('period1'):
+ sheet.write(row, col + 9, line_data.get('amount'), txt)
+ else:
+ sheet.write(row, col + 9, "0", txt_v)
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close()
diff --git a/dynamic_accounts_report/wizard/balance_sheet.py b/dynamic_accounts_report/wizard/balance_sheet.py
new file mode 100644
index 0000000..ac12975
--- /dev/null
+++ b/dynamic_accounts_report/wizard/balance_sheet.py
@@ -0,0 +1,611 @@
+import time
+from odoo import fields, models, api, _
+
+import io
+import json
+from odoo.exceptions import AccessError, UserError, AccessDenied
+
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class BalanceSheetView(models.TransientModel):
+ _name = 'dynamic.balance.sheet.report'
+
+ company_id = fields.Many2one('res.company', required=True,
+ default=lambda self: self.env.company)
+ journal_ids = fields.Many2many('account.journal',
+ string='Journals', required=True,
+ default=[])
+ account_ids = fields.Many2many("account.account", string="Accounts")
+ account_tag_ids = fields.Many2many("account.account.tag",
+ string="Account Tags")
+ analytic_ids = fields.Many2many(
+ "account.analytic.account", string="Analytic Accounts")
+ analytic_tag_ids = fields.Many2many("account.analytic.tag",
+ string="Analytic Tags")
+ 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')
+ target_move = fields.Selection(
+ [('all', 'All'), ('posted', 'Posted')],
+ string='Target Move', required=True, default='posted')
+ date_from = fields.Date(string="Start date")
+ date_to = fields.Date(string="End date")
+
+ @api.model
+ def view_report(self, option, tag):
+ r = self.env['dynamic.balance.sheet.report'].search(
+ [('id', '=', option[0])])
+ data = {
+ 'display_account': r.display_account,
+ 'model': self,
+ 'journals': r.journal_ids,
+ 'target_move': r.target_move,
+ 'accounts': r.account_ids,
+ 'account_tags': r.account_tag_ids,
+ 'analytics': r.analytic_ids,
+ 'analytic_tags': r.analytic_tag_ids,
+ }
+ if r.date_from:
+ data.update({
+ 'date_from': r.date_from,
+ })
+ if r.date_to:
+ data.update({
+ 'date_to': r.date_to,
+ })
+
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ if r.account_tag_ids:
+ company_domain.append(
+ ('tag_ids', 'in', r.account_tag_ids.ids))
+ if r.account_ids:
+ company_domain.append(('id', 'in', r.account_ids.ids))
+
+ new_account_ids = self.env['account.account'].search(company_domain)
+ data.update({'accounts': new_account_ids,})
+ filters = self.get_filter(option)
+ records = self._get_report_values(data)
+
+ if filters['account_tags'] != ['All']:
+ tag_accounts = list(map(lambda x: x.code, new_account_ids))
+
+ def filter_code(rec_dict):
+ if rec_dict['code'] in tag_accounts:
+ return True
+ else:
+ return False
+
+ new_records = list(filter(filter_code, records['Accounts']))
+ records['Accounts'] = new_records
+
+ account_report_id = self.env['account.financial.report'].search([
+ ('name', 'ilike', tag)])
+
+ new_data = {'id': self.id, 'date_from': False,
+ 'enable_filter': True,
+ 'debit_credit': True,
+ 'date_to': False, 'account_report_id': account_report_id,
+ 'target_move': filters['target_move'],
+ 'view_format': 'vertical',
+ 'company_id': self.company_id,
+ 'used_context': {'journal_ids': False,
+ 'state': filters['target_move'].lower(),
+ 'date_from': filters['date_from'],
+ 'date_to': filters['date_to'],
+ 'strict_range': False,
+ 'company_id': self.company_id,
+ 'lang': 'en_US'}}
+
+ account_lines = self.get_account_lines(new_data)
+ report_lines = self.view_report_pdf(account_lines, new_data)[
+ 'report_lines']
+ move_line_accounts = []
+ move_lines_dict = {}
+
+ for rec in records['Accounts']:
+ move_line_accounts.append(rec['code'])
+ move_lines_dict[rec['code']] = {}
+ move_lines_dict[rec['code']]['debit'] = rec['debit']
+ move_lines_dict[rec['code']]['credit'] = rec['credit']
+ move_lines_dict[rec['code']]['balance'] = rec['balance']
+
+ report_lines_move = []
+ parent_list = []
+
+ def filter_movelines_parents(obj):
+ for each in obj:
+ if each['report_type'] == 'accounts':
+ if each['code'] in move_line_accounts:
+ report_lines_move.append(each)
+ parent_list.append(each['p_id'])
+
+ elif each['report_type'] == 'account_report':
+ report_lines_move.append(each)
+ else:
+ report_lines_move.append(each)
+
+ filter_movelines_parents(report_lines)
+
+ for rec in report_lines_move:
+ if rec['report_type'] == 'accounts':
+ if rec['code'] in move_line_accounts:
+ rec['debit'] = move_lines_dict[rec['code']]['debit']
+ rec['credit'] = move_lines_dict[rec['code']]['credit']
+ rec['balance'] = move_lines_dict[rec['code']]['balance']
+
+ parent_list = list(set(parent_list))
+ max_level = 0
+ for rep in report_lines_move:
+ if rep['level'] > max_level:
+ max_level = rep['level']
+
+ def get_parents(obj):
+ for item in report_lines_move:
+ for each in obj:
+ if item['report_type'] != 'account_type' and \
+ each in item['c_ids']:
+ obj.append(item['r_id'])
+ if item['report_type'] == 'account_report':
+ obj.append(item['r_id'])
+ break
+
+ get_parents(parent_list)
+ for i in range(max_level):
+ get_parents(parent_list)
+
+ parent_list = list(set(parent_list))
+ final_report_lines = []
+
+ for rec in report_lines_move:
+ if rec['report_type'] != 'accounts':
+ if rec['r_id'] in parent_list:
+ final_report_lines.append(rec)
+ else:
+ final_report_lines.append(rec)
+
+ def filter_sum(obj):
+ sum_list = {}
+ for pl in parent_list:
+ sum_list[pl] = {}
+ sum_list[pl]['s_debit'] = 0
+ sum_list[pl]['s_credit'] = 0
+ sum_list[pl]['s_balance'] = 0
+
+ for each in obj:
+ if each['p_id'] and each['p_id'] in parent_list:
+ sum_list[each['p_id']]['s_debit'] += each['debit']
+ sum_list[each['p_id']]['s_credit'] += each['credit']
+ sum_list[each['p_id']]['s_balance'] += each['balance']
+ return sum_list
+
+ def assign_sum(obj):
+ for each in obj:
+ if each['r_id'] in parent_list and \
+ each['report_type'] != 'account_report':
+ each['debit'] = sum_list_new[each['r_id']]['s_debit']
+ each['credit'] = sum_list_new[each['r_id']]['s_credit']
+
+ for p in range(max_level):
+ sum_list_new = filter_sum(final_report_lines)
+ assign_sum(final_report_lines)
+
+ company_id = self.env.company
+ currency = company_id.currency_id
+ symbol = currency.symbol
+ rounding = currency.rounding
+ position = currency.position
+
+ for rec in final_report_lines:
+ rec['debit'] = round(rec['debit'], 2)
+ rec['credit'] = round(rec['credit'], 2)
+ rec['balance'] = rec['debit'] - rec['credit']
+ rec['balance'] = round(rec['balance'], 2)
+ if (rec['balance_cmp'] < 0 and rec['balance'] > 0) or (
+ rec['balance_cmp'] > 0 and rec['balance'] < 0):
+ rec['balance'] = rec['balance'] * -1
+
+ if position == "before":
+ rec['m_debit'] = symbol + " " + "{:,.2f}".format(rec['debit'])
+ rec['m_credit'] = symbol + " " + "{:,.2f}".format(rec['credit'])
+ rec['m_balance'] = symbol + " " + "{:,.2f}".format(
+ rec['balance'])
+ else:
+ rec['m_debit'] = "{:,.2f}".format(rec['debit']) + " " + symbol
+ rec['m_credit'] = "{:,.2f}".format(rec['credit']) + " " + symbol
+ rec['m_balance'] = "{:,.2f}".format(
+ rec['balance']) + " " + symbol
+
+ return {
+ 'name': tag,
+ 'type': 'ir.actions.client',
+ 'tag': tag,
+ 'filters': filters,
+ 'report_lines': records['Accounts'],
+ 'debit_total': records['debit_total'],
+ 'credit_total': records['credit_total'],
+ 'debit_balance': records['debit_balance'],
+ 'currency': currency,
+ 'bs_lines': final_report_lines,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(
+ data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('account_ids', []):
+ filters['accounts'] = self.env['account.account'].browse(
+ data.get('account_ids', [])).mapped('code')
+ else:
+ filters['accounts'] = ['All']
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ else:
+ filters['target_move'] = 'posted'
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ else:
+ filters['date_from'] = False
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+ else:
+ filters['date_to'] = False
+ if data.get('analytic_ids', []):
+ filters['analytics'] = self.env['account.analytic.account'].browse(
+ data.get('analytic_ids', [])).mapped('name')
+ else:
+ filters['analytics'] = ['All']
+
+ if data.get('account_tag_ids'):
+ filters['account_tags'] = self.env['account.account.tag'].browse(
+ data.get('account_tag_ids', [])).mapped('name')
+ else:
+ filters['account_tags'] = ['All']
+
+ if data.get('analytic_tag_ids', []):
+ filters['analytic_tags'] = self.env['account.analytic.tag'].browse(
+ data.get('analytic_tag_ids', [])).mapped('name')
+ else:
+ filters['analytic_tags'] = ['All']
+
+ filters['company_id'] = ''
+ filters['accounts_list'] = data.get('accounts_list')
+ filters['journals_list'] = data.get('journals_list')
+ filters['analytic_list'] = data.get('analytic_list')
+ filters['account_tag_list'] = data.get('account_tag_list')
+ filters['analytic_tag_list'] = data.get('analytic_tag_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['dynamic.balance.sheet.report'].search(
+ [('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = r.journal_ids if r.journal_ids else self.env[
+ 'account.journal'].search(company_domain)
+ analytics = self.analytic_ids if self.analytic_ids else self.env[
+ 'account.analytic.account'].search(
+ company_domain)
+ account_tags = self.account_tag_ids if self.account_tag_ids else \
+ self.env[
+ 'account.account.tag'].search([])
+ analytic_tags = self.analytic_tag_ids if self.analytic_tag_ids else \
+ self.env[
+ 'account.analytic.tag'].sudo().search(
+ ['|', ('company_id', '=', company_id.id),
+ ('company_id', '=', False)])
+
+ if r.account_tag_ids:
+ company_domain.append(
+ ('tag_ids', 'in', r.account_tag_ids.ids))
+
+ accounts = self.account_ids if self.account_ids else self.env[
+ 'account.account'].search(company_domain)
+ filter_dict = {
+ 'journal_ids': r.journal_ids.ids,
+ 'account_ids': r.account_ids.ids,
+ 'analytic_ids': r.analytic_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to': r.date_to,
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'accounts_list': [(a.id, a.name) for a in accounts],
+ 'analytic_list': [(anl.id, anl.name) for anl in analytics],
+ 'company_name': company_id and company_id.name,
+ 'analytic_tag_ids': r.analytic_tag_ids.ids,
+ 'analytic_tag_list': [(anltag.id, anltag.name) for anltag in
+ analytic_tags],
+ 'account_tag_ids': r.account_tag_ids.ids,
+ 'account_tag_list': [(a.id, a.name) for a in account_tags],
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data):
+ docs = data['model']
+ display_account = data['display_account']
+ init_balance = True
+ journals = data['journals']
+ accounts = self.env['account.account'].search([])
+ if not accounts:
+ raise UserError(_("No Accounts Found! Please Add One"))
+ account_res = self._get_accounts(accounts, init_balance,
+ display_account, data)
+ debit_total = 0
+ debit_total = sum(x['debit'] for x in account_res)
+ credit_total = sum(x['credit'] for x in account_res)
+ debit_balance = round(debit_total, 2) - round(credit_total, 2)
+ return {
+ 'doc_ids': self.ids,
+ 'debit_total': debit_total,
+ 'credit_total': credit_total,
+ 'debit_balance': debit_balance,
+ 'docs': docs,
+ 'time': time,
+ 'Accounts': account_res,
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(BalanceSheetView, self).create(vals)
+ return res
+
+ def write(self, vals):
+
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if not vals.get('journal_ids'):
+ vals.update({'journal_ids': [(5,)]})
+ if vals.get('account_ids'):
+ vals.update(
+ {'account_ids': [(4, j) for j in vals.get('account_ids')]})
+ if not vals.get('account_ids'):
+ vals.update({'account_ids': [(5,)]})
+ if vals.get('analytic_ids'):
+ vals.update(
+ {'analytic_ids': [(4, j) for j in vals.get('analytic_ids')]})
+ if not vals.get('analytic_ids'):
+ vals.update({'analytic_ids': [(5,)]})
+
+ if vals.get('account_tag_ids'):
+ vals.update({'account_tag_ids': [(4, j) for j in
+ vals.get('account_tag_ids')]})
+ if not vals.get('account_tag_ids'):
+ vals.update({'account_tag_ids': [(5,)]})
+
+ if vals.get('analytic_tag_ids'):
+ vals.update({'analytic_tag_ids': [(4, j) for j in
+ vals.get('analytic_tag_ids')]})
+ if not vals.get('analytic_tag_ids'):
+ vals.update({'analytic_tag_ids': [(5,)]})
+
+ res = super(BalanceSheetView, self).write(vals)
+ return res
+
+ def _get_accounts(self, accounts, init_balance, display_account, data):
+ cr = self.env.cr
+ MoveLine = self.env['account.move.line']
+ move_lines = {x: [] for x in accounts.ids}
+ currency_id = self.env.company.currency_id
+
+ # Prepare sql query base on selected parameters from wizard
+ tables, where_clause, where_params = MoveLine._query_get()
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ final_filters = " AND ".join(wheres)
+ final_filters = final_filters.replace('account_move_line__move_id',
+ 'm').replace(
+ 'account_move_line', 'l')
+ new_final_filter = final_filters
+
+ if data['target_move'] == 'posted':
+ new_final_filter += " AND m.state = 'posted'"
+ else:
+ new_final_filter += " AND m.state in ('draft','posted')"
+
+ if data.get('date_from'):
+ new_final_filter += " AND l.date >= '%s'" % data.get('date_from')
+ if data.get('date_to'):
+ new_final_filter += " AND l.date <= '%s'" % data.get('date_to')
+
+ if data['journals']:
+ new_final_filter += ' AND j.id IN %s' % str(
+ tuple(data['journals'].ids) + tuple([0]))
+
+ if data.get('accounts'):
+ WHERE = "WHERE l.account_id IN %s" % str(
+ tuple(data.get('accounts').ids) + tuple([0]))
+ else:
+ WHERE = "WHERE l.account_id IN %s"
+
+ if data['analytics']:
+ WHERE += ' AND anl.id IN %s' % str(
+ tuple(data.get('analytics').ids) + tuple([0]))
+
+ if data['analytic_tags']:
+ WHERE += ' AND anltag.account_analytic_tag_id IN %s' % str(
+ tuple(data.get('analytic_tags').ids) + tuple([0]))
+
+ # Get move lines base on sql query and Calculate the total balance of move lines
+ sql = ('''SELECT l.id AS lid,m.id AS move_id, l.account_id AS account_id,
+ l.date AS ldate, j.code AS lcode, l.currency_id, l.amount_currency, l.ref AS lref,
+ l.name AS lname, COALESCE(l.debit,0) AS debit, COALESCE(l.credit,0) AS credit,
+ COALESCE(SUM(l.balance),0) AS balance,\
+ m.name AS move_name, c.symbol AS currency_code,c.position AS currency_position, p.name AS partner_name\
+ FROM account_move_line l\
+ JOIN account_move m ON (l.move_id=m.id)\
+ LEFT JOIN res_currency c ON (l.currency_id=c.id)\
+ LEFT JOIN res_partner p ON (l.partner_id=p.id)\
+ LEFT JOIN account_analytic_account anl ON (l.analytic_account_id=anl.id)\
+ LEFT JOIN account_analytic_tag_account_move_line_rel anltag ON (anltag.account_move_line_id = l.id)\
+ JOIN account_journal j ON (l.journal_id=j.id)\
+ JOIN account_account acc ON (l.account_id = acc.id) '''
+ + WHERE + new_final_filter + ''' GROUP BY l.id, m.id, l.account_id, l.date, j.code, l.currency_id, l.amount_currency, l.ref, l.name, m.name, c.symbol, c.position, p.name''')
+ if data.get('accounts'):
+ params = tuple(where_params)
+ else:
+ params = (tuple(accounts.ids),) + tuple(where_params)
+ cr.execute(sql, params)
+
+ for row in cr.dictfetchall():
+ balance = 0
+ for line in move_lines.get(row['account_id']):
+ balance += round(line['debit'], 2) - round(line['credit'], 2)
+ row['balance'] += (round(balance, 2))
+ row['m_id'] = row['account_id']
+ move_lines[row.pop('account_id')].append(row)
+ # Calculate the debit, credit and balance for Accounts
+ account_res = []
+ for account in accounts:
+ currency = account.currency_id and account.currency_id or account.company_id.currency_id
+ res = dict((fn, 0.0) for fn in ['credit', 'debit', 'balance'])
+ res['code'] = account.code
+ res['name'] = account.name
+ res['id'] = account.id
+ res['move_lines'] = move_lines[account.id]
+ for line in res.get('move_lines'):
+ res['debit'] += round(line['debit'], 2)
+ res['credit'] += round(line['credit'], 2)
+ res['balance'] = round(line['balance'], 2)
+ if display_account == 'all':
+ account_res.append(res)
+ if display_account == 'movement' and res.get('move_lines'):
+ account_res.append(res)
+ if display_account == 'not_zero' and not currency.is_zero(
+ res['balance']):
+ account_res.append(res)
+
+ return account_res
+
+ @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
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, options, response, report_data, dfr_data):
+ i_data = str(report_data)
+ filters = json.loads(options)
+ j_data = dfr_data
+ rl_data = json.loads(j_data)
+
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+ sub_heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ side_heading_main = workbook.add_format(
+ {'align': 'left', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+
+ side_heading_sub = workbook.add_format(
+ {'align': 'left', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+
+ side_heading_sub.set_indent(1)
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_name = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_name_bold = workbook.add_format({'font_size': '10px', 'border': 1,
+ 'bold': True})
+ txt_name.set_indent(2)
+ txt_name_bold.set_indent(2)
+
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+
+ sheet.merge_range('A2:D3',
+ filters.get('company_name') + ' : ' + i_data,
+ head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+
+ date_head.set_align('vcenter')
+ date_head.set_text_wrap()
+ date_head.set_shrink()
+ date_head_left = workbook.add_format({'align': 'left', 'bold': True,
+ 'font_size': '10px'})
+
+ date_head_right = workbook.add_format({'align': 'right', 'bold': True,
+ 'font_size': '10px'})
+
+ date_head_left.set_indent(1)
+ date_head_right.set_indent(1)
+
+ if filters.get('date_from'):
+ sheet.merge_range('A4:B4', 'From: ' + filters.get('date_from'),
+ date_head_left)
+ if filters.get('date_to'):
+ sheet.merge_range('C4:D4', 'To: ' + filters.get('date_to'),
+ date_head_right)
+
+ sheet.merge_range('A5:D6', ' Accounts: ' + ', '.join(
+ [lt or '' for lt in
+ filters['accounts']]) + '; Journals: ' + ', '.join(
+ [lt or '' for lt in
+ filters['journals']]) + '; Account Tags: ' + ', '.join(
+ [lt or '' for lt in
+ filters['account_tags']]) + '; Analytic Tags: ' + ', '.join(
+ [lt or '' for lt in
+ filters['analytic_tags']]) + '; Analytic: ' + ', '.join(
+ [at or '' for at in
+ filters['analytics']]) + '; Target Moves: ' + filters.get(
+ 'target_move').capitalize(), date_head)
+
+ sheet.set_column(0, 0, 30)
+ sheet.set_column(1, 1, 20)
+ sheet.set_column(2, 2, 15)
+ sheet.set_column(3, 3, 15)
+
+ row = 5
+ col = 0
+
+ row += 2
+ sheet.write(row, col, '', sub_heading)
+ sheet.write(row, col + 1, 'Debit', sub_heading)
+ sheet.write(row, col + 2, 'Credit', sub_heading)
+ sheet.write(row, col + 3, 'Balance', sub_heading)
+
+ if rl_data:
+ for fr in rl_data:
+
+ row += 1
+ if fr['level'] == 1:
+ sheet.write(row, col, fr['name'], side_heading_main)
+ elif fr['level'] == 2:
+ sheet.write(row, col, fr['name'], side_heading_sub)
+ else:
+ sheet.write(row, col, fr['name'], txt_name)
+ sheet.write(row, col + 1, fr['debit'], txt)
+ sheet.write(row, col + 2, fr['credit'], txt)
+ sheet.write(row, col + 3, fr['balance'], txt)
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/dynamic_accounts_report/wizard/balance_sheet_config.py b/dynamic_accounts_report/wizard/balance_sheet_config.py
new file mode 100644
index 0000000..6643ad2
--- /dev/null
+++ b/dynamic_accounts_report/wizard/balance_sheet_config.py
@@ -0,0 +1,305 @@
+import re
+from odoo import models, fields, api
+
+
+class BalanceSheet(models.TransientModel):
+ _inherit = "dynamic.balance.sheet.report"
+
+ def view_report_pdf(self, acc, form):
+ data = dict()
+ report_lines = acc
+ data['form'] = 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']
+ item_id = item['id']
+ report_id = item['r_id']
+ else:
+ item['level'] = set_report_level(item)
+ data['journal_items'] = journal_items
+ data['report_lines'] = report_lines
+
+ return 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([
+ ('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 = data['account_report_id']
+ 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
+
+ child_ids = []
+ for chd in report.children_ids:
+ child_ids.append(chd.id)
+
+ vals = {
+ 'r_id': report.id,
+ 'p_id': report.parent_id.id,
+ 'report_type': report.type,
+ 'c_ids': child_ids,
+ '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,
+ 'is_present': 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 = {
+ 'r_id': False,
+ 'p_id': report.id,
+ 'report_type': 'accounts',
+ 'c_ids': [],
+ 'account': account.id,
+ 'code': account.code,
+ '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.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
+
+ 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
+
+
+
+
+
+
diff --git a/dynamic_accounts_report/wizard/cash_flow.py b/dynamic_accounts_report/wizard/cash_flow.py
new file mode 100644
index 0000000..021ca3f
--- /dev/null
+++ b/dynamic_accounts_report/wizard/cash_flow.py
@@ -0,0 +1,604 @@
+import time
+from datetime import datetime
+
+from odoo import models, api, fields
+FETCH_RANGE = 2000
+import io
+import json
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+year = datetime.now().year
+
+
+class AccountCasgFlow(models.TransientModel):
+ _name = "account.cash.flow"
+ _inherit = "account.common.report"
+
+ date_from = fields.Date(string="Start Date", default=str(year)+'-01-01')
+ date_to = fields.Date(string="End Date", default=fields.Date.today)
+ today = fields.Date("Report Date", default=fields.Date.today)
+ levels = fields.Selection([('summary', 'Summary'),
+ ('consolidated', 'Consolidated'),
+ ('detailed', 'Detailed'),
+ ('very', 'Very Detailed')],
+ string='Levels', required=True, default='summary',
+ help='Different levels for cash flow statements \n'
+ 'Summary: Month wise report.\n'
+ 'Consolidated: Based on account types.\n'
+ 'Detailed: Based on accounts.\n'
+ 'Very Detailed: Accounts with their move lines')
+
+ account_ids = fields.Many2many(
+ "account.account",
+ string="Accounts",
+ )
+
+ @api.model
+ def view_report(self, option):
+ r = self.env['account.cash.flow'].search([('id', '=', option[0])])
+ data = {
+ 'model': self,
+ 'journals': r.journal_ids,
+ 'target_move': r.target_move,
+ 'levels': r.levels,
+ }
+ if r.date_from:
+ data.update({
+ 'date_from': r.date_from,
+ })
+ if r.date_to:
+ data.update({
+ 'date_to': r.date_to,
+ })
+
+ filters = self.get_filter(option)
+ report_lines = self._get_report_values(data, option)
+ fetched_data = report_lines['fetched_data']
+ fetched = report_lines['fetched']
+ account_res = report_lines['account_res']
+ journal_res = report_lines['journal_res']
+ levels = report_lines['levels']
+ currency = self._get_currency()
+
+ return {
+ 'name': "Cash Flow Statements",
+ 'type': 'ir.actions.client',
+ 'tag': 'c_f',
+ 'report_lines': report_lines,
+ 'fetched_data': fetched_data,
+ 'fetched': fetched,
+ 'account_res': account_res,
+ 'journal_res': journal_res,
+ 'levels': r.levels,
+ 'filters': filters,
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('account_ids', []):
+ filters['accounts'] = self.env['account.account'].browse(data.get('account_ids', [])).mapped('code')
+ else:
+ filters['accounts'] = ['All']
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+ if data.get('levels'):
+ filters['levels'] = data.get('levels')
+
+ filters['company_id'] = ''
+ filters['accounts_list'] = data.get('accounts_list')
+ filters['journals_list'] = data.get('journals_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.cash.flow'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = r.journal_ids if r.journal_ids else self.env['account.journal'].search(company_domain)
+ accounts = self.account_ids if self.account_ids else self.env['account.account'].search(company_domain)
+
+ filter_dict = {
+ 'journal_ids': r.journal_ids.ids,
+ 'account_ids': self.account_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to': r.date_to,
+ 'levels': r.levels,
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'accounts_list': [(a.id, a.name) for a in accounts],
+ 'company_name': company_id and company_id.name,
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data, option):
+ cr = self.env.cr
+ data = self.get_filter(option)
+ company_id = self.env.company
+ currency = company_id.currency_id
+ symbol = company_id.currency_id.symbol
+ rounding = company_id.currency_id.rounding
+ position = company_id.currency_id.position
+
+ fetched_data = []
+ account_res = []
+ journal_res = []
+ fetched = []
+
+ account_type_id = self.env.ref('account.data_account_type_liquidity').id
+ model = self.env.context.get('active_model')
+ if data.get('levels') == 'summary':
+ state = """ WHERE am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ query3 = """SELECT to_char(am.date, 'Month') as month_part, extract(YEAR from am.date) as year_part,
+ sum(aml.debit) AS total_debit, sum(aml.credit) AS total_credit,
+ sum(aml.balance) AS total_balance FROM (SELECT am.date, am.id, am.state FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' ) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ """ + state + """GROUP BY month_part,year_part"""
+ cr = self._cr
+ cr.execute(query3)
+ fetched_data = cr.dictfetchall()
+ elif data.get('date_from') is False:
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get(
+ 'target_move') == 'posted' else ''
+ sql = """SELECT DISTINCT aa.id, aa.name,aa.code, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit,sum(aml.balance) AS total_balance
+ FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ GROUP BY aa.name, aa.code,aa.id"""
+ cr = self._cr
+ cr.execute(sql)
+ fetched_data = cr.dictfetchall()
+ elif data.get('date_from') is False and data.get('date_from') != False:
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get(
+ 'target_move') == 'posted' else ''
+ sql = """SELECT DISTINCT aa.id, aa.name,aa.code, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit,sum(aml.balance) AS total_balance
+ FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ GROUP BY aa.name, aa.code,aa.id"""
+ cr = self._cr
+ cr.execute(sql)
+ fetched_data = cr.dictfetchall()
+ elif data.get('date_from') is False and data.get('date_from') != False:
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get(
+ 'target_move') == 'posted' else ''
+ sql = """SELECT DISTINCT aa.id, aa.name,aa.code, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit,sum(aml.balance) AS total_balance
+ FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ GROUP BY aa.name, aa.code,aa.id"""
+ cr = self._cr
+ cr.execute(sql)
+ fetched_data = cr.dictfetchall()
+
+ elif data.get('date_to') == " ":
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get(
+ 'target_move') == 'posted' else ''
+ sql = """SELECT DISTINCT aa.id, aa.name,aa.code, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit,sum(aml.balance) AS total_balance
+ FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ GROUP BY aa.name, aa.code,aa.id"""
+ cr = self._cr
+ cr.execute(sql)
+ fetched_data = cr.dictfetchall()
+
+ elif data.get('levels') == 'consolidated':
+ state = """ WHERE am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ query2 = """SELECT aat.name, sum(aml.debit) AS total_debit, sum(aml.credit) AS total_credit,
+ sum(aml.balance) AS total_balance FROM ( SELECT am.id, am.state FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' ) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ """ + state + """GROUP BY aat.name"""
+ cr = self._cr
+ cr.execute(query2)
+ fetched_data = cr.dictfetchall()
+ elif data.get('levels') == 'detailed':
+ state = """ WHERE am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ query1 = """SELECT aa.id,aa.name,aa.code, sum(aml.debit) AS total_debit, sum(aml.credit) AS total_credit,
+ sum(aml.balance) AS total_balance FROM (SELECT am.id, am.state FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' ) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ """ + state + """GROUP BY aa.name, aa.code, aa.id"""
+ cr = self._cr
+ cr.execute(query1)
+ fetched_data = cr.dictfetchall()
+ for account in self.env['account.account'].search([]):
+ child_lines = self.get_journal_lines(account, data)
+ if child_lines:
+ journal_res.append(child_lines)
+
+ else:
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ sql = """SELECT DISTINCT aa.id, aa.name,aa.code, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit,sum(aml.balance) AS total_balance
+ FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ GROUP BY aa.name, aa.code,aa.id"""
+ cr = self._cr
+ cr.execute(sql)
+ fetched_data = cr.dictfetchall()
+ for account in self.env['account.account'].search([]):
+ child_lines = self._get_lines(account, data)
+ if child_lines:
+ account_res.append(child_lines)
+ journals = self.get_journal_lines(account, data)
+ if journals:
+ journal_res.append(journals)
+
+ return {
+ 'date_from': data.get('date_from'),
+ 'date_to': data.get('date_to'),
+ 'levels': data.get('level'),
+ 'doc_ids': self.ids,
+ 'doc_model': model,
+ 'fetched_data': fetched_data,
+ 'account_res': account_res,
+ 'journal_res': journal_res,
+ 'fetched': fetched,
+ 'company_currency_id': currency,
+ 'company_currency_symbol': symbol,
+ 'company_currency_position': position,
+ }
+
+ def _get_lines(self, account, data):
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ state = """AND am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ query = """SELECT aml.account_id,aj.id as j_id,aj.name,am.id, am.name as move_name, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit, COALESCE(SUM(aml.debit - aml.credit),0) AS balance FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_journal aj ON aj.id = am.journal_id
+ WHERE aa.id = """ + str(account.id) + """
+ GROUP BY am.name, aml.account_id, aj.id, aj.name, am.id"""
+
+ cr = self._cr
+ cr.execute(query)
+ fetched_data = cr.dictfetchall()
+
+ sql2 = """SELECT aa.name as account_name,aa.id as account_id, aj.id, aj.name, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit, sum(aml.balance) AS total_balance FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_journal aj ON aj.id = am.journal_id
+ WHERE aa.id = """ + str(
+ account.id) + """
+ GROUP BY aa.name, aj.name, aj.id,aa.id"""
+
+ cr = self._cr
+ cr.execute(sql2)
+ fetch_data = cr.dictfetchall()
+ if fetched_data:
+ return {
+ 'account': account.name,
+ 'id': account.id,
+ 'code': account.code,
+ 'move_lines': fetched_data,
+ 'journal_lines': fetch_data,
+ }
+
+
+ def get_journal_lines(self, account, data, offset=0, fetch_range=FETCH_RANGE):
+ account_type_id = self.env.ref(
+ 'account.data_account_type_liquidity').id
+ offset_count = offset * fetch_range
+ state = """AND am.state = 'posted' """ if data.get('target_move') == 'posted' else ''
+ sql2 = """SELECT aa.name as account_name, aj.name, sum(aml.debit) AS total_debit,
+ sum(aml.credit) AS total_credit, COALESCE(SUM(aml.debit - aml.credit),0) AS balance FROM (SELECT am.* FROM account_move as am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_account_type aat ON aat.id = aa.user_type_id
+ WHERE am.date BETWEEN '""" + str(
+ data.get('date_from')) + """' and '""" + str(
+ data.get('date_to')) + """' AND aat.id='""" + str(
+ account_type_id) + """' """ + state + """) am
+ LEFT JOIN account_move_line aml ON aml.move_id = am.id
+ LEFT JOIN account_account aa ON aa.id = aml.account_id
+ LEFT JOIN account_journal aj ON aj.id = am.journal_id
+ WHERE aa.id = """ + str(account.id) + """
+ GROUP BY aa.name, aj.name"""
+
+ cr = self._cr
+ cr.execute(sql2)
+ fetched_data = cr.dictfetchall()
+ if fetched_data:
+ return {
+ 'account': account.name,
+ 'id': account.id,
+ 'journal_lines': fetched_data,
+ 'offset': offset_count,
+ }
+
+
+
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(AccountCasgFlow, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if vals.get('journal_ids') == []:
+ vals.update({'journal_ids': [(5,)]})
+ if vals.get('account_ids'):
+ vals.update({'account_ids': [(4, j) for j in vals.get('account_ids')]})
+ if vals.get('account_ids') == []:
+ vals.update({'account_ids': [(5,)]})
+
+ res = super(AccountCasgFlow, self).write(vals)
+ return res
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position, lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response, report_data, dfr_data):
+ report_main_data = json.loads(dfr_data)
+ data = json.loads(data)
+ report_data = report_main_data.get('report_lines')
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ fetched_data = report_data.get('fetched_data')
+ account_res = report_data.get('account_res')
+ journal_res = report_data.get('journal_res')
+ fetched = report_data.get('fetched')
+ account_type_id = self.env.ref('account.data_account_type_liquidity').id
+ currency_symbol = self.env.company.currency_id.symbol
+
+
+ logged_users = self.env['res.company']._company_default_get('account.account')
+ sheet = workbook.add_worksheet()
+ bold = workbook.add_format({'align': 'center',
+ 'bold': True,
+ 'font_size': '10px',
+ 'border': 1})
+ date = workbook.add_format({'font_size': '10px'})
+ cell_format = workbook.add_format({'bold': True,
+ 'font_size': '10px'})
+ head = workbook.add_format({'align': 'center',
+ 'bold': True,
+ 'bg_color': '#D3D3D3',
+ 'font_size': '15px'})
+ txt = workbook.add_format({'align': 'left',
+ 'font_size': '10px'})
+ txt_left = workbook.add_format({'align': 'left',
+ 'font_size': '10px',
+ 'border': 1})
+ txt_center = workbook.add_format({'align': 'center',
+ 'font_size': '10px',
+ 'border': 1})
+ amount = workbook.add_format({'align': 'right',
+ 'font_size': '10px',
+ 'border': 1})
+ amount_bold = workbook.add_format({'align': 'right',
+ 'bold': True,
+ 'font_size': '10px',
+ 'border': 1})
+ txt_bold = workbook.add_format({'align': 'left',
+ 'bold': True,
+ 'font_size': '10px',
+ 'border': 1})
+
+ sheet.set_column('C:C', 30, cell_format)
+ sheet.set_column('D:E', 20, cell_format)
+ sheet.set_column('F:F', 20, cell_format)
+ sheet.merge_range('C3:F5', '')
+ sheet.merge_range('C3:F4', 'CASH FLOW STATEMENTS', head)
+ sheet.merge_range('C4:F4', '')
+
+ sheet.write('C6', "Date From", cell_format)
+ sheet.write('D6', str(data['date_from']), date)
+ sheet.write('E6', "Date To", cell_format)
+ sheet.write('F6', str(data['date_to']), date)
+ if data.get('levels'):
+ sheet.write('C7', "Level", cell_format)
+ sheet.write('D7', data.get("levels"), date)
+ sheet.write('E7', "Target Moves", cell_format)
+ sheet.write('F7', data.get("target_move"), date)
+ sheet.write('C9', 'NAME', bold)
+ sheet.write('D9', 'CASH IN', bold)
+ sheet.write('E9', 'CASH OUT', bold)
+ sheet.write('F9', 'BALANCE', bold)
+
+ row_num = 9
+ col_num = 2
+ fetched_data_list = fetched_data
+ account_res_list = account_res
+ journal_res_list = journal_res
+ fetched_list = fetched
+
+ for i_rec in fetched_data_list:
+ if data['levels'] == 'summary':
+ sheet.write(row_num + 1, col_num, str(i_rec['month_part']) + str(int(i_rec['year_part'])), txt_left)
+ sheet.write(row_num + 1, col_num + 1, str(i_rec['total_debit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 2, str(i_rec['total_credit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 3,
+ str(i_rec['total_debit'] - i_rec['total_credit']) + str(currency_symbol),
+ amount)
+ row_num = row_num + 1
+ elif data['levels'] == 'consolidated':
+ sheet.write(row_num + 1, col_num, i_rec['name'], txt_left)
+ sheet.write(row_num + 1, col_num + 1, str(i_rec['total_debit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 2, str(i_rec['total_credit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 3,
+ str(i_rec['total_debit'] - i_rec['total_credit']) + str(currency_symbol),
+ amount)
+ row_num = row_num + 1
+
+ for j_rec in journal_res_list:
+ if data['levels'] == 'detailed':
+ for k in fetched_data_list:
+ if k['name'] == j_rec['account']:
+ sheet.write(row_num + 1, col_num, str(k['code']) + str(k['name']), txt_bold)
+ sheet.write(row_num + 1, col_num + 1, str(k['total_debit']) + str(currency_symbol), amount_bold)
+ sheet.write(row_num + 1, col_num + 2, str(k['total_credit']) + str(currency_symbol), amount_bold)
+ sheet.write(row_num + 1, col_num + 3,
+ str(k['total_debit'] - k['total_credit']) + str(currency_symbol), amount_bold)
+ row_num = row_num + 1
+ for l_jrec in j_rec['journal_lines']:
+ sheet.write(row_num + 1, col_num, l_jrec['name'], txt_left)
+ sheet.write(row_num + 1, col_num + 1, str(l_jrec['total_debit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 2, str(l_jrec['total_credit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 3,
+ str(l_jrec['total_debit'] - l_jrec['total_credit']) + str(currency_symbol),
+ amount)
+ row_num = row_num + 1
+
+ for j_rec in account_res_list:
+ if data['levels'] == 'very':
+ for k in fetched_data_list:
+ if k['name'] == j_rec['account']:
+ sheet.write(row_num + 1, col_num, str(k['code']) + str(k['name']), txt_bold)
+ sheet.write(row_num + 1, col_num + 1, str(k['total_debit']) + str(currency_symbol), amount_bold)
+ sheet.write(row_num + 1, col_num + 2, str(k['total_credit']) + str(currency_symbol), amount_bold)
+ sheet.write(row_num + 1, col_num + 3,
+ str(k['total_debit'] - k['total_credit']) + str(currency_symbol), amount_bold)
+ row_num = row_num + 1
+ for l_jrec in j_rec['journal_lines']:
+ if l_jrec['account_name'] == j_rec['account']:
+ sheet.write(row_num + 1, col_num, l_jrec['name'], txt_left)
+ sheet.write(row_num + 1, col_num + 1, str(l_jrec['total_debit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 2, str(l_jrec['total_credit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 3,
+ str(l_jrec['total_debit'] - l_jrec['total_credit']) + str(currency_symbol),
+ amount)
+ row_num = row_num + 1
+ for m_rec in j_rec['move_lines']:
+ if m_rec['name'] == l_jrec['name']:
+ sheet.write(row_num + 1, col_num, m_rec['move_name'], txt_center)
+ sheet.write(row_num + 1, col_num + 1, str(m_rec['total_debit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 2, str(m_rec['total_credit']) + str(currency_symbol), amount)
+ sheet.write(row_num + 1, col_num + 3,
+ str(m_rec['total_debit'] - m_rec['total_credit']) + str(currency_symbol),
+ amount)
+ row_num = row_num + 1
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/dynamic_accounts_report/wizard/daybook.py b/dynamic_accounts_report/wizard/daybook.py
new file mode 100644
index 0000000..90aa199
--- /dev/null
+++ b/dynamic_accounts_report/wizard/daybook.py
@@ -0,0 +1,320 @@
+import time
+from datetime import date
+from datetime import timedelta, datetime
+from odoo import fields, models, api, _
+import io
+import json
+from odoo.exceptions import AccessError, UserError, AccessDenied
+
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class AgeingView(models.TransientModel):
+ _name = 'account.day.book'
+
+ 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([]))
+
+ account_ids = fields.Many2many('account.account',
+ required=True, string='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)
+
+ target_move = fields.Selection([('posted', 'All Posted Entries'),
+ ('all', 'All Entries')],
+ string='Target Moves', required=True,
+ default='posted')
+
+ @api.model
+ def view_report(self, option):
+ r = self.env['account.day.book'].search([('id', '=', option[0])])
+ data = {}
+ data['ids'] = self.env.context.get('active_ids', [])
+ data['model'] = self.env.context.get('active_model', 'ir.ui.menu')
+ data['form'] = \
+ r.read(['date_from', 'date_to', 'journal_ids', 'target_move',
+ 'account_ids'])[0]
+ filters = self.get_filter(option)
+ records = self._get_report_values(data)
+ currency = self._get_currency()
+ return {
+ 'name': "Day Book",
+ 'type': 'ir.actions.client',
+ 'tag': 'd_b',
+ 'filters': filters,
+ 'report_lines': records['Accounts'],
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(
+ data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('account_ids', []):
+ filters['accounts'] = self.env['account.account'].browse(
+ data.get('account_ids', [])).mapped('code')
+ else:
+ filters['accounts'] = ['All']
+ filters['company_id'] = ''
+ filters['accounts_list'] = data.get('accounts_list')
+ filters['journals_list'] = data.get('journals_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.day.book'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = self.journal_ids if self.journal_ids else self.env[
+ 'account.journal'].search(company_domain)
+ accounts = self.account_ids if self.account_ids else self.env[
+ 'account.account'].search(company_domain)
+
+ filter_dict = {
+ 'journal_ids': self.journal_ids.ids,
+ 'account_ids': self.account_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to':r.date_to,
+
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'accounts_list': [(a.id, a.name) for a in accounts],
+
+ 'company_name': company_id and company_id.name,
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data=None):
+ form_data = data['form']
+ active_acc = data['form']['account_ids']
+ accounts = self.env['account.account'].search(
+ [('id', 'in', active_acc)]) if data['form']['account_ids'] else \
+ self.env['account.account'].search([])
+ if not accounts:
+ raise UserError(_("No Accounts Found! Please Add One"))
+ active_jrnl = data['form']['journal_ids']
+ journals = self.env['account.journal'].search(
+ [('id', 'in', active_jrnl)]) if data['form']['journal_ids'] else \
+ self.env['account.journal'].search([])
+ if not journals:
+ raise UserError(_("No journals Found!"))
+
+
+ date_start = datetime.strptime(str(form_data['date_from']),
+ '%Y-%m-%d').date()
+ date_end = datetime.strptime(str(form_data['date_to']), '%Y-%m-%d').date()
+ days = date_end - date_start
+ dates = []
+ record = []
+ for i in range(days.days + 1):
+ dates.append(date_start + timedelta(days=i))
+ for head in dates:
+ pass_date = str(head)
+ accounts_res = self._get_account_move_entry(
+ accounts, form_data,journals, pass_date)
+ if accounts_res['lines']:
+ record.append({
+ 'date': head,
+ 'debit': accounts_res['debit'],
+ 'credit': accounts_res['credit'],
+ 'balance': accounts_res['balance'],
+ 'child_lines': accounts_res['lines'],
+ 'id': accounts_res['move_id'],
+ })
+ return {
+ 'doc_ids': self.ids,
+ 'time': time,
+ 'Accounts': record,
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(AgeingView, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if vals.get('journal_ids') == []:
+ vals.update({'journal_ids': [(5,)]})
+ if vals.get('account_ids'):
+ vals.update(
+ {'account_ids': [(4, j) for j in vals.get('account_ids')]})
+ if vals.get('account_ids') == []:
+ vals.update({'account_ids': [(5,)]})
+ res = super(AgeingView, self).write(vals)
+ return res
+
+ def _get_account_move_entry(self, accounts, form_data,journals, pass_date):
+ cr = self.env.cr
+ move_line = self.env['account.move.line']
+ tables, where_clause, where_params = move_line._query_get()
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ if form_data['target_move'] == 'posted':
+ target_move = "AND m.state = 'posted'"
+ else:
+ target_move = ''
+ sql = ('''
+ SELECT l.id AS lid,m.id AS move_id, acc.name as accname, l.account_id AS account_id, l.date AS ldate, j.code AS lcode, l.currency_id,
+ l.amount_currency, l.ref AS lref, l.name AS lname, COALESCE(l.debit,0) AS debit, COALESCE(l.credit,0) AS credit,
+ COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) AS balance,
+ m.name AS move_name, c.symbol AS currency_code, p.name AS partner_name
+ FROM account_move_line l
+ JOIN account_move m ON (l.move_id=m.id)
+ LEFT JOIN res_currency c ON (l.currency_id=c.id)
+ LEFT JOIN res_partner p ON (l.partner_id=p.id)
+ JOIN account_journal j ON (l.journal_id=j.id)
+ JOIN account_account acc ON (l.account_id = acc.id)
+ WHERE l.account_id IN %s AND l.journal_id IN %s ''' + target_move + ''' AND l.date = %s
+ GROUP BY l.id,m.id, l.account_id, l.date,
+ j.code, l.currency_id, l.amount_currency, l.ref, l.name, m.name, c.symbol, p.name , acc.name
+ ORDER BY l.date DESC
+ ''')
+ params = (
+ tuple(accounts.ids), tuple(journals.ids), pass_date)
+ cr.execute(sql, params)
+ data = cr.dictfetchall()
+
+ res = {}
+ debit = credit = balance = 0.00
+ id = ''
+ for line in data:
+ debit += line['debit']
+ credit += line['credit']
+ balance += line['balance']
+ id = line['move_id']
+ res['debit'] = debit
+ res['credit'] = credit
+ res['balance'] = balance
+ res['lines'] = data
+ res['move_id'] = id
+ return res
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position, lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response, report_data, dfr_data):
+ report_data_main = json.loads(report_data)
+ output = io.BytesIO()
+ filters = json.loads(data)
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+ sub_heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_l = workbook.add_format(
+ {'font_size': '10px', 'border': 1, 'bold': True})
+ sheet.merge_range('A2:D3',
+ filters.get('company_name') + ':' + ' Day Book',
+ head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+ date_style = workbook.add_format({'align': 'center',
+ 'font_size': '10px'})
+ if filters.get('date_from'):
+ sheet.merge_range('A4:B4', 'From: ' + filters.get('date_from'),
+ date_head)
+ if filters.get('date_to'):
+ sheet.merge_range('C4:D4', 'To: ' + filters.get('date_to'),
+ date_head)
+ sheet.write('A5', 'Journals: ' + ', '.join([lt or '' for lt in
+ filters[
+ 'journals']]),
+ date_head)
+
+ sheet.merge_range('E4:F4',
+ 'Target Moves: ' + filters.get('target_move'),
+ date_head)
+ sheet.merge_range('B5:D5',
+ 'Account Type: ' + ', '.join([lt or '' for lt in
+ filters[
+ 'accounts']]),
+ date_head)
+
+ sheet.merge_range('A7:E7', 'Date', sub_heading)
+ sheet.write('F7', 'Debit', sub_heading)
+ sheet.write('G7', 'Credit', sub_heading)
+ sheet.write('H7', 'Balance', sub_heading)
+
+ row = 6
+ col = 0
+ sheet.set_column(4, 0, 15)
+ sheet.set_column(5, 0, 15)
+ sheet.set_column(6, 1, 15)
+ sheet.set_column(7, 2, 15)
+ sheet.set_column(8, 3, 15)
+ sheet.set_column(9, 4, 15)
+ sheet.set_column(10, 5, 15)
+ sheet.set_column(11, 6, 15)
+ for rec_data in report_data_main:
+ one_lst = []
+ two_lst = []
+ row += 1
+ sheet.merge_range(row, col, row, col + 4, rec_data['date'], txt_l)
+ sheet.write(row, col + 5, rec_data['debit'], txt_l)
+ sheet.write(row, col + 6, rec_data['credit'], txt_l)
+ sheet.write(row, col + 7, rec_data['balance'], txt_l)
+ for line_data in rec_data['child_lines']:
+ row += 1
+ sheet.write(row, col, line_data.get('ldate'), txt)
+ sheet.write(row, col + 1, line_data.get('lcode'), txt)
+ sheet.write(row, col + 2, line_data.get('partner_name'),
+ txt)
+ sheet.write(row, col + 3, line_data.get('move_name'), txt)
+ sheet.write(row, col + 4, line_data.get('lname'), txt)
+ sheet.write(row, col + 5, line_data.get('debit'), txt)
+ sheet.write(row, col + 6, line_data.get('credit'), txt)
+ sheet.write(row, col + 7, line_data.get('balance'), txt)
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close()
diff --git a/dynamic_accounts_report/wizard/general_ledger.py b/dynamic_accounts_report/wizard/general_ledger.py
new file mode 100644
index 0000000..cb994b3
--- /dev/null
+++ b/dynamic_accounts_report/wizard/general_ledger.py
@@ -0,0 +1,477 @@
+import time
+from odoo import fields, models, api, _
+
+import io
+import json
+from odoo.exceptions import AccessError, UserError, AccessDenied
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class GeneralView(models.TransientModel):
+ _inherit = "account.common.report"
+ _name = 'account.general.ledger'
+
+ journal_ids = fields.Many2many('account.journal',
+
+ string='Journals', required=True,
+ default=[])
+ account_ids = fields.Many2many(
+ "account.account",
+ string="Accounts",
+ )
+ account_tag_ids = fields.Many2many("account.account.tag", string="Account Tags")
+
+ analytic_ids = fields.Many2many(
+ "account.analytic.account", string="Analytic Accounts"
+ )
+ analytic_tag_ids = fields.Many2many("account.analytic.tag", string="Analytic Tags")
+
+ 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')
+ titles = fields.Char('Title')
+ target_move = fields.Selection([('posted', 'All Posted Entries'),
+ ('all', 'All Entries')],
+ string='Target Moves', required=True)
+
+ @api.model
+ def view_report(self, option, title):
+ r = self.env['account.general.ledger'].search([('id', '=', option[0])])
+ new_title = ''
+ journals = r.journal_ids
+ if title == 'General Ledger':
+ journals = r.journal_ids
+ new_title = 'General Ledger'
+ if title == 'Bank Book':
+ journals = self.env['account.journal'].search([('type', '=', 'bank')],
+ limit=1)
+ new_title = 'Bank Book'
+ if title == 'Cash Book':
+ journals = self.env['account.journal'].search([('type', '=', 'cash')],
+ limit=1)
+ new_title = 'Cash Book'
+ r.write({
+ 'titles': new_title,
+ })
+ data = {
+ 'display_account': r.display_account,
+ 'model':self,
+ 'journals': journals,
+ 'target_move': r.target_move,
+ 'accounts': r.account_ids,
+ 'account_tags': r.account_tag_ids,
+ 'analytics': r.analytic_ids,
+ 'analytic_tags': r.analytic_tag_ids,
+
+ }
+ if r.date_from:
+ data.update({
+ 'date_from': r.date_from,
+ })
+ if r.date_to:
+ data.update({
+ 'date_to': r.date_to,
+ })
+
+ filters = self.get_filter(option)
+ records = self._get_report_values(data)
+ currency = self._get_currency()
+ return {
+ 'name': new_title,
+ 'type': 'ir.actions.client',
+ 'tag': 'g_l',
+ 'filters': filters,
+ 'report_lines': records['Accounts'],
+ 'debit_total': records['debit_total'],
+ 'credit_total': records['credit_total'],
+ 'debit_balance': records['debit_balance'],
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('account_ids', []):
+ filters['accounts'] = self.env['account.account'].browse(data.get('account_ids', [])).mapped('code')
+ else:
+ filters['accounts'] = ['All']
+ if data.get('account_tag_ids', []):
+ filters['account_tags'] = data.get('account_tag_ids')
+ else:
+ filters['account_tags'] = ['All']
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+ if data.get('analytic_ids', []):
+ filters['analytics'] = self.env['account.analytic.account'].browse(
+ data.get('analytic_ids', [])).mapped('name')
+ else:
+ filters['analytics'] = ['All']
+ if data.get('analytic_tag_ids', []):
+ filters['account_tags'] = self.env['account.account.tag'].browse(
+ data.get('account_tag_ids', [])).mapped('name')
+ else:
+ filters['analytic_tags'] = ['All']
+
+ filters['company_id'] = ''
+ filters['accounts_list'] = data.get('accounts_list')
+ filters['account_tag_list'] = data.get('account_tag_list')
+ filters['journals_list'] = data.get('journals_list')
+ filters['analytic_list'] = data.get('analytic_list')
+ filters['analytic_tag_list'] = data.get('analytic_tag_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.general.ledger'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = r.journal_ids if r.journal_ids else self.env['account.journal'].search(company_domain)
+ accounts = self.account_ids if self.account_ids else self.env['account.account'].search(company_domain)
+ account_tags = r.account_tag_ids if r.account_tag_ids else self.env[
+ 'account.account.tag'].search([])
+ analytics = r.analytic_ids if r.analytic_ids else self.env['account.analytic.account'].search(
+ company_domain)
+ analytic_tags = r.analytic_tag_ids if r.analytic_tag_ids else self.env[
+ 'account.analytic.tag'].search([])
+ filter_dict = {
+ 'journal_ids': r.journal_ids.ids,
+ 'analytic_ids': r.analytic_ids.ids,
+ 'analytic_tag_ids': r.analytic_tag_ids.ids,
+ 'account_ids': r.account_ids.ids,
+ 'account_tag_ids': r.account_tag_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to': r.date_to,
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'accounts_list': [(a.id, a.name) for a in accounts],
+ 'account_tag_list': [(a.id, a.name) for a in account_tags],
+ 'analytic_list': [(anl.id, anl.name) for anl in analytics],
+ 'analytic_tag_list': [(anltag.id, anltag.name) for anltag in analytic_tags],
+ 'company_name': company_id and company_id.name,
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data):
+ docs = data['model']
+ display_account = data['display_account']
+ init_balance = True
+ journals = data['journals']
+ accounts = self.env['account.account'].search([])
+ if not accounts:
+ raise UserError(_("No Accounts Found! Please Add One"))
+ account_res = self._get_accounts(accounts, init_balance, display_account, data)
+ debit_total = 0
+ debit_total = sum(x['debit'] for x in account_res)
+ credit_total = sum(x['credit'] for x in account_res)
+ debit_balance = round(debit_total,2) - round(credit_total,2)
+ return {
+ 'doc_ids': self.ids,
+ 'debit_total': debit_total,
+ 'credit_total': credit_total,
+ 'debit_balance':debit_balance,
+ 'docs': docs,
+ 'time': time,
+ 'Accounts': account_res,
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(GeneralView, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if vals.get('journal_ids') == []:
+ vals.update({'journal_ids': [(5,)]})
+ if vals.get('account_ids'):
+ vals.update({'account_ids': [(4, j) for j in vals.get('account_ids')]})
+ if vals.get('account_ids') == []:
+ vals.update({'account_ids': [(5,)]})
+ if vals.get('account_tag_ids'):
+ vals.update({'account_tag_ids': [(4, j) for j in vals.get('account_tag_ids')]})
+ if vals.get('account_tag_ids') == []:
+ vals.update({'account_tag_ids': [(5,)]})
+ if vals.get('analytic_ids'):
+ vals.update({'analytic_ids': [(4, j) for j in vals.get('analytic_ids')]})
+ if vals.get('analytic_ids') == []:
+ vals.update({'analytic_ids': [(5,)]})
+ if vals.get('analytic_tag_ids') == []:
+ vals.update({'analytic_tag_ids': [(4, j) for j in vals.get('analytic_tag_ids')]})
+ if vals.get('analytic_tag_ids') == []:
+ vals.update({'analytic_tag_ids': [(5,)]})
+ res = super(GeneralView, self).write(vals)
+ return res
+
+ def _get_accounts(self, accounts, init_balance, display_account, data):
+
+ cr = self.env.cr
+ MoveLine = self.env['account.move.line']
+ move_lines = {x: [] for x in accounts.ids}
+
+ # Prepare initial sql query and Get the initial move lines
+ if init_balance and data.get('date_from'):
+ init_tables, init_where_clause, init_where_params = MoveLine.with_context(
+ date_from=self.env.context.get('date_from'), date_to=False,
+ initial_bal=True)._query_get()
+ init_wheres = [""]
+ if init_where_clause.strip():
+ init_wheres.append(init_where_clause.strip())
+ init_filters = " AND ".join(init_wheres)
+ filters = init_filters.replace('account_move_line__move_id',
+ 'm').replace('account_move_line',
+ 'l')
+ new_filter = filters
+ if data['target_move'] == 'posted':
+ new_filter += " AND m.state = 'posted'"
+ else:
+ new_filter += " AND m.state in ('draft','posted')"
+ if data.get('date_from'):
+ new_filter += " AND l.date < '%s'" % data.get('date_from')
+ if data['journals']:
+ new_filter += ' AND j.id IN %s' % str(tuple(data['journals'].ids) + tuple([0]))
+ if data.get('accounts'):
+ WHERE = "WHERE l.account_id IN %s" % str(tuple(data.get('accounts').ids) + tuple([0]))
+ else:
+ WHERE = "WHERE l.account_id IN %s"
+ if data.get('analytics'):
+ WHERE += ' AND anl.id IN %s' % str(tuple(data.get('analytics').ids) + tuple([0]))
+ if data.get('analytic_tags'):
+ WHERE += ' AND anltag.account_analytic_tag_id IN %s' % str(
+ tuple(data.get('analytic_tags').ids) + tuple([0]))
+
+
+ sql = ("""SELECT 0 AS lid, l.account_id AS account_id, '' AS ldate, '' AS lcode, 0.0 AS amount_currency, '' AS lref, 'Initial Balance' AS lname, COALESCE(SUM(l.debit),0.0) AS debit, COALESCE(SUM(l.credit),0.0) AS credit, COALESCE(SUM(l.debit),0) - COALESCE(SUM(l.credit), 0) as balance, '' AS lpartner_id,\
+ '' AS move_name, '' AS mmove_id, '' AS currency_code,\
+ NULL AS currency_id,\
+ '' AS invoice_id, '' AS invoice_type, '' AS invoice_number,\
+ '' AS partner_name\
+ FROM account_move_line l\
+ LEFT JOIN account_move m ON (l.move_id=m.id)\
+ LEFT JOIN res_currency c ON (l.currency_id=c.id)\
+ LEFT JOIN res_partner p ON (l.partner_id=p.id)\
+ LEFT JOIN account_move i ON (m.id =i.id)\
+ LEFT JOIN account_account_tag_account_move_line_rel acc ON (acc.account_move_line_id=l.id)
+ LEFT JOIN account_analytic_account anl ON (l.analytic_account_id=anl.id)
+ LEFT JOIN account_analytic_tag_account_move_line_rel anltag ON (anltag.account_move_line_id=l.id)
+ JOIN account_journal j ON (l.journal_id=j.id)"""
+ + WHERE + new_filter + ' GROUP BY l.account_id')
+ if data.get('accounts'):
+ params = tuple(init_where_params)
+ else:
+ params = (tuple(accounts.ids),) + tuple(init_where_params)
+ cr.execute(sql, params)
+ for row in cr.dictfetchall():
+ row['m_id'] = row['account_id']
+ move_lines[row.pop('account_id')].append(row)
+
+ tables, where_clause, where_params = MoveLine._query_get()
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ final_filters = " AND ".join(wheres)
+ final_filters = final_filters.replace('account_move_line__move_id', 'm').replace(
+ 'account_move_line', 'l')
+ new_final_filter = final_filters
+ if data['target_move'] == 'posted':
+ new_final_filter += " AND m.state = 'posted'"
+ else:
+ new_final_filter += " AND m.state in ('draft','posted')"
+ if data.get('date_from'):
+ new_final_filter += " AND l.date >= '%s'" % data.get('date_from')
+ if data.get('date_to'):
+ new_final_filter += " AND l.date <= '%s'" % data.get('date_to')
+
+ if data['journals']:
+ new_final_filter += ' AND j.id IN %s' % str(tuple(data['journals'].ids) + tuple([0]))
+ if data.get('accounts'):
+ WHERE = "WHERE l.account_id IN %s" % str(tuple(data.get('accounts').ids) + tuple([0]))
+ else:
+ WHERE = "WHERE l.account_id IN %s"
+ if data.get('analytics'):
+ WHERE += ' AND anl.id IN %s' % str(tuple(data.get('analytics').ids) + tuple([0]))
+
+ if data.get('analytic_tags'):
+ WHERE += ' AND anltag.account_analytic_tag_id IN %s' % str(
+ tuple(data.get('analytic_tags').ids) + tuple([0]))
+
+ # Get move lines base on sql query and Calculate the total balance of move lines
+ sql = ('''SELECT l.id AS lid,m.id AS move_id, l.account_id AS account_id, l.date AS ldate, j.code AS lcode, l.currency_id, l.amount_currency, l.ref AS lref, l.name AS lname, COALESCE(l.debit,0) AS debit, COALESCE(l.credit,0) AS credit, COALESCE(SUM(l.balance),0) AS balance,\
+ m.name AS move_name, c.symbol AS currency_code, p.name AS partner_name\
+ FROM account_move_line l\
+ JOIN account_move m ON (l.move_id=m.id)\
+ LEFT JOIN res_currency c ON (l.currency_id=c.id)\
+ LEFT JOIN res_partner p ON (l.partner_id=p.id)\
+ LEFT JOIN account_analytic_account anl ON (l.analytic_account_id=anl.id)
+ LEFT JOIN account_account_tag_account_move_line_rel acc ON (acc.account_move_line_id=l.id)
+ LEFT JOIN account_analytic_tag_account_move_line_rel anltag ON (anltag.account_move_line_id=l.id)
+ JOIN account_journal j ON (l.journal_id=j.id)\
+ JOIN account_account a ON (l.account_id = a.id) '''
+ + WHERE + new_final_filter + ''' GROUP BY l.id, m.id, l.account_id, l.date, j.code, l.currency_id, l.amount_currency, l.ref, l.name, m.name, c.symbol, c.position, p.name''' )
+ if data.get('accounts'):
+ params = tuple(where_params)
+ else:
+ params = (tuple(accounts.ids),) + tuple(where_params)
+ cr.execute(sql, params)
+
+ for row in cr.dictfetchall():
+ balance = 0
+ for line in move_lines.get(row['account_id']):
+ balance += round(line['debit'],2) - round(line['credit'],2)
+ row['balance'] += round(balance,2)
+ row['m_id'] = row['account_id']
+ move_lines[row.pop('account_id')].append(row)
+
+ # Calculate the debit, credit and balance for Accounts
+ account_res = []
+ for account in accounts:
+ currency = account.currency_id and account.currency_id or account.company_id.currency_id
+ res = dict((fn, 0.0) for fn in ['credit', 'debit', 'balance'])
+ res['code'] = account.code
+ res['name'] = account.name
+ res['id'] = account.id
+ res['move_lines'] = move_lines[account.id]
+ for line in res.get('move_lines'):
+ res['debit'] += round(line['debit'],2)
+ res['credit'] += round(line['credit'],2)
+ res['balance'] = round(line['balance'],2)
+ if display_account == 'all':
+ account_res.append(res)
+ if display_account == 'movement' and res.get('move_lines'):
+ account_res.append(res)
+ if display_account == 'not_zero' and not currency.is_zero(
+ res['balance']):
+ account_res.append(res)
+
+ return account_res
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position,lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response ,report_data, dfr_data):
+ report_data_main = json.loads(report_data)
+ output = io.BytesIO()
+ name_data = json.loads(dfr_data)
+ filters = json.loads(data)
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+ sub_heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_l = workbook.add_format({'font_size': '10px', 'border': 1, 'bold': True})
+ sheet.merge_range('A2:J3', filters.get('company_name') + ':' + name_data.get('name'), head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+ date_style = workbook.add_format({'align': 'center',
+ 'font_size': '10px'})
+ if filters.get('date_from'):
+ sheet.merge_range('B4:C4', 'From: ' + filters.get('date_from'), date_head)
+ if filters.get('date_to'):
+ sheet.merge_range('H4:I4', 'To: ' + filters.get('date_to'), date_head)
+ # sheet.merge_range('A5:J6', 'Journals: ' + ', '.join(
+ # [lt or '' for lt in filters['journals']]) + ' Target Moves: ' + filters.get('target_move'), date_head)
+
+ sheet.merge_range('A5:J6', ' Journals: ' + ', '.join(
+ [lt or '' for lt in
+ filters['journals']]) + ' Accounts: ' + ', '.join(
+ [lt or '' for lt in
+ filters['accounts']]) + ' Account Tags: ' + ', '.join(
+ [lt or '' for lt in
+ filters['analytic_tags']]) + ' Analytic: ' + ', '.join(
+ [at or '' for at in
+ filters['analytics']]) + ' Target Moves : ' + filters.get('target_move'),
+ date_head)
+
+
+ sheet.write('A8', 'Code', sub_heading)
+ sheet.write('B8', 'Amount', sub_heading)
+ sheet.write('C8', 'Date', sub_heading)
+ sheet.write('D8', 'JRNL', sub_heading)
+ sheet.write('E8', 'Partner', sub_heading)
+ sheet.write('F8', 'Move', sub_heading)
+ sheet.write('G8', 'Entry Label', sub_heading)
+ sheet.write('H8', 'Debit', sub_heading)
+ sheet.write('I8', 'Credit', sub_heading)
+ sheet.write('J8', 'Balance', sub_heading)
+
+ row = 6
+ col = 0
+ sheet.set_column(8, 0, 15)
+ sheet.set_column('B:B', 40)
+ sheet.set_column(8, 2, 15)
+ sheet.set_column(8, 3, 15)
+ sheet.set_column(8, 4, 15)
+ sheet.set_column(8, 5, 15)
+ sheet.set_column(8, 6, 50)
+ sheet.set_column(8, 7, 26)
+ sheet.set_column(8, 8, 15)
+ sheet.set_column(8, 9, 15)
+
+ for rec_data in report_data_main:
+
+ row += 1
+ sheet.write(row + 1, col, rec_data['code'], txt)
+ sheet.write(row + 1, col + 1, rec_data['name'], txt)
+ sheet.write(row + 1, col + 2, '', txt)
+ sheet.write(row + 1, col + 3, '', txt)
+ sheet.write(row + 1, col + 4, '', txt)
+ sheet.write(row + 1, col + 5, '', txt)
+ sheet.write(row + 1, col + 6, '', txt)
+
+ sheet.write(row + 1, col + 7, rec_data['debit'], txt)
+ sheet.write(row + 1, col + 8, rec_data['credit'], txt)
+ sheet.write(row + 1, col + 9, rec_data['balance'], txt)
+ for line_data in rec_data['move_lines']:
+ row += 1
+ sheet.write(row + 1, col, '', txt)
+ sheet.write(row + 1, col + 1, '', txt)
+ sheet.write(row + 1, col + 2, line_data.get('ldate'), txt)
+ sheet.write(row + 1, col + 3, line_data.get('lcode'), txt)
+ sheet.write(row + 1, col + 4, line_data.get('partner_name'), txt)
+ sheet.write(row + 1, col + 5, line_data.get('move_name'), txt)
+ sheet.write(row + 1, col + 6, line_data.get('lname'), txt)
+ sheet.write(row + 1, col + 7, line_data.get('debit'), txt)
+ sheet.write(row + 1, col + 8, line_data.get('credit'), txt)
+ sheet.write(row + 1, col + 9, line_data.get('balance'), txt)
+
+
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close() \ No newline at end of file
diff --git a/dynamic_accounts_report/wizard/partner_leadger.py b/dynamic_accounts_report/wizard/partner_leadger.py
new file mode 100644
index 0000000..f7bddd8
--- /dev/null
+++ b/dynamic_accounts_report/wizard/partner_leadger.py
@@ -0,0 +1,456 @@
+import time
+from odoo import fields, models, api, _
+
+import io
+import json
+from odoo.exceptions import AccessError, UserError, AccessDenied
+
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class PartnerView(models.TransientModel):
+ _inherit = "account.common.report"
+ _name = 'account.partner.ledger'
+
+ journal_ids = fields.Many2many('account.journal',
+ string='Journals', required=True,
+ default=[])
+ account_ids = fields.Many2many(
+ "account.account",
+ string="Accounts", check_company=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')
+
+ partner_ids = fields.Many2many('res.partner', string='Partner')
+ partner_category_ids = fields.Many2many('res.partner.category',
+ string='Partner tags')
+ reconciled = fields.Selection([
+ ('unreconciled', 'Unreconciled Only')],
+ string='Reconcile Type', default='unreconciled')
+
+ account_type_ids = fields.Many2many('account.account.type',string='Account Type',
+ domain=[('type', 'in', ('receivable', 'payable'))])
+
+ @api.model
+ def view_report(self, option):
+ r = self.env['account.partner.ledger'].search([('id', '=', option[0])])
+ data = {
+ 'display_account': r.display_account,
+ 'model': self,
+ 'journals': r.journal_ids,
+ 'accounts': r.account_ids,
+ 'target_move': r.target_move,
+ 'partners': r.partner_ids,
+ 'reconciled': r.reconciled,
+ 'account_type': r.account_type_ids,
+ 'partner_tags': r.partner_category_ids,
+ }
+
+ if r.date_from:
+ data.update({
+ 'date_from':r.date_from,
+ })
+ if r.date_to:
+ data.update({
+ 'date_to':r.date_to,
+ })
+
+ filters = self.get_filter(option)
+ records = self._get_report_values(data)
+ currency = self._get_currency()
+
+ return {
+ 'name': "partner Ledger",
+ 'type': 'ir.actions.client',
+ 'tag': 'p_l',
+ 'filters': filters,
+ 'report_lines': records['Partners'],
+ 'debit_total': records['debit_total'],
+ 'credit_total': records['credit_total'],
+ 'debit_balance': records['debit_balance'],
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+
+ filters = {}
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('account_ids', []):
+ filters['accounts'] = self.env['account.account'].browse(data.get('account_ids', [])).mapped('code')
+ else:
+ filters['accounts'] = ['All Payable and Receivable']
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move').capitalize()
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+
+ filters['company_id'] = ''
+ filters['accounts_list'] = data.get('accounts_list')
+ filters['journals_list'] = data.get('journals_list')
+
+ filters['company_name'] = data.get('company_name')
+
+ if data.get('partners'):
+ filters['partners'] = self.env['res.partner'].browse(
+ data.get('partners')).mapped('name')
+ else:
+ filters['partners'] = ['All']
+
+ if data.get('reconciled') == 'unreconciled':
+ filters['reconciled'] = 'Unreconciled'
+
+ if data.get('account_type', []):
+ filters['account_type'] = self.env['account.account.type'].browse(data.get('account_type', [])).mapped('name')
+ else:
+ filters['account_type'] = ['Receivable and Payable']
+
+ if data.get('partner_tags', []):
+ filters['partner_tags'] = self.env['res.partner.category'].browse(
+ data.get('partner_tags', [])).mapped('name')
+ else:
+ filters['partner_tags'] = ['All']
+
+ filters['partners_list'] = data.get('partners_list')
+ filters['category_list'] = data.get('category_list')
+ filters['account_type_list'] = data.get('account_type_list')
+ filters['target_move'] = data.get('target_move').capitalize()
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.partner.ledger'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = r.journal_ids if r.journal_ids else self.env['account.journal'].search(company_domain)
+ accounts = self.account_ids if self.account_ids else self.env['account.account'].search(company_domain)
+
+ partner = r.partner_ids if r.partner_ids else self.env[
+ 'res.partner'].search([])
+ categories = self.partner_category_ids if self.partner_category_ids \
+ else self.env['res.partner.category'].search([])
+ account_types = r.account_type_ids if r.account_type_ids \
+ else self.env['account.account.type'].search([('type', 'in', ('receivable', 'payable'))])
+
+ filter_dict = {
+ 'journal_ids': r.journal_ids.ids,
+ 'account_ids': r.account_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to': r.date_to,
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'accounts_list': [(a.id, a.name) for a in accounts],
+ 'company_name': company_id and company_id.name,
+ 'partners': r.partner_ids.ids,
+ 'reconciled': r.reconciled,
+ 'account_type': r.account_type_ids.ids,
+ 'partner_tags': r.partner_category_ids.ids,
+ 'partners_list': [(p.id, p.name) for p in partner],
+ 'category_list': [(c.id, c.name) for c in categories],
+ 'account_type_list': [(t.id, t.name) for t in account_types],
+
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data):
+ docs = data['model']
+ display_account = data['display_account']
+ init_balance = True
+ accounts = self.env['account.account'].search([('user_type_id.type', 'in', ('receivable', 'payable')),
+ ('company_id', '=', self.env.company.id)])
+ if data['account_type']:
+ accounts = self.env['account.account'].search(
+ [('user_type_id.id', 'in', data['account_type'].ids),('company_id', '=', self.env.company.id)])
+
+ partners = self.env['res.partner'].search([])
+
+ if data['partner_tags']:
+ partners = self.env['res.partner'].search(
+ [('category_id', 'in', data['partner_tags'].ids)])
+ if not accounts:
+ raise UserError(_("No Accounts Found! Please Add One"))
+ partner_res = self._get_partners(partners,accounts, init_balance, display_account, data)
+
+ debit_total = 0
+ debit_total = sum(x['debit'] for x in partner_res)
+ credit_total = sum(x['credit'] for x in partner_res)
+ debit_balance = round(debit_total,2) - round(credit_total,2)
+ return {
+ 'doc_ids': self.ids,
+ 'debit_total': debit_total,
+ 'credit_total': credit_total,
+ 'debit_balance':debit_balance,
+ 'docs': docs,
+ 'time': time,
+ 'Partners': partner_res,
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(PartnerView, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if not vals.get('journal_ids'):
+ vals.update({'journal_ids': [(5,)]})
+ if vals.get('account_ids'):
+ vals.update({'account_ids': [(4, j) for j in vals.get('account_ids')]})
+ if not vals.get('account_ids'):
+ vals.update({'account_ids': [(5,)]})
+ if vals.get('partner_ids'):
+ vals.update(
+ {'partner_ids': [(4, j) for j in vals.get('partner_ids')]})
+ if not vals.get('partner_ids'):
+ vals.update({'partner_ids': [(5,)]})
+ if vals.get('partner_category_ids'):
+ vals.update({'partner_category_ids': [(4, j) for j in vals.get(
+ 'partner_category_ids')]})
+ if not vals.get('partner_category_ids'):
+ vals.update({'partner_category_ids': [(5,)]})
+
+ if vals.get('account_type-ids'):
+ vals.update(
+ {'account_type_ids': [(4, j) for j in vals.get('account_type_ids')]})
+ if not vals.get('account_type_ids'):
+ vals.update({'account_type_ids': [(5,)]})
+
+ res = super(PartnerView, self).write(vals)
+ return res
+
+ def _get_partners(self, partners, accounts, init_balance, display_account, data):
+
+ cr = self.env.cr
+ move_line = self.env['account.move.line']
+ move_lines = {x: [] for x in partners.ids}
+ currency_id = self.env.company.currency_id
+
+ tables, where_clause, where_params = move_line._query_get()
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ final_filters = " AND ".join(wheres)
+ final_filters = final_filters.replace('account_move_line__move_id', 'm').replace(
+ 'account_move_line', 'l')
+ new_final_filter = final_filters
+ if data['target_move'] == 'posted':
+ new_final_filter += " AND m.state = 'posted'"
+ else:
+ new_final_filter += " AND m.state in ('draft','posted')"
+ if data.get('date_from'):
+ new_final_filter += " AND l.date >= '%s'" % data.get('date_from')
+ if data.get('date_to'):
+ new_final_filter += " AND l.date <= '%s'" % data.get('date_to')
+
+ if data['journals']:
+ new_final_filter += ' AND j.id IN %s' % str(tuple(data['journals'].ids) + tuple([0]))
+
+ if data.get('accounts'):
+ WHERE = "WHERE l.account_id IN %s" % str(tuple(data.get('accounts').ids) + tuple([0]))
+ else:
+ WHERE = "WHERE l.account_id IN %s"
+
+ if data.get('partners'):
+ WHERE += ' AND p.id IN %s' % str(
+ tuple(data.get('partners').ids) + tuple([0]))
+
+ if data.get('reconciled') == 'unreconciled':
+ WHERE += ' AND l.full_reconcile_id is null AND' \
+ ' l.balance != 0 AND a.reconcile is true'
+
+ sql = ('''SELECT l.id AS lid,l.partner_id AS partner_id,m.id AS move_id,
+ l.account_id AS account_id, l.date AS ldate, j.code AS lcode, l.currency_id,
+ l.amount_currency, l.ref AS lref, l.name AS lname,
+ COALESCE(l.debit,0) AS debit, COALESCE(l.credit,0) AS credit,
+ COALESCE(SUM(l.balance),0) AS balance,\
+ m.name AS move_name, c.symbol AS currency_code,c.position AS currency_position, p.name AS partner_name\
+ FROM account_move_line l\
+ JOIN account_move m ON (l.move_id=m.id)\
+ JOIN account_account a ON (l.account_id=a.id)
+ LEFT JOIN res_currency c ON (l.currency_id=c.id)\
+ LEFT JOIN res_partner p ON (l.partner_id=p.id)\
+ JOIN account_journal j ON (l.journal_id=j.id)\
+ JOIN account_account acc ON (l.account_id = acc.id) '''
+ + WHERE + new_final_filter + ''' GROUP BY l.id, m.id, l.account_id, l.date, j.code, l.currency_id, l.amount_currency, l.ref, l.name, m.name, c.symbol, c.position, p.name''' )
+ if data.get('accounts'):
+ params = tuple(where_params)
+ else:
+ params = (tuple(accounts.ids),) + tuple(where_params)
+ cr.execute(sql, params)
+
+ account_list = { x.id : {'name' : x.name, 'code': x.code} for x in accounts}
+
+ for row in cr.dictfetchall():
+ balance = 0
+ if row['partner_id'] in move_lines:
+ for line in move_lines.get(row['partner_id']):
+ balance += round(line['debit'],2) - round(line['credit'],2)
+ row['balance'] += (round(balance, 2))
+ row['m_id'] = row['account_id']
+ row['account_name'] = account_list[row['account_id']]['name'] + "(" +account_list[row['account_id']]['code'] + ")"
+ move_lines[row.pop('partner_id')].append(row)
+
+ partner_res = []
+ for partner in partners:
+ company_id = self.env.company
+ currency = company_id.currency_id
+ res = dict((fn, 0.0) for fn in ['credit', 'debit', 'balance'])
+ res['name'] = partner.name
+ res['id'] = partner.id
+ res['move_lines'] = move_lines[partner.id]
+ for line in res.get('move_lines'):
+ res['debit'] += round(line['debit'], 2)
+ res['credit'] += round(line['credit'], 2)
+ res['balance'] = round(line['balance'], 2)
+ if display_account == 'all':
+ partner_res.append(res)
+ if display_account == 'movement' and res.get('move_lines'):
+ partner_res.append(res)
+ if display_account == 'not_zero' and not currency.is_zero(
+ res['balance']):
+ partner_res.append(res)
+ return partner_res
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position, lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response, report_data, dfr_data):
+ report_data = json.loads(report_data)
+ filters = json.loads(data)
+
+ output = io.BytesIO()
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ cell_format = workbook.add_format(
+ {'align': 'center', 'bold': True,
+ 'border': 0
+ })
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ sub_heading_sub = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ sheet.merge_range('A1:H2',
+ filters.get('company_name') + ':' + 'Partner Ledger',
+ head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+
+ sheet.merge_range('A4:B4',
+ 'Target Moves: ' + filters.get('target_move'),
+ date_head)
+
+ sheet.merge_range('C4:D4', 'Account Type: ' + ', ' .join(
+ [lt or '' for lt in
+ filters['account_type']]),
+ date_head)
+ sheet.merge_range('E3:F3', ' Partners: ' + ', '.join(
+ [lt or '' for lt in
+ filters['partners']]), date_head)
+ sheet.merge_range('G3:H3', ' Partner Tags: ' + ', '.join(
+ [lt or '' for lt in
+ filters['partner_tags']]),
+ date_head)
+ sheet.merge_range('A3:B3', ' Journals: ' + ', '.join(
+ [lt or '' for lt in
+ filters['journals']]),
+ date_head)
+ sheet.merge_range('C3:D3', ' Accounts: ' + ', '.join(
+ [lt or '' for lt in
+ filters['accounts']]),
+ date_head)
+
+ if filters.get('date_from') and filters.get('date_to'):
+ sheet.merge_range('E4:F4', 'From: ' + filters.get('date_from'),
+ date_head)
+
+ sheet.merge_range('G4:H4', 'To: ' + filters.get('date_to'),
+ date_head)
+ elif filters.get('date_from'):
+ sheet.merge_range('E4:F4', 'From: ' + filters.get('date_from'),
+ date_head)
+ elif filters.get('date_to'):
+ sheet.merge_range('E4:F4', 'To: ' + filters.get('date_to'),
+ date_head)
+
+ sheet.merge_range('A5:E5', 'Partner', cell_format)
+ sheet.write('F5', 'Debit', cell_format)
+ sheet.write('G5', 'Credit', cell_format)
+ sheet.write('H5', 'Balance', cell_format)
+
+ row = 4
+ col = 0
+
+ sheet.set_column(0, 0, 15)
+ sheet.set_column(1, 1, 15)
+ sheet.set_column(2, 2, 25)
+ sheet.set_column(3, 3, 15)
+ sheet.set_column(4, 4, 36)
+ sheet.set_column(5, 5, 15)
+ sheet.set_column(6, 6, 15)
+ sheet.set_column(7, 7, 15)
+
+ for report in report_data:
+
+ row += 1
+ sheet.merge_range(row, col + 0, row, col + 4, report['name'],
+ sub_heading_sub)
+ sheet.write(row, col + 5, report['debit'], sub_heading_sub)
+ sheet.write(row, col + 6, report['credit'], sub_heading_sub)
+ sheet.write(row, col + 7, report['balance'], sub_heading_sub)
+ row += 1
+ sheet.write(row, col + 0, 'Date', cell_format)
+ sheet.write(row, col + 1, 'JRNL', cell_format)
+ sheet.write(row, col + 2, 'Account', cell_format)
+ sheet.write(row, col + 3, 'Move', cell_format)
+ sheet.write(row, col + 4, 'Entry Label', cell_format)
+ sheet.write(row, col + 5, 'Debit', cell_format)
+ sheet.write(row, col + 6, 'Credit', cell_format)
+ sheet.write(row, col + 7, 'Balance', cell_format)
+ for r_rec in report['move_lines']:
+ row += 1
+ sheet.write(row, col + 0, r_rec['ldate'], txt)
+ sheet.write(row, col + 1, r_rec['lcode'], txt)
+ sheet.write(row, col + 2, r_rec['account_name'], txt)
+ sheet.write(row, col + 3, r_rec['move_name'], txt)
+ sheet.write(row, col + 4, r_rec['lname'], txt)
+ sheet.write(row, col + 5, r_rec['debit'], txt)
+ sheet.write(row, col + 6, r_rec['credit'], txt)
+ sheet.write(row, col + 7, r_rec['balance'], txt)
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close()
diff --git a/dynamic_accounts_report/wizard/trial_balance.py b/dynamic_accounts_report/wizard/trial_balance.py
new file mode 100644
index 0000000..563a88c
--- /dev/null
+++ b/dynamic_accounts_report/wizard/trial_balance.py
@@ -0,0 +1,324 @@
+import time
+from odoo import fields, models, api, _
+
+import io
+import json
+from odoo.exceptions import AccessError, UserError, AccessDenied
+
+try:
+ from odoo.tools.misc import xlsxwriter
+except ImportError:
+ import xlsxwriter
+
+
+class TrialView(models.TransientModel):
+ _inherit = "account.common.report"
+ _name = 'account.trial.balance'
+
+ journal_ids = fields.Many2many('account.journal',
+
+ string='Journals', required=True,
+ default=[])
+ 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')
+
+ @api.model
+ def view_report(self, option):
+ r = self.env['account.trial.balance'].search([('id', '=', option[0])])
+
+ data = {
+ 'display_account': r.display_account,
+ 'model':self,
+ 'journals': r.journal_ids,
+ 'target_move': r.target_move,
+
+ }
+ if r.date_from:
+ data.update({
+ 'date_from':r.date_from,
+ })
+ if r.date_to:
+ data.update({
+ 'date_to':r.date_to,
+ })
+
+ filters = self.get_filter(option)
+ records = self._get_report_values(data)
+ currency = self._get_currency()
+
+ return {
+ 'name': "Trial Balance",
+ 'type': 'ir.actions.client',
+ 'tag': 't_b',
+ 'filters': filters,
+ 'report_lines': records['Accounts'],
+ 'debit_total': records['debit_total'],
+ 'credit_total': records['credit_total'],
+ 'currency': currency,
+ }
+
+ def get_filter(self, option):
+ data = self.get_filter_data(option)
+ filters = {}
+ if data.get('journal_ids'):
+ filters['journals'] = self.env['account.journal'].browse(data.get('journal_ids')).mapped('code')
+ else:
+ filters['journals'] = ['All']
+ if data.get('target_move'):
+ filters['target_move'] = data.get('target_move')
+ if data.get('date_from'):
+ filters['date_from'] = data.get('date_from')
+ if data.get('date_to'):
+ filters['date_to'] = data.get('date_to')
+
+ filters['company_id'] = ''
+ filters['journals_list'] = data.get('journals_list')
+ filters['company_name'] = data.get('company_name')
+ filters['target_move'] = data.get('target_move').capitalize()
+
+ return filters
+
+ def get_filter_data(self, option):
+ r = self.env['account.trial.balance'].search([('id', '=', option[0])])
+ default_filters = {}
+ company_id = self.env.company
+ company_domain = [('company_id', '=', company_id.id)]
+ journals = r.journal_ids if r.journal_ids else self.env['account.journal'].search(company_domain)
+
+ filter_dict = {
+ 'journal_ids': r.journal_ids.ids,
+ 'company_id': company_id.id,
+ 'date_from': r.date_from,
+ 'date_to': r.date_to,
+ 'target_move': r.target_move,
+ 'journals_list': [(j.id, j.name, j.code) for j in journals],
+ 'company_name': company_id and company_id.name,
+ }
+ filter_dict.update(default_filters)
+ return filter_dict
+
+ def _get_report_values(self, data):
+ docs = data['model']
+ display_account = data['display_account']
+ journals = data['journals']
+ accounts = self.env['account.account'].search([])
+ if not accounts:
+ raise UserError(_("No Accounts Found! Please Add One"))
+ account_res = self._get_accounts(accounts, display_account, data)
+ debit_total = 0
+ debit_total = sum(x['debit'] for x in account_res)
+ credit_total = sum(x['credit'] for x in account_res)
+ return {
+ 'doc_ids': self.ids,
+ 'debit_total': debit_total,
+ 'credit_total': credit_total,
+ 'docs': docs,
+ 'time': time,
+ 'Accounts': account_res,
+ }
+
+ @api.model
+ def create(self, vals):
+ vals['target_move'] = 'posted'
+ res = super(TrialView, self).create(vals)
+ return res
+
+ def write(self, vals):
+ if vals.get('target_move'):
+ vals.update({'target_move': vals.get('target_move').lower()})
+ if vals.get('journal_ids'):
+ vals.update({'journal_ids': [(6, 0, vals.get('journal_ids'))]})
+ if vals.get('journal_ids') == []:
+ vals.update({'journal_ids': [(5,)]})
+ res = super(TrialView, self).write(vals)
+ return res
+
+ def _get_accounts(self, accounts, display_account, data):
+
+ account_result = {}
+ # Prepare sql query base on selected parameters from wizard
+ tables, where_clause, where_params = self.env['account.move.line']._query_get()
+ tables = tables.replace('"', '')
+ if not tables:
+ tables = 'account_move_line'
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ filters = " AND ".join(wheres)
+ if data['target_move'] == 'posted':
+ filters += " AND account_move_line__move_id.state = 'posted'"
+ else:
+ filters += " AND account_move_line__move_id.state in ('draft','posted')"
+ if data.get('date_from'):
+ filters += " AND account_move_line.date >= '%s'" % data.get('date_from')
+ if data.get('date_to'):
+ filters += " AND account_move_line.date <= '%s'" % data.get('date_to')
+
+ if data['journals']:
+ filters += ' AND jrnl.id IN %s' % str(tuple(data['journals'].ids) + tuple([0]))
+ tables += 'JOIN account_journal jrnl ON (account_move_line.journal_id=jrnl.id)'
+ # compute the balance, debit and credit for the provided accounts
+ request = (
+ "SELECT account_id AS id, SUM(debit) AS debit, SUM(credit) AS credit, (SUM(debit) - SUM(credit)) AS balance" + \
+ " 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():
+ account_result[row.pop('id')] = row
+
+ account_res = []
+ for account in accounts:
+ res = dict((fn, 0.0) for fn in ['credit', 'debit', 'balance'])
+ currency = account.currency_id and account.currency_id or account.company_id.currency_id
+ res['code'] = account.code
+ res['name'] = account.name
+ res['id'] = account.id
+ if data.get('date_from'):
+
+ res['Init_balance'] = self.get_init_bal(account, display_account, data)
+
+ if account.id in account_result:
+ res['debit'] = account_result[account.id].get('debit')
+ res['credit'] = account_result[account.id].get('credit')
+ res['balance'] = account_result[account.id].get('balance')
+ if display_account == 'all':
+ account_res.append(res)
+ if display_account == 'not_zero' and not currency.is_zero(
+ res['balance']):
+ account_res.append(res)
+ if display_account == 'movement' and (
+ not currency.is_zero(res['debit']) or not currency.is_zero(
+ res['credit'])):
+ account_res.append(res)
+ return account_res
+
+ def get_init_bal(self, account, display_account, data):
+ if data.get('date_from'):
+
+ tables, where_clause, where_params = self.env[
+ 'account.move.line']._query_get()
+ tables = tables.replace('"', '')
+ if not tables:
+ tables = 'account_move_line'
+ wheres = [""]
+ if where_clause.strip():
+ wheres.append(where_clause.strip())
+ filters = " AND ".join(wheres)
+ if data['target_move'] == 'posted':
+ filters += " AND account_move_line__move_id.state = 'posted'"
+ else:
+ filters += " AND account_move_line__move_id.state in ('draft','posted')"
+ if data.get('date_from'):
+ filters += " AND account_move_line.date < '%s'" % data.get('date_from')
+
+ if data['journals']:
+ filters += ' AND jrnl.id IN %s' % str(tuple(data['journals'].ids) + tuple([0]))
+ tables += 'JOIN account_journal jrnl ON (account_move_line.journal_id=jrnl.id)'
+
+ # compute the balance, debit and credit for the provided accounts
+ request = (
+ "SELECT account_id AS id, SUM(debit) AS debit, SUM(credit) AS credit, (SUM(debit) - SUM(credit)) AS balance" + \
+ " FROM " + tables + " WHERE account_id = %s" % account.id + filters + " GROUP BY account_id")
+ params = tuple(where_params)
+ self.env.cr.execute(request, params)
+ for row in self.env.cr.dictfetchall():
+ return row
+
+ @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
+ lang = self.env.user.lang
+ if not lang:
+ lang = 'en_US'
+ lang = lang.replace("_", '-')
+ currency_array = [self.env.company.currency_id.symbol,
+ self.env.company.currency_id.position,
+ lang]
+ return currency_array
+
+ def get_dynamic_xlsx_report(self, data, response ,report_data, dfr_data):
+ report_data_main = json.loads(report_data)
+ output = io.BytesIO()
+ total = json.loads(dfr_data)
+ filters = json.loads(data)
+ workbook = xlsxwriter.Workbook(output, {'in_memory': True})
+ sheet = workbook.add_worksheet()
+ head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '20px'})
+ sub_heading = workbook.add_format(
+ {'align': 'center', 'bold': True, 'font_size': '10px',
+ 'border': 1,
+ 'border_color': 'black'})
+ txt = workbook.add_format({'font_size': '10px', 'border': 1})
+ txt_l = workbook.add_format({'font_size': '10px', 'border': 1, 'bold': True})
+ sheet.merge_range('A2:D3', filters.get('company_name') + ':' + ' Trial Balance', head)
+ date_head = workbook.add_format({'align': 'center', 'bold': True,
+ 'font_size': '10px'})
+ date_style = workbook.add_format({'align': 'center',
+ 'font_size': '10px'})
+ if filters.get('date_from'):
+ sheet.merge_range('A4:B4', 'From: '+filters.get('date_from') , date_head)
+ if filters.get('date_to'):
+ sheet.merge_range('C4:D4', 'To: '+ filters.get('date_to'), date_head)
+ sheet.merge_range('A5:D6', 'Journals: ' + ', '.join([ lt or '' for lt in filters['journals'] ]) + ' Target Moves: '+ filters.get('target_move'), date_head)
+ sheet.write('A7', 'Code', sub_heading)
+ sheet.write('B7', 'Amount', sub_heading)
+ if filters.get('date_from'):
+ sheet.write('C7', 'Initial Debit', sub_heading)
+ sheet.write('D7', 'Initial Credit', sub_heading)
+ sheet.write('E7', 'Debit', sub_heading)
+ sheet.write('F7', 'Credit', sub_heading)
+ else:
+ sheet.write('C7', 'Debit', sub_heading)
+ sheet.write('D7', 'Credit', sub_heading)
+
+ row = 6
+ col = 0
+ sheet.set_column(5, 0, 15)
+ sheet.set_column(6, 1, 15)
+ sheet.set_column(7, 2, 26)
+ if filters.get('date_from'):
+ sheet.set_column(8, 3, 15)
+ sheet.set_column(9, 4, 15)
+ sheet.set_column(10, 5, 15)
+ sheet.set_column(11, 6, 15)
+ else:
+
+ sheet.set_column(8, 3, 15)
+ sheet.set_column(9, 4, 15)
+ for rec_data in report_data_main:
+
+ row += 1
+ sheet.write(row, col, rec_data['code'], txt)
+ sheet.write(row, col + 1, rec_data['name'], txt)
+ if filters.get('date_from'):
+ if rec_data.get('Init_balance'):
+ sheet.write(row, col + 2, rec_data['Init_balance']['debit'], txt)
+ sheet.write(row, col + 3, rec_data['Init_balance']['credit'], txt)
+ else:
+ sheet.write(row, col + 2, 0, txt)
+ sheet.write(row, col + 3, 0, txt)
+
+ sheet.write(row, col + 4, rec_data['debit'], txt)
+ sheet.write(row, col + 5, rec_data['credit'], txt)
+
+ else:
+ sheet.write(row, col + 2, rec_data['debit'], txt)
+ sheet.write(row, col + 3, rec_data['credit'], txt)
+ sheet.write(row+1, col, 'Total', sub_heading)
+ if filters.get('date_from'):
+ sheet.write(row + 1, col + 4, total.get('debit_total'), txt_l)
+ sheet.write(row + 1, col + 5, total.get('credit_total'), txt_l)
+ else:
+ sheet.write(row + 1, col + 2, total.get('debit_total'), txt_l)
+ sheet.write(row + 1, col + 3, total.get('credit_total'), txt_l)
+
+ workbook.close()
+ output.seek(0)
+ response.stream.write(output.read())
+ output.close()