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.

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