You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

741 lines
34 KiB

  1. # © 2016 Julien Coux (Camptocamp)
  2. # Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from odoo import _, models, api
  5. from odoo.tools import float_is_zero
  6. import calendar
  7. import datetime
  8. import operator
  9. class GeneralLedgerReport(models.AbstractModel):
  10. _name = 'report.account_financial_report.general_ledger'
  11. _description = "General Ledger Report"
  12. def _get_accounts_data(self, account_ids):
  13. accounts = self.env['account.account'].browse(account_ids)
  14. accounts_data = {}
  15. for account in accounts:
  16. accounts_data.update({account.id: {
  17. 'id': account.id,
  18. 'code': account.code,
  19. 'name': account.name,
  20. 'group_id': account.group_id.id,
  21. 'currency_id': account.currency_id or False,
  22. 'currency_name': account.currency_id.name,
  23. 'centralized': account.centralized
  24. }
  25. })
  26. return accounts_data
  27. def _get_journals_data(self, journals_ids):
  28. journals = self.env['account.journal'].browse(journals_ids)
  29. journals_data = {}
  30. for journal in journals:
  31. journals_data.update({journal.id: {'id': journal.id,
  32. 'code': journal.code}})
  33. return journals_data
  34. def _get_tags_data(self, tags_ids):
  35. tags = self.env['account.analytic.tag'].browse(tags_ids)
  36. tags_data = {}
  37. for tag in tags:
  38. tags_data.update({tag.id: {'name': tag.name}})
  39. return tags_data
  40. def _get_taxes_data(self, taxes_ids):
  41. taxes = self.env['account.tax'].browse(taxes_ids)
  42. taxes_data = {}
  43. for tax in taxes:
  44. taxes_data.update({tax.id: {
  45. 'id': tax.id,
  46. 'amount': tax.amount,
  47. 'amount_type': tax.amount_type,
  48. 'display_name': tax.display_name,
  49. }})
  50. if tax.amount_type == 'percent' or tax.amount_type == 'division':
  51. taxes_data[tax.id]['string'] = '%'
  52. else:
  53. taxes_data[tax.id]['string'] = ''
  54. taxes_data[tax.id]['tax_name'] = tax.display_name + ' (' + \
  55. str(tax.amount) + taxes_data[tax.id]['string'] + ')'
  56. return taxes_data
  57. def _get_acc_prt_accounts_ids(self, company_id):
  58. accounts_domain = [
  59. ('company_id', '=', company_id),
  60. ('internal_type', 'in', ['receivable', 'payable'])]
  61. acc_prt_accounts = self.env['account.account'].search(accounts_domain)
  62. return acc_prt_accounts.ids
  63. def _get_initial_balances_bs_ml_domain(self, account_ids,
  64. company_id, date_from,
  65. base_domain, acc_prt=False):
  66. accounts_domain = [
  67. ('company_id', '=', company_id),
  68. ('user_type_id.include_initial_balance', '=', True)]
  69. if account_ids:
  70. accounts_domain += [('id', 'in', account_ids)]
  71. domain = []
  72. domain += base_domain
  73. domain += [('date', '<', date_from)]
  74. accounts = self.env['account.account'].search(accounts_domain)
  75. domain += [('account_id', 'in', accounts.ids)]
  76. if acc_prt:
  77. domain += [('account_id.internal_type', 'in', [
  78. 'receivable', 'payable'])]
  79. return domain
  80. def _get_initial_balances_pl_ml_domain(self, account_ids,
  81. company_id, date_from,
  82. fy_start_date, base_domain):
  83. accounts_domain = [
  84. ('company_id', '=', company_id),
  85. ('user_type_id.include_initial_balance', '=', False)]
  86. if account_ids:
  87. accounts_domain += [('id', 'in', account_ids)]
  88. domain = []
  89. domain += base_domain
  90. domain += [('date', '<', date_from), ('date', '>=', fy_start_date)]
  91. accounts = self.env['account.account'].search(accounts_domain)
  92. domain += [('account_id', 'in', accounts.ids)]
  93. return domain
  94. def _get_accounts_initial_balance(self, initial_domain_bs,
  95. initial_domain_pl):
  96. gl_initial_acc_bs = self.env['account.move.line'].read_group(
  97. domain=initial_domain_bs,
  98. fields=['account_id', 'debit', 'credit', 'balance',
  99. 'amount_currency'],
  100. groupby=['account_id']
  101. )
  102. gl_initial_acc_pl = self.env['account.move.line'].read_group(
  103. domain=initial_domain_pl,
  104. fields=['account_id', 'debit', 'credit', 'balance',
  105. 'amount_currency'],
  106. groupby=['account_id'])
  107. gl_initial_acc = gl_initial_acc_bs + gl_initial_acc_pl
  108. return gl_initial_acc
  109. def _get_initial_balance_fy_pl_ml_domain(self, account_ids, company_id,
  110. fy_start_date, base_domain):
  111. accounts_domain = [
  112. ('company_id', '=', company_id),
  113. ('user_type_id.include_initial_balance', '=', False)]
  114. if account_ids:
  115. accounts_domain += [('id', 'in', account_ids)]
  116. domain = []
  117. domain += base_domain
  118. domain += [('date', '<', fy_start_date)]
  119. accounts = self.env['account.account'].search(accounts_domain)
  120. domain += [('account_id', 'in', accounts.ids)]
  121. return domain
  122. def _get_pl_initial_balance(self, account_ids, company_id,
  123. fy_start_date, foreign_currency, base_domain):
  124. domain = self._get_initial_balance_fy_pl_ml_domain(
  125. account_ids, company_id, fy_start_date, base_domain
  126. )
  127. initial_balances = self.env['account.move.line'].read_group(
  128. domain=domain,
  129. fields=[
  130. 'account_id',
  131. 'debit',
  132. 'credit',
  133. 'balance',
  134. 'amount_currency'],
  135. groupby=['account_id'])
  136. pl_initial_balance = {
  137. 'debit': 0.0,
  138. 'credit': 0.0,
  139. 'balance': 0.0,
  140. 'bal_curr': 0.0,
  141. }
  142. for initial_balance in initial_balances:
  143. pl_initial_balance['debit'] += initial_balance['debit']
  144. pl_initial_balance['credit'] += initial_balance['credit']
  145. pl_initial_balance['balance'] += initial_balance['balance']
  146. pl_initial_balance['bal_curr'] += initial_balance['amount_currency']
  147. return pl_initial_balance
  148. def _get_initial_balance_data(
  149. self, account_ids, partner_ids, company_id, date_from,
  150. foreign_currency, only_posted_moves, unaffected_earnings_account,
  151. fy_start_date, analytic_tag_ids, cost_center_ids, extra_domain):
  152. base_domain = []
  153. if company_id:
  154. base_domain += [('company_id', '=', company_id)]
  155. if partner_ids:
  156. base_domain += [('partner_id', 'in', partner_ids)]
  157. if only_posted_moves:
  158. base_domain += [('move_id.state', '=', 'posted')]
  159. if analytic_tag_ids:
  160. base_domain += [('analytic_tag_ids', 'in', analytic_tag_ids)]
  161. if cost_center_ids:
  162. base_domain += [('analytic_account_id', 'in', cost_center_ids)]
  163. if extra_domain:
  164. base_domain += extra_domain
  165. initial_domain_bs = self._get_initial_balances_bs_ml_domain(
  166. account_ids, company_id, date_from, base_domain
  167. )
  168. initial_domain_pl = self._get_initial_balances_pl_ml_domain(
  169. account_ids, company_id, date_from, fy_start_date, base_domain
  170. )
  171. gl_initial_acc = self._get_accounts_initial_balance(
  172. initial_domain_bs, initial_domain_pl
  173. )
  174. initial_domain_acc_prt = self._get_initial_balances_bs_ml_domain(
  175. account_ids, company_id, date_from, base_domain, acc_prt=True
  176. )
  177. gl_initial_acc_prt = self.env['account.move.line'].read_group(
  178. domain=initial_domain_acc_prt,
  179. fields=['account_id', 'partner_id',
  180. 'debit', 'credit', 'balance', 'amount_currency'],
  181. groupby=['account_id', 'partner_id'],
  182. lazy=False
  183. )
  184. gen_ld_data = {}
  185. for gl in gl_initial_acc:
  186. acc_id = gl['account_id'][0]
  187. gen_ld_data[acc_id] = {}
  188. gen_ld_data[acc_id]['id'] = acc_id
  189. gen_ld_data[acc_id]['partners'] = False
  190. gen_ld_data[acc_id]['init_bal'] = {}
  191. gen_ld_data[acc_id]['init_bal']['credit'] = gl['credit']
  192. gen_ld_data[acc_id]['init_bal']['debit'] = gl['debit']
  193. gen_ld_data[acc_id]['init_bal']['balance'] = gl['balance']
  194. gen_ld_data[acc_id]['fin_bal'] = {}
  195. gen_ld_data[acc_id]['fin_bal']['credit'] = gl['credit']
  196. gen_ld_data[acc_id]['fin_bal']['debit'] = gl['debit']
  197. gen_ld_data[acc_id]['fin_bal']['balance'] = gl['balance']
  198. gen_ld_data[acc_id]['init_bal']['bal_curr'] = gl['amount_currency']
  199. gen_ld_data[acc_id]['fin_bal']['bal_curr'] = gl['amount_currency']
  200. partners_data = {}
  201. partners_ids = set()
  202. if gl_initial_acc_prt:
  203. for gl in gl_initial_acc_prt:
  204. if not gl['partner_id']:
  205. prt_id = 0
  206. prt_name = 'Missing Partner'
  207. else:
  208. prt_id = gl['partner_id'][0]
  209. prt_name = gl['partner_id'][1]
  210. prt_name = prt_name._value
  211. if prt_id not in partners_ids:
  212. partners_ids.add(prt_id)
  213. partners_data.update({
  214. prt_id: {'id': prt_id, 'name': prt_name}
  215. })
  216. acc_id = gl['account_id'][0]
  217. gen_ld_data[acc_id][prt_id] = {}
  218. gen_ld_data[acc_id][prt_id]['id'] = prt_id
  219. gen_ld_data[acc_id]['partners'] = True
  220. gen_ld_data[acc_id][prt_id]['init_bal'] = {}
  221. gen_ld_data[acc_id][prt_id][
  222. 'init_bal']['credit'] = gl['credit']
  223. gen_ld_data[acc_id][prt_id][
  224. 'init_bal']['debit'] = gl['debit']
  225. gen_ld_data[acc_id][prt_id][
  226. 'init_bal']['balance'] = gl['balance']
  227. gen_ld_data[acc_id][prt_id]['fin_bal'] = {}
  228. gen_ld_data[acc_id][prt_id][
  229. 'fin_bal']['credit'] = gl['credit']
  230. gen_ld_data[acc_id][prt_id][
  231. 'fin_bal']['debit'] = gl['debit']
  232. gen_ld_data[acc_id][prt_id][
  233. 'fin_bal']['balance'] = gl['balance']
  234. gen_ld_data[acc_id][prt_id]['init_bal'][
  235. 'bal_curr'] = gl['amount_currency']
  236. gen_ld_data[acc_id][prt_id]['fin_bal'][
  237. 'bal_curr'] = gl['amount_currency']
  238. accounts_ids = list(gen_ld_data.keys())
  239. unaffected_id = unaffected_earnings_account
  240. if unaffected_id not in accounts_ids:
  241. accounts_ids.append(unaffected_id)
  242. self._initialize_account(
  243. gen_ld_data, unaffected_id, foreign_currency
  244. )
  245. pl_initial_balance = self._get_pl_initial_balance(
  246. account_ids, company_id, fy_start_date,
  247. foreign_currency, base_domain
  248. )
  249. gen_ld_data[unaffected_id]['init_bal']['debit'] += \
  250. pl_initial_balance['debit']
  251. gen_ld_data[unaffected_id]['init_bal']['credit'] += \
  252. pl_initial_balance['credit']
  253. gen_ld_data[unaffected_id]['init_bal']['balance'] += \
  254. pl_initial_balance['balance']
  255. gen_ld_data[unaffected_id]['fin_bal']['debit'] += \
  256. pl_initial_balance['debit']
  257. gen_ld_data[unaffected_id]['fin_bal']['credit'] += \
  258. pl_initial_balance['credit']
  259. gen_ld_data[unaffected_id]['fin_bal']['balance'] += \
  260. pl_initial_balance['balance']
  261. if foreign_currency:
  262. gen_ld_data[unaffected_id]['init_bal']['bal_curr'] += \
  263. pl_initial_balance['bal_curr']
  264. gen_ld_data[unaffected_id]['fin_bal']['bal_curr'] += \
  265. pl_initial_balance['bal_curr']
  266. return gen_ld_data, partners_data, partner_ids
  267. @api.model
  268. def _get_move_line_data(self, move_line):
  269. move_line_data = {
  270. 'id': move_line['id'],
  271. 'date': move_line['date'],
  272. 'entry': move_line['move_id'][1],
  273. 'entry_id': move_line['move_id'][0],
  274. 'journal_id': move_line['journal_id'][0],
  275. 'account_id': move_line['account_id'][0],
  276. 'partner_id': move_line['partner_id'][0] if
  277. move_line['partner_id'] else False,
  278. 'partner_name': move_line['partner_id'][1] if
  279. move_line['partner_id'] else "",
  280. 'ref': '' if not move_line['ref'] else move_line['ref'],
  281. 'name': '' if not move_line['name'] else move_line['name'],
  282. 'tax_ids': move_line['tax_ids'],
  283. 'debit': move_line['debit'],
  284. 'credit': move_line['credit'],
  285. 'balance': move_line['balance'],
  286. 'bal_curr': move_line['amount_currency'],
  287. 'rec_id': move_line['full_reconcile_id'][0] if
  288. move_line['full_reconcile_id'] else False,
  289. 'rec_name': move_line['full_reconcile_id'][1] if
  290. move_line['full_reconcile_id'] else "",
  291. 'tag_ids': move_line['analytic_tag_ids'],
  292. 'currency_id': move_line['currency_id'],
  293. 'analytic_account': move_line['analytic_account_id'][1] if
  294. move_line['analytic_account_id'] else "",
  295. 'analytic_account_id': move_line['analytic_account_id'][0] if
  296. move_line['analytic_account_id'] else False,
  297. }
  298. if move_line_data['ref'] == move_line_data['name'] or move_line_data[
  299. 'ref'] == '':
  300. ref_label = move_line_data['name']
  301. elif move_line_data['name'] == '':
  302. ref_label = move_line_data['ref']
  303. else:
  304. ref_label = move_line_data['ref'] + str(' - ') + move_line_data[
  305. 'name']
  306. move_line_data.update({'ref_label': ref_label})
  307. return move_line_data
  308. @api.model
  309. def _get_period_domain(
  310. self, account_ids, partner_ids, company_id, only_posted_moves,
  311. date_to, date_from, analytic_tag_ids, cost_center_ids):
  312. domain = [('date', '>=', date_from), ('date', '<=', date_to)]
  313. if account_ids:
  314. domain += [('account_id', 'in', account_ids)]
  315. if company_id:
  316. domain += [('company_id', '=', company_id)]
  317. if partner_ids:
  318. domain += [('partner_id', 'in', partner_ids)]
  319. if only_posted_moves:
  320. domain += [('move_id.state', '=', 'posted')]
  321. if analytic_tag_ids:
  322. domain += [('analytic_tag_ids', 'in', analytic_tag_ids)]
  323. if cost_center_ids:
  324. domain += [('analytic_account_id', 'in', cost_center_ids)]
  325. return domain
  326. @api.model
  327. def _initialize_partner(self, gen_ld_data, acc_id, prt_id,
  328. foreign_currency):
  329. gen_ld_data[acc_id]['partners'] = True
  330. gen_ld_data[acc_id][prt_id] = {}
  331. gen_ld_data[acc_id][prt_id]['id'] = prt_id
  332. gen_ld_data[acc_id][prt_id]['init_bal'] = {}
  333. gen_ld_data[acc_id][prt_id]['init_bal']['balance'] = 0.0
  334. gen_ld_data[acc_id][prt_id]['init_bal']['credit'] = 0.0
  335. gen_ld_data[acc_id][prt_id]['init_bal']['debit'] = 0.0
  336. gen_ld_data[acc_id][prt_id]['fin_bal'] = {}
  337. gen_ld_data[acc_id][prt_id]['fin_bal']['credit'] = 0.0
  338. gen_ld_data[acc_id][prt_id]['fin_bal']['debit'] = 0.0
  339. gen_ld_data[acc_id][prt_id]['fin_bal']['balance'] = 0.0
  340. if foreign_currency:
  341. gen_ld_data[acc_id][prt_id]['init_bal']['bal_curr'] = 0.0
  342. gen_ld_data[acc_id][prt_id]['fin_bal']['bal_curr'] = 0.0
  343. return gen_ld_data
  344. def _initialize_account(self, gen_ld_data, acc_id, foreign_currency):
  345. gen_ld_data[acc_id] = {}
  346. gen_ld_data[acc_id]['id'] = acc_id
  347. gen_ld_data[acc_id]['partners'] = False
  348. gen_ld_data[acc_id]['init_bal'] = {}
  349. gen_ld_data[acc_id]['init_bal']['balance'] = 0.0
  350. gen_ld_data[acc_id]['init_bal']['credit'] = 0.0
  351. gen_ld_data[acc_id]['init_bal']['debit'] = 0.0
  352. gen_ld_data[acc_id]['fin_bal'] = {}
  353. gen_ld_data[acc_id]['fin_bal']['credit'] = 0.0
  354. gen_ld_data[acc_id]['fin_bal']['debit'] = 0.0
  355. gen_ld_data[acc_id]['fin_bal']['balance'] = 0.0
  356. if foreign_currency:
  357. gen_ld_data[acc_id]['init_bal']['bal_curr'] = 0.0
  358. gen_ld_data[acc_id]['fin_bal']['bal_curr'] = 0.0
  359. return gen_ld_data
  360. def _get_reconciled_after_date_to_ids(self, full_reconcile_ids, date_to):
  361. full_reconcile_ids = list(full_reconcile_ids)
  362. domain = [('max_date', '>', date_to),
  363. ('full_reconcile_id', 'in', full_reconcile_ids)]
  364. fields = ['full_reconcile_id']
  365. reconciled_after_date_to = \
  366. self.env['account.partial.reconcile'].search_read(
  367. domain=domain,
  368. fields=fields
  369. )
  370. rec_after_date_to_ids = list(map(
  371. operator.itemgetter('full_reconcile_id'),
  372. reconciled_after_date_to))
  373. rec_after_date_to_ids = [i[0] for i in rec_after_date_to_ids]
  374. return rec_after_date_to_ids
  375. def _get_period_ml_data(
  376. self, account_ids, partner_ids, company_id, foreign_currency,
  377. only_posted_moves, date_from, date_to, partners_data,
  378. gen_ld_data, partners_ids, analytic_tag_ids, cost_center_ids,
  379. extra_domain):
  380. domain = self._get_period_domain(account_ids, partner_ids,
  381. company_id, only_posted_moves,
  382. date_to, date_from,
  383. analytic_tag_ids, cost_center_ids)
  384. if extra_domain:
  385. domain += extra_domain
  386. ml_fields = [
  387. 'id', 'name', 'date', 'move_id', 'journal_id', 'account_id',
  388. 'partner_id', 'debit', 'credit', 'balance', 'currency_id',
  389. 'full_reconcile_id', 'tax_ids', 'analytic_tag_ids',
  390. 'amount_currency', 'ref', 'name', 'analytic_account_id']
  391. move_lines = self.env['account.move.line'].search_read(
  392. domain=domain,
  393. fields=ml_fields)
  394. journal_ids = set()
  395. full_reconcile_ids = set()
  396. taxes_ids = set()
  397. tags_ids = set()
  398. full_reconcile_data = {}
  399. acc_prt_account_ids = self._get_acc_prt_accounts_ids(company_id)
  400. for move_line in move_lines:
  401. journal_ids.add(move_line['journal_id'][0])
  402. for tax_id in move_line['tax_ids']:
  403. taxes_ids.add(tax_id)
  404. for analytic_tag_id in move_line['analytic_tag_ids']:
  405. tags_ids.add(analytic_tag_id)
  406. if move_line['full_reconcile_id']:
  407. rec_id = move_line['full_reconcile_id'][0]
  408. if rec_id not in full_reconcile_ids:
  409. full_reconcile_data.update({
  410. rec_id: {
  411. 'id': rec_id,
  412. 'name': move_line['full_reconcile_id'][1]}
  413. })
  414. full_reconcile_ids.add(rec_id)
  415. acc_id = move_line['account_id'][0]
  416. ml_id = move_line['id']
  417. if move_line['partner_id']:
  418. prt_id = move_line['partner_id'][0]
  419. partner_name = move_line['partner_id'][1]
  420. if acc_id not in gen_ld_data.keys():
  421. gen_ld_data = self._initialize_account(gen_ld_data, acc_id,
  422. foreign_currency)
  423. if acc_id in acc_prt_account_ids:
  424. if not move_line['partner_id']:
  425. prt_id = 0
  426. partner_name = 'Missing Partner'
  427. partners_ids.append(prt_id)
  428. partners_data.update({
  429. prt_id: {'id': prt_id,
  430. 'name': partner_name}
  431. })
  432. if prt_id not in gen_ld_data[acc_id]:
  433. gen_ld_data = self._initialize_partner(
  434. gen_ld_data, acc_id, prt_id, foreign_currency
  435. )
  436. gen_ld_data[acc_id][prt_id][ml_id] = \
  437. self._get_move_line_data(move_line)
  438. gen_ld_data[acc_id][prt_id]['fin_bal']['credit'] += \
  439. move_line['credit']
  440. gen_ld_data[acc_id][prt_id]['fin_bal']['debit'] += \
  441. move_line['debit']
  442. gen_ld_data[acc_id][prt_id]['fin_bal']['balance'] += \
  443. move_line['balance']
  444. if foreign_currency:
  445. gen_ld_data[acc_id][prt_id]['fin_bal']['bal_curr'] += \
  446. move_line['amount_currency']
  447. else:
  448. gen_ld_data[acc_id][ml_id] = self._get_move_line_data(move_line)
  449. gen_ld_data[acc_id]['fin_bal']['credit'] += \
  450. move_line['credit']
  451. gen_ld_data[acc_id]['fin_bal']['debit'] += \
  452. move_line['debit']
  453. gen_ld_data[acc_id]['fin_bal']['balance'] += \
  454. move_line['balance']
  455. if foreign_currency:
  456. gen_ld_data[acc_id]['fin_bal']['bal_curr'] += \
  457. move_line['amount_currency']
  458. journals_data = self._get_journals_data(list(journal_ids))
  459. accounts_data = self._get_accounts_data(gen_ld_data.keys())
  460. taxes_data = self._get_taxes_data(list(taxes_ids))
  461. tags_data = self._get_tags_data(list(tags_ids))
  462. rec_after_date_to_ids = self._get_reconciled_after_date_to_ids(
  463. full_reconcile_data.keys(), date_to)
  464. return gen_ld_data, accounts_data, partners_data, journals_data, \
  465. full_reconcile_data, taxes_data, tags_data, rec_after_date_to_ids
  466. @api.model
  467. def _recalculate_cumul_balance(self, move_lines, last_cumul_balance,
  468. rec_after_date_to_ids):
  469. for move_line in move_lines:
  470. move_line['balance'] += last_cumul_balance
  471. last_cumul_balance = move_line['balance']
  472. if move_line['rec_id'] in rec_after_date_to_ids:
  473. move_line['rec_name'] = '('+_('future')+') '+move_line[
  474. 'rec_name']
  475. return move_lines
  476. def _create_general_ledger(
  477. self, gen_led_data, accounts_data,
  478. show_partner_details, rec_after_date_to_ids, hide_account_at_0):
  479. general_ledger = []
  480. rounding = self.env.user.company_id.currency_id.rounding
  481. for acc_id in gen_led_data.keys():
  482. account = {}
  483. account.update({
  484. 'code': accounts_data[acc_id]['code'],
  485. 'name': accounts_data[acc_id]['name'],
  486. 'type': 'account',
  487. 'currency_id': accounts_data[acc_id]['currency_id'],
  488. 'centralized': accounts_data[acc_id]['centralized'],
  489. }
  490. )
  491. if not gen_led_data[acc_id]['partners']:
  492. move_lines = []
  493. for ml_id in gen_led_data[acc_id].keys():
  494. if not isinstance(ml_id, int):
  495. account.update({ml_id: gen_led_data[acc_id][ml_id]})
  496. else:
  497. move_lines += [gen_led_data[acc_id][ml_id]]
  498. move_lines = sorted(move_lines, key=lambda k: (k['date']))
  499. move_lines = self._recalculate_cumul_balance(
  500. move_lines, gen_led_data[acc_id]['init_bal']['balance'],
  501. rec_after_date_to_ids)
  502. account.update({'move_lines': move_lines})
  503. if hide_account_at_0:
  504. if float_is_zero(gen_led_data[acc_id]['init_bal'][
  505. 'balance'], precision_rounding=rounding) and \
  506. account['move_lines'] == []:
  507. continue
  508. else:
  509. if show_partner_details:
  510. list_partner = []
  511. for prt_id in gen_led_data[acc_id].keys():
  512. partner = {}
  513. move_lines = []
  514. if not isinstance(prt_id, int):
  515. account.update({prt_id: gen_led_data[acc_id][
  516. prt_id]})
  517. else:
  518. for ml_id in gen_led_data[acc_id][prt_id].keys():
  519. if not isinstance(ml_id, int):
  520. partner.update({ml_id: gen_led_data[acc_id][
  521. prt_id][ml_id]})
  522. else:
  523. move_lines += [
  524. gen_led_data[acc_id][prt_id][ml_id]]
  525. move_lines = sorted(move_lines,
  526. key=lambda k: (k['date']))
  527. move_lines = self._recalculate_cumul_balance(
  528. move_lines,
  529. gen_led_data[acc_id][prt_id]['init_bal'][
  530. 'balance'],
  531. rec_after_date_to_ids)
  532. partner.update({'move_lines': move_lines})
  533. if hide_account_at_0:
  534. if float_is_zero(gen_led_data[acc_id][prt_id][
  535. 'init_bal']['balance'],
  536. precision_rounding=rounding) and \
  537. partner['move_lines'] == []:
  538. continue
  539. list_partner += [partner]
  540. account.update({'list_partner': list_partner})
  541. if hide_account_at_0:
  542. if float_is_zero(gen_led_data[acc_id]['init_bal'][
  543. 'balance'], precision_rounding=rounding) and \
  544. account['list_partner'] == []:
  545. continue
  546. else:
  547. move_lines = []
  548. for prt_id in gen_led_data[acc_id].keys():
  549. if not isinstance(prt_id, int):
  550. account.update({prt_id: gen_led_data[acc_id][
  551. prt_id]})
  552. else:
  553. for ml_id in gen_led_data[acc_id][prt_id].keys():
  554. if isinstance(ml_id, int):
  555. move_lines += [
  556. gen_led_data[acc_id][prt_id][ml_id]]
  557. move_lines = sorted(move_lines, key=lambda k: (k['date']))
  558. move_lines = self._recalculate_cumul_balance(
  559. move_lines, gen_led_data[acc_id]['init_bal'][
  560. 'balance'], rec_after_date_to_ids)
  561. account.update({
  562. 'move_lines': move_lines,
  563. 'partners': False,
  564. })
  565. if hide_account_at_0:
  566. if float_is_zero(gen_led_data[acc_id]['init_bal'][
  567. 'balance'], precision_rounding=rounding) and \
  568. account['move_lines'] == []:
  569. continue
  570. general_ledger += [account]
  571. return general_ledger
  572. @api.model
  573. def _calculate_centralization(self, centralized_ml, move_line, date_to):
  574. jnl_id = move_line['journal_id']
  575. month = move_line['date'].month
  576. if jnl_id not in centralized_ml.keys():
  577. centralized_ml[jnl_id] = {}
  578. if month not in centralized_ml[jnl_id].keys():
  579. centralized_ml[jnl_id][month] = {}
  580. last_day_month = \
  581. calendar.monthrange(move_line['date'].year, month)
  582. date = datetime.date(
  583. move_line['date'].year,
  584. month,
  585. last_day_month[1])
  586. if date > date_to:
  587. date = date_to
  588. centralized_ml[jnl_id][month].update({
  589. 'journal_id': jnl_id,
  590. 'ref_label': 'Centralized entries',
  591. 'date': date,
  592. 'debit': 0.0,
  593. 'credit': 0.0,
  594. 'balance': 0.0,
  595. 'bal_curr': 0.0,
  596. 'partner_id': False,
  597. 'rec_id': 0,
  598. 'entry_id': False,
  599. 'tax_ids': [],
  600. 'full_reconcile_id': False,
  601. 'id': False,
  602. 'tag_ids': False,
  603. 'currency_id': False,
  604. 'analytic_account_id': False,
  605. })
  606. centralized_ml[jnl_id][month]['debit'] += move_line['debit']
  607. centralized_ml[jnl_id][month]['credit'] += move_line['credit']
  608. centralized_ml[jnl_id][month]["balance"] += move_line["debit"] - \
  609. move_line["credit"]
  610. centralized_ml[jnl_id][month]['bal_curr'] += move_line['bal_curr']
  611. return centralized_ml
  612. @api.model
  613. def _get_centralized_ml(self, account, date_to):
  614. centralized_ml = {}
  615. if isinstance(date_to, str):
  616. date_to = datetime.datetime.strptime(date_to, '%Y-%m-%d').date()
  617. if account['partners']:
  618. for partner in account['list_partner']:
  619. for move_line in partner['move_lines']:
  620. centralized_ml = self._calculate_centralization(
  621. centralized_ml,
  622. move_line,
  623. date_to,
  624. )
  625. else:
  626. for move_line in account['move_lines']:
  627. centralized_ml = self._calculate_centralization(
  628. centralized_ml,
  629. move_line,
  630. date_to,
  631. )
  632. list_centralized_ml = []
  633. for jnl_id in centralized_ml.keys():
  634. list_centralized_ml += list(centralized_ml[jnl_id].values())
  635. return list_centralized_ml
  636. @api.multi
  637. def _get_report_values(self, docids, data):
  638. wizard_id = data['wizard_id']
  639. company = self.env['res.company'].browse(data['company_id'])
  640. company_id = data['company_id']
  641. date_to = data['date_to']
  642. date_from = data['date_from']
  643. partner_ids = data['partner_ids']
  644. if not partner_ids:
  645. filter_partner_ids = False
  646. else:
  647. filter_partner_ids = True
  648. account_ids = data['account_ids']
  649. analytic_tag_ids = data['analytic_tag_ids']
  650. cost_center_ids = data['cost_center_ids']
  651. show_partner_details = data['show_partner_details']
  652. hide_account_at_0 = data['hide_account_at_0']
  653. foreign_currency = data['foreign_currency']
  654. only_posted_moves = data['only_posted_moves']
  655. unaffected_earnings_account = data['unaffected_earnings_account']
  656. fy_start_date = data['fy_start_date']
  657. extra_domain = data['domain']
  658. gen_ld_data, partners_data, partners_ids = \
  659. self._get_initial_balance_data(
  660. account_ids, partner_ids, company_id, date_from,
  661. foreign_currency, only_posted_moves,
  662. unaffected_earnings_account, fy_start_date, analytic_tag_ids,
  663. cost_center_ids, extra_domain)
  664. centralize = data['centralize']
  665. gen_ld_data, accounts_data, partners_data, journals_data, \
  666. full_reconcile_data, taxes_data, \
  667. tags_data, rec_after_date_to_ids = \
  668. self._get_period_ml_data(
  669. account_ids, partner_ids, company_id, foreign_currency,
  670. only_posted_moves, date_from, date_to,
  671. partners_data, gen_ld_data, partners_ids,
  672. analytic_tag_ids, cost_center_ids, extra_domain)
  673. general_ledger = self._create_general_ledger(
  674. gen_ld_data, accounts_data,
  675. show_partner_details, rec_after_date_to_ids, hide_account_at_0
  676. )
  677. if centralize:
  678. for account in general_ledger:
  679. if account['centralized']:
  680. centralized_ml = self._get_centralized_ml(
  681. account, date_to)
  682. account['move_lines'] = centralized_ml
  683. account["move_lines"] = self._recalculate_cumul_balance(
  684. account["move_lines"],
  685. gen_ld_data[account["id"]]["init_bal"]["balance"],
  686. rec_after_date_to_ids
  687. )
  688. if account['partners']:
  689. account['partners'] = False
  690. del account['list_partner']
  691. general_ledger = sorted(general_ledger, key=lambda k: k['code'])
  692. return {
  693. 'doc_ids': [wizard_id],
  694. 'doc_model': 'general.ledger.report.wizard',
  695. 'docs': self.env['general.ledger.report.wizard'].browse(wizard_id),
  696. 'foreign_currency': data['foreign_currency'],
  697. 'company_name': company.display_name,
  698. 'company_currency': company.currency_id,
  699. 'currency_name': company.currency_id.name,
  700. 'date_from': data['date_from'],
  701. 'date_to': data['date_to'],
  702. 'only_posted_moves': data['only_posted_moves'],
  703. 'hide_account_at_0': data['hide_account_at_0'],
  704. 'show_analytic_tags': data['show_analytic_tags'],
  705. 'show_cost_center': data['show_cost_center'],
  706. 'general_ledger': general_ledger,
  707. 'accounts_data': accounts_data,
  708. 'partners_data': partners_data,
  709. 'journals_data': journals_data,
  710. 'full_reconcile_data': full_reconcile_data,
  711. 'taxes_data': taxes_data,
  712. 'centralize': centralize,
  713. 'tags_data': tags_data,
  714. 'filter_partner_ids': filter_partner_ids,
  715. }