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.

973 lines
45 KiB

  1. # -*- coding: utf-8 -*-
  2. import calendar
  3. import odoo.addons.decimal_precision as dp
  4. from datetime import datetime, timedelta
  5. from odoo import api, models, fields, _
  6. from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
  7. from odoo.exceptions import AccessError, UserError
  8. D_LEDGER = {'general': {'name': _('General Ledger'),
  9. 'group_by': 'account_id',
  10. 'model': 'account.account',
  11. 'short': 'code',
  12. },
  13. 'partner': {'name': _('Partner Ledger'),
  14. 'group_by': 'partner_id',
  15. 'model': 'res.partner',
  16. 'short': 'name',
  17. },
  18. 'journal': {'name': _('Journal Ledger'),
  19. 'group_by': 'journal_id',
  20. 'model': 'account.journal',
  21. 'short': 'code',
  22. },
  23. 'open': {'name': _('Open Ledger'),
  24. 'group_by': 'account_id',
  25. 'model': 'account.account',
  26. 'short': 'code',
  27. },
  28. 'aged': {'name': _('Aged Balance'),
  29. 'group_by': 'partner_id',
  30. 'model': 'res.partner',
  31. 'short': 'name',
  32. },
  33. }
  34. class AccountStandardLedgerPeriode(models.TransientModel):
  35. _name = 'account.report.standard.ledger.periode'
  36. name = fields.Char('Name')
  37. date_from = fields.Datetime('Date from')
  38. date_to = fields.Datetime('Date to')
  39. class AccountStandardLedgerReport(models.TransientModel):
  40. _name = 'account.report.standard.ledger.report'
  41. name = fields.Char()
  42. report_object_ids = fields.One2many('account.report.standard.ledger.report.object', 'report_id')
  43. report_name = fields.Char()
  44. line_total_ids = fields.Many2many('account.report.standard.ledger.line', relation='table_standard_report_line_total')
  45. line_super_total_id = fields.Many2one('account.report.standard.ledger.line')
  46. print_time = fields.Char()
  47. date_from = fields.Date(string='Start Date', help='Use to compute initial balance.')
  48. date_to = fields.Date(string='End Date', help='Use to compute the entrie matched with futur.')
  49. class AccountStandardLedgerLines(models.TransientModel):
  50. _name = 'account.report.standard.ledger.line'
  51. _order = 'id' # ,move_id,account_id #type,date,move_line_id_id,
  52. _rec_name = 'move_id'
  53. report_id = fields.Many2one('account.report.standard.ledger.report')
  54. account_id = fields.Many2one('account.account', 'Account')
  55. type = fields.Selection([('0_init', 'Initial'), ('1_init_line', 'Init Line'), ('2_line', 'Line'), ('3_compact',
  56. 'Compacted'), ('4_total', 'Total'), ('5_super_total', 'Super Total')], string='Type')
  57. type_view = fields.Selection([('init', 'Init'), ('normal', 'Normal'), ('total', 'Total')])
  58. journal_id = fields.Many2one('account.journal', 'Journal')
  59. partner_id = fields.Many2one('res.partner', 'Partner')
  60. group_by_key = fields.Char()
  61. move_id = fields.Many2one('account.move', 'Entrie')
  62. move_line_id = fields.Many2one('account.move.line')
  63. date = fields.Date()
  64. date_maturity = fields.Date('Due Date')
  65. debit = fields.Float(default=0.0, digits=dp.get_precision('Account'))
  66. credit = fields.Float(default=0.0, digits=dp.get_precision('Account'))
  67. balance = fields.Float(default=0.0, digits=dp.get_precision('Account'))
  68. cumul_balance = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='Balance')
  69. full_reconcile_id = fields.Many2one('account.full.reconcile', 'Match.')
  70. reconciled = fields.Boolean('Reconciled')
  71. report_object_id = fields.Many2one('account.report.standard.ledger.report.object')
  72. current = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='Not due')
  73. age_30_days = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='30 days')
  74. age_60_days = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='60 days')
  75. age_90_days = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='90 days')
  76. age_120_days = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='120 days')
  77. older = fields.Float(default=0.0, digits=dp.get_precision('Account'), string='Older')
  78. company_currency_id = fields.Many2one('res.currency')
  79. @api.model
  80. def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
  81. res = super(AccountStandardLedgerLines, self).read_group(domain, fields, groupby, offset, limit=limit, orderby=orderby, lazy=lazy)
  82. if 'cumul_balance' in fields and 'debit' in fields and 'credit' in fields:
  83. for line in res:
  84. line['cumul_balance'] = line['debit'] - line['credit']
  85. return res
  86. class AccountStandardLedgerReportObject(models.TransientModel):
  87. _name = 'account.report.standard.ledger.report.object'
  88. _order = 'name, id'
  89. name = fields.Char()
  90. object_id = fields.Integer()
  91. report_id = fields.Many2one('account.report.standard.ledger.report')
  92. line_ids = fields.One2many('account.report.standard.ledger.line', 'report_object_id')
  93. account_id = fields.Many2one('account.account', 'Account')
  94. journal_id = fields.Many2one('account.journal', 'Journal')
  95. partner_id = fields.Many2one('res.partner', 'Partner')
  96. class AccountStandardLedger(models.TransientModel):
  97. _name = 'account.report.standard.ledger'
  98. _description = 'Account Standard Ledger'
  99. def _get_periode_date(self):
  100. lang_code = self.env.user.lang or 'en_US'
  101. date_format = self.env['res.lang']._lang_get(lang_code).date_format
  102. today_year = fields.datetime.now().year
  103. last_day = self.company_id.fiscalyear_last_day or 31
  104. last_month = self.company_id.fiscalyear_last_month or 12
  105. periode_obj = self.env['account.report.standard.ledger.periode']
  106. periode_obj.search([]).unlink()
  107. periode_ids = periode_obj
  108. for year in range(today_year, today_year - 4, -1):
  109. date_from = datetime(year - 1, last_month, last_day) + timedelta(days=1)
  110. date_to = datetime(year, last_month, last_day)
  111. user_periode = "%s - %s" % (date_from.strftime(date_format),
  112. date_to.strftime(date_format),
  113. )
  114. vals = {
  115. 'name': user_periode,
  116. 'date_from': date_from.strftime(DEFAULT_SERVER_DATE_FORMAT),
  117. 'date_to': date_to.strftime(DEFAULT_SERVER_DATE_FORMAT), }
  118. periode_ids += periode_obj.create(vals)
  119. return False
  120. name = fields.Char(default='Standard Report')
  121. type_ledger = fields.Selection([('general', 'General Ledger'), ('partner', 'Partner Ledger'), ('journal', 'Journal Ledger'), ('open', 'Open Ledger'), ('aged', 'Aged Balance')], string='Type', default='general', required=True,
  122. help=' * General Ledger : Journal entries group by account\n'
  123. ' * Partner Leger : Journal entries group by partner, with only payable/recevable accounts\n'
  124. ' * Journal Ledger : Journal entries group by journal, without initial balance\n'
  125. ' * Open Ledger : Openning journal at Start date\n')
  126. summary = fields.Boolean('Trial Balance', default=False,
  127. help=' * Check : generate a trial balance.\n'
  128. ' * Uncheck : detail report.\n')
  129. amount_currency = fields.Boolean("With Currency", help="It adds the currency column on report if the currency differs from the company currency.")
  130. reconciled = fields.Boolean('With Reconciled Entries', default=True,
  131. help='Only for entrie with a payable/receivable account.\n'
  132. ' * Check this box to see un-reconcillied and reconciled entries with payable.\n'
  133. ' * Uncheck to see only un-reconcillied entries. Can be use only with parnter ledger.\n')
  134. partner_select_ids = fields.Many2many(comodel_name='res.partner', string='Partners', domain=['|', ('is_company', '=', True), ('parent_id', '=', False)], help='If empty, get all partners')
  135. account_methode = fields.Selection([('include', 'Include'), ('exclude', 'Exclude')], string="Methode")
  136. account_in_ex_clude = fields.Many2many(comodel_name='account.account', string='Accounts', help='If empty, get all accounts')
  137. init_balance_history = fields.Boolean('Initial balance with history.', default=True,
  138. help=' * Check this box if you need to report all the debit and the credit sum before the Start Date.\n'
  139. ' * Uncheck this box to report only the balance before the Start Date\n')
  140. company_id = fields.Many2one('res.company', string='Company', readonly=True, default=lambda self: self.env.user.company_id)
  141. company_currency_id = fields.Many2one('res.currency', related='company_id.currency_id', string="Company Currency", readonly=True,
  142. help='Utility field to express amount currency', store=True)
  143. journal_ids = fields.Many2many('account.journal', string='Journals', required=True, default=lambda self: self.env['account.journal'].search([('company_id', '=', self.env.user.company_id.id)]),
  144. help='Select journal, for the Open Ledger you need to set all journals.')
  145. date_from = fields.Date(string='Start Date', help='Use to compute initial balance.')
  146. date_to = fields.Date(string='End Date', help='Use to compute the entrie matched with futur.')
  147. target_move = fields.Selection([('posted', 'All Posted Entries'),
  148. ('all', 'All Entries'),
  149. ], string='Target Moves', required=True, default='posted')
  150. periode_date = fields.Many2one('account.report.standard.ledger.periode', 'Periode', default=_get_periode_date, help="Auto complete Start and End date.")
  151. month_selec = fields.Selection([(1, '01 Junary'), (2, '02 Febuary'), (3, '03 March'), (4, '04 April'), (5, '05 May'), (6, '06 June'),
  152. (7, '07 Jully'), (8, '08 August'), (9, '09 September'), (10, '10 October'), (11, '11 November'), (12, '12 December')],
  153. string='Month')
  154. result_selection = fields.Selection([('customer', 'Customer'),
  155. ('supplier', 'Supplier'),
  156. ('customer_supplier', 'Receivable and Payable Accounts')
  157. ], string="Partner's", required=True, default='supplier')
  158. report_name = fields.Char('Report Name')
  159. compact_account = fields.Boolean('Compacte account.', default=False)
  160. report_id = fields.Many2one('account.report.standard.ledger.report')
  161. account_ids = fields.Many2many('account.account', relation='table_standard_report_accounts')
  162. partner_ids = fields.Many2many('res.partner', relation='table_standard_report_partner')
  163. type = fields.Selection([('account', 'Account'), ('partner', 'Partner'), ('journal', 'Journal')])
  164. @api.onchange('account_in_ex_clude')
  165. def on_change_summary(self):
  166. if self.account_in_ex_clude:
  167. self.account_methode = 'include'
  168. else:
  169. self.account_methode = False
  170. @api.onchange('type_ledger')
  171. def on_change_type_ledger(self):
  172. if self.type_ledger in ('partner', 'journal', 'open', 'aged'):
  173. self.compact_account = False
  174. if self.type_ledger == 'aged':
  175. self.date_from = False
  176. self.reconciled = False
  177. else:
  178. self.on_change_periode_date()
  179. self.on_change_month_selec()
  180. if self.type_ledger not in ('partner', 'aged',):
  181. self.reconciled = True
  182. return {'domain': {'account_in_ex_clude': []}}
  183. self.account_in_ex_clude = False
  184. if self.result_selection == 'suplier':
  185. return {'domain': {'account_in_ex_clude': [('type_third_parties', '=', 'supplier')]}}
  186. if self.result_selection == 'customer':
  187. return {'domain': {'account_in_ex_clude': [('type_third_parties', '=', 'customer')]}}
  188. return {'domain': {'account_in_ex_clude': [('type_third_parties', 'in', ('supplier', 'customer'))]}}
  189. @api.onchange('periode_date')
  190. def on_change_periode_date(self):
  191. if self.periode_date:
  192. self.date_from = self.periode_date.date_from
  193. self.date_to = self.periode_date.date_to
  194. if self.month_selec:
  195. self.on_change_month_selec()
  196. @api.onchange('month_selec')
  197. def on_change_month_selec(self):
  198. if self.periode_date and self.month_selec:
  199. date_from = datetime.strptime(self.periode_date.date_from, DEFAULT_SERVER_DATETIME_FORMAT)
  200. date_from = datetime(date_from.year, self.month_selec, 1)
  201. date_to = datetime(date_from.year, self.month_selec, calendar.monthrange(date_from.year, self.month_selec)[1])
  202. self.date_from = date_from.strftime(DEFAULT_SERVER_DATE_FORMAT)
  203. self.date_to = date_to.strftime(DEFAULT_SERVER_DATE_FORMAT)
  204. elif self.periode_date and not self.month_selec:
  205. self.on_change_periode_date()
  206. def action_view_lines(self):
  207. self.ensure_one()
  208. self._compute_data()
  209. return {
  210. 'name': _("Ledger Lines"),
  211. 'view_type': 'form',
  212. 'view_mode': 'tree,form',
  213. 'views': [(self.env.ref('account_standard_report.view_aged_tree').id if self.type_ledger == 'aged' else False, 'tree'), (False, 'form')],
  214. 'res_model': 'account.report.standard.ledger.line',
  215. 'type': 'ir.actions.act_window',
  216. 'domain': "[('report_id','=',%s),('type','not in',('5_super_total','4_total'))]" % (self.report_id.id),
  217. 'context': {'search_default_%s' % self.type_ledger: 1, 'read_report_id': self.report_id.id},
  218. 'target': 'current',
  219. }
  220. def print_pdf_report(self):
  221. self.ensure_one()
  222. self._compute_data()
  223. return self.env['report'].get_action(self, 'account_standard_report.report_account_standard_report')
  224. def print_excel_report(self):
  225. self.ensure_one()
  226. self._compute_data()
  227. return self.env['report'].get_action(self, 'account_standard_report.report_account_standard_excel')
  228. def _pre_compute(self):
  229. lang_code = self.env.context.get('lang') or 'en_US'
  230. date_format = self.env['res.lang']._lang_get(lang_code).date_format
  231. time_format = self.env['res.lang']._lang_get(lang_code).time_format
  232. vals = {'report_name': self._get_name_report(),
  233. 'name': self._get_name_report(),
  234. 'print_time': '%s' % fields.Datetime.context_timestamp(self.with_context(tz=self.env.user.tz), datetime.now()).strftime(('%s %s') % (date_format, time_format)),
  235. 'date_to': self.date_to if self.date_to else "2099-01-01",
  236. 'date_from': self.date_from if self.date_from else "1970-01-01",
  237. }
  238. self.report_id = self.env['account.report.standard.ledger.report'].create(vals)
  239. self.account_ids = self._search_account()
  240. self.partner_ids = self._search_partner()
  241. if self.type_ledger in ('general', 'open'):
  242. self.type = 'account'
  243. elif self.type_ledger in ('partner', 'aged'):
  244. self.type = 'partner'
  245. else:
  246. self.type = 'journal'
  247. if self.type_ledger in ('partner', 'journal', 'open', 'aged'):
  248. self.compact_account = False
  249. if self.type_ledger not in ('partner', 'aged',):
  250. self.reconciled = True
  251. self.partner_select_ids = False
  252. def _compute_data(self):
  253. if not self.user_has_groups('account.group_account_user'):
  254. raise UserError(_('Your are not an accountant !'))
  255. self._pre_compute()
  256. self._sql_report_object()
  257. if self.type == 'account':
  258. self._sql_unaffected_earnings()
  259. if self.type in ('account, partner'):
  260. if self.type_ledger != 'aged':
  261. self._sql_init_balance()
  262. self._sql_lines()
  263. if self.compact_account and self.type_ledger == 'general':
  264. self._sql_lines_compacted()
  265. self._sql_total()
  266. self._sql_super_total()
  267. self.refresh()
  268. # complet total line
  269. line_obj = self.env['account.report.standard.ledger.line']
  270. self.report_id.line_total_ids = line_obj.search([('report_id', '=', self.report_id.id), ('type', '=', '4_total')])
  271. self.report_id.line_super_total_id = line_obj.search([('report_id', '=', self.report_id.id), ('type', '=', '5_super_total')], limit=1)
  272. self._format_total()
  273. def _sql_report_object(self):
  274. query = """INSERT INTO account_report_standard_ledger_report_object
  275. (report_id, create_uid, create_date, object_id, name, account_id, partner_id, journal_id)
  276. SELECT DISTINCT
  277. %s AS report_id,
  278. %s AS create_uid,
  279. NOW() AS create_date,
  280. CASE
  281. WHEN %s = 'account' THEN aml.account_id
  282. WHEN %s = 'partner' THEN aml.partner_id
  283. ELSE aml.journal_id
  284. END AS object_id,
  285. CASE
  286. WHEN %s = 'account' THEN acc.code || ' ' || acc.name
  287. WHEN %s = 'partner' THEN CASE WHEN rep.ref IS NULL THEN rep.name ELSE rep.ref || ' ' || rep.name END
  288. ELSE acj.code || ' ' || acj.name
  289. END AS name,
  290. CASE WHEN %s = 'account' THEN aml.account_id ELSE NULL END AS account_id,
  291. CASE WHEN %s = 'partner' THEN aml.partner_id ELSE NULL END AS partner_id,
  292. CASE WHEN %s = 'journal' THEN aml.journal_id ELSE NULL END AS journal_id
  293. FROM
  294. account_move_line aml
  295. LEFT JOIN account_account acc ON (acc.id = aml.account_id)
  296. LEFT JOIN res_partner rep ON (rep.id = aml.partner_id)
  297. LEFT JOIN account_journal acj ON (acj.id = aml.journal_id)
  298. WHERE
  299. aml.company_id = %s
  300. AND aml.journal_id IN %s
  301. AND aml.account_id IN %s
  302. AND (%s in ('account', 'journal') OR aml.partner_id IN %s)
  303. ORDER BY
  304. name
  305. """
  306. params = [
  307. # SELECT
  308. self.report_id.id,
  309. self.env.uid,
  310. self.type, self.type, self.type, self.type,
  311. self.type, self.type, self.type,
  312. # WHERE
  313. self.company_id.id,
  314. tuple(self.journal_ids.ids) if self.journal_ids else (None,),
  315. tuple(self.account_ids.ids) if self.account_ids else (None,),
  316. self.type,
  317. tuple(self.partner_ids.ids) if self.partner_ids else (None,),
  318. ]
  319. self.env.cr.execute(query, tuple(params))
  320. def _sql_unaffected_earnings(self):
  321. company = self.company_id
  322. unaffected_earnings_account = self.env['account.account'].search([('company_id', '=', company.id), ('user_type_id', '=', self.env.ref('account.data_unaffected_earnings').id)], limit=1)
  323. if unaffected_earnings_account not in self.account_ids:
  324. return
  325. report_object_id = self.report_id.report_object_ids.filtered(lambda x: x.object_id == unaffected_earnings_account.id)
  326. if not report_object_id:
  327. report_object_id = self.report_id.report_object_ids.create({'report_id': self.report_id.id,
  328. 'object_id': unaffected_earnings_account.id,
  329. 'name': '%s %s' % (unaffected_earnings_account.code, unaffected_earnings_account.name),
  330. 'account_id': unaffected_earnings_account.id})
  331. query = """
  332. INSERT INTO account_report_standard_ledger_line
  333. (report_id, create_uid, create_date, account_id, type, type_view, date, debit, credit, balance, cumul_balance, company_currency_id, reconciled, report_object_id)
  334. SELECT
  335. %s AS report_id,
  336. %s AS create_uid,
  337. NOW() AS create_date,
  338. %s AS account_id,
  339. '0_init' AS type,
  340. 'init' AS type_view,
  341. %s AS date,
  342. CASE WHEN %s THEN COALESCE(SUM(aml.debit), 0) ELSE CASE WHEN COALESCE(SUM(aml.balance), 0) <= 0 THEN 0 ELSE COALESCE(SUM(aml.balance), 0) END END AS debit,
  343. CASE WHEN %s THEN COALESCE(SUM(aml.credit), 0) ELSE CASE WHEN COALESCE(SUM(aml.balance), 0) >= 0 THEN 0 ELSE COALESCE(-SUM(aml.balance), 0) END END AS credit,
  344. COALESCE(SUM(aml.balance), 0) AS balance,
  345. COALESCE(SUM(aml.balance), 0) AS cumul_balance,
  346. %s AS company_currency_id,
  347. FALSE as reconciled,
  348. %s AS report_object_id
  349. FROM
  350. account_move_line aml
  351. LEFT JOIN account_account acc ON (aml.account_id = acc.id)
  352. LEFT JOIN account_account_type acc_type ON (acc.user_type_id = acc_type.id)
  353. LEFT JOIN account_move m ON (aml.move_id = m.id)
  354. WHERE
  355. m.state IN %s
  356. AND aml.company_id = %s
  357. AND aml.date < %s
  358. AND acc_type.include_initial_balance = FALSE
  359. HAVING
  360. CASE
  361. WHEN %s = FALSE THEN ABS(SUM(aml.balance)) > %s
  362. ELSE ABS(SUM(aml.debit)) > %s OR ABS(SUM(aml.debit)) > %s OR ABS(SUM(aml.balance)) > %s
  363. END
  364. """
  365. date_from_fiscal = self.company_id.compute_fiscalyear_dates(datetime.strptime(self.report_id.date_from, DEFAULT_SERVER_DATE_FORMAT))['date_from']
  366. params = [
  367. # SELECT
  368. self.report_id.id,
  369. self.env.uid,
  370. unaffected_earnings_account.id,
  371. date_from_fiscal,
  372. self.init_balance_history,
  373. self.init_balance_history,
  374. self.company_currency_id.id,
  375. report_object_id.id,
  376. # WHERE
  377. ('posted',) if self.target_move == 'posted' else ('posted', 'draft',),
  378. company.id,
  379. self.report_id.date_from,
  380. # HAVING
  381. self.init_balance_history,
  382. self.company_currency_id.rounding, self.company_currency_id.rounding, self.company_currency_id.rounding, self.company_currency_id.rounding,
  383. ]
  384. self.env.cr.execute(query, tuple(params))
  385. def _sql_init_balance(self):
  386. company = self.company_id
  387. # initial balance partner
  388. query = """
  389. INSERT INTO account_report_standard_ledger_line
  390. (report_id, create_uid, create_date, account_id, partner_id, group_by_key, type, type_view, date, debit, credit, balance, cumul_balance, company_currency_id, reconciled, report_object_id)
  391. WITH matching_in_futur_before_init (id) AS
  392. (
  393. SELECT DISTINCT
  394. afr.id as id
  395. FROM
  396. account_full_reconcile afr
  397. INNER JOIN account_move_line aml ON aml.full_reconcile_id=afr.id
  398. WHERE
  399. aml.company_id = %s
  400. AND aml.date >= %s
  401. )
  402. SELECT
  403. %s AS report_id,
  404. %s AS create_uid,
  405. NOW() AS create_date,
  406. MIN(aml.account_id),
  407. CASE WHEN %s = 'partner' THEN MIN(aml.partner_id) ELSE NULL END,
  408. (CASE
  409. WHEN %s = 'account' THEN '-' || aml.account_id
  410. ELSE aml.partner_id || '-' || aml.account_id
  411. END) AS group_by_key,
  412. '0_init' AS type,
  413. 'init' AS type_view,
  414. %s AS date,
  415. CASE WHEN %s THEN COALESCE(SUM(aml.debit), 0) ELSE CASE WHEN COALESCE(SUM(aml.balance), 0) <= 0 THEN 0 ELSE COALESCE(SUM(aml.balance), 0) END END AS debit,
  416. CASE WHEN %s THEN COALESCE(SUM(aml.credit), 0) ELSE CASE WHEN COALESCE(SUM(aml.balance), 0) >= 0 THEN 0 ELSE COALESCE(-SUM(aml.balance), 0) END END AS credit,
  417. COALESCE(SUM(aml.balance), 0) AS balance,
  418. COALESCE(SUM(aml.balance), 0) AS cumul_balance,
  419. %s AS company_currency_id,
  420. FALSE as reconciled,
  421. MIN(ro.id) AS report_object_id
  422. FROM
  423. account_report_standard_ledger_report_object ro
  424. INNER JOIN account_move_line aml ON (CASE WHEN %s = 'account' THEN aml.account_id = ro.object_id ELSE aml.partner_id = ro.object_id END)
  425. LEFT JOIN account_account acc ON (aml.account_id = acc.id)
  426. LEFT JOIN account_account_type acc_type ON (acc.user_type_id = acc_type.id)
  427. LEFT JOIN account_move m ON (aml.move_id = m.id)
  428. LEFT JOIN matching_in_futur_before_init mif ON (aml.full_reconcile_id = mif.id)
  429. WHERE
  430. m.state IN %s
  431. AND ro.report_id = %s
  432. AND aml.company_id = %s
  433. AND aml.date < %s
  434. AND acc_type.include_initial_balance = TRUE
  435. AND aml.journal_id IN %s
  436. AND aml.account_id IN %s
  437. AND (%s in ('account', 'journal') OR aml.partner_id IN %s)
  438. AND ((%s AND acc.compacted = TRUE) OR acc.type_third_parties = 'no' OR (aml.full_reconcile_id IS NOT NULL AND mif.id IS NULL))
  439. GROUP BY
  440. group_by_key
  441. HAVING
  442. CASE
  443. WHEN %s = FALSE THEN ABS(SUM(aml.balance)) > %s
  444. ELSE ABS(SUM(aml.debit)) > %s OR ABS(SUM(aml.debit)) > %s OR ABS(SUM(aml.balance)) > %s
  445. END
  446. """
  447. params = [
  448. # matching_in_futur
  449. company.id,
  450. self.report_id.date_from,
  451. # init_account_table
  452. # SELECT
  453. self.report_id.id,
  454. self.env.uid,
  455. self.type, self.type,
  456. self.report_id.date_from,
  457. self.init_balance_history,
  458. self.init_balance_history,
  459. self.company_currency_id.id,
  460. # FROM
  461. self.type,
  462. # WHERE
  463. ('posted',) if self.target_move == 'posted' else ('posted', 'draft',),
  464. self.report_id.id,
  465. company.id,
  466. self.report_id.date_from,
  467. tuple(self.journal_ids.ids) if self.journal_ids else (None,),
  468. tuple(self.account_ids.ids) if self.account_ids else (None,),
  469. self.type,
  470. tuple(self.partner_ids.ids) if self.partner_ids else (None,),
  471. self.compact_account,
  472. # HAVING
  473. self.init_balance_history,
  474. self.company_currency_id.rounding, self.company_currency_id.rounding, self.company_currency_id.rounding, self.company_currency_id.rounding,
  475. ]
  476. self.env.cr.execute(query, tuple(params))
  477. def _sql_lines(self):
  478. # lines_table
  479. query = """
  480. INSERT INTO account_report_standard_ledger_line
  481. (report_id, create_uid, create_date, account_id, type, type_view, journal_id, partner_id, move_id, move_line_id, date, date_maturity, debit, credit, balance, full_reconcile_id, reconciled, report_object_id, cumul_balance, current, age_30_days, age_60_days, age_90_days, age_120_days, older, company_currency_id)
  482. WITH matching_in_futur_before_init (id) AS
  483. (
  484. SELECT DISTINCT
  485. afr.id AS id
  486. FROM
  487. account_full_reconcile afr
  488. INNER JOIN account_move_line aml ON aml.full_reconcile_id=afr.id
  489. WHERE
  490. aml.company_id = %s
  491. AND aml.date >= %s
  492. ),
  493. matching_in_futur_after_date_to (id) AS
  494. (
  495. SELECT DISTINCT
  496. afr.id AS id
  497. FROM
  498. account_full_reconcile afr
  499. INNER JOIN account_move_line aml ON aml.full_reconcile_id = afr.id
  500. WHERE
  501. aml.company_id = %s
  502. AND aml.date > %s
  503. ),
  504. initial_balance (id, balance) AS
  505. (
  506. SELECT
  507. MIN(report_object_id) AS id,
  508. COALESCE(SUM(balance), 0) AS balance
  509. FROM
  510. account_report_standard_ledger_line
  511. WHERE
  512. report_id = %s
  513. AND type = '0_init'
  514. GROUP BY
  515. report_object_id
  516. ),
  517. date_range AS
  518. (
  519. SELECT
  520. %s AS date_current,
  521. DATE %s - INTEGER '30' AS date_less_30_days,
  522. DATE %s - INTEGER '60' AS date_less_60_days,
  523. DATE %s - INTEGER '90' AS date_less_90_days,
  524. DATE %s - INTEGER '120' AS date_less_120_days,
  525. DATE %s - INTEGER '150' AS date_older
  526. )
  527. SELECT
  528. %s AS report_id,
  529. %s AS create_uid,
  530. NOW() AS create_date,
  531. aml.account_id,
  532. CASE WHEN aml.date >= %s THEN '2_line' ELSE '1_init_line' END AS type,
  533. CASE WHEN aml.date >= %s THEN 'normal' ELSE 'init' END AS type_view,
  534. aml.journal_id,
  535. aml.partner_id,
  536. aml.move_id,
  537. aml.id,
  538. aml.date,
  539. aml.date_maturity,
  540. aml.debit,
  541. aml.credit,
  542. aml.balance,
  543. aml.full_reconcile_id,
  544. CASE WHEN aml.full_reconcile_id is NOT NULL AND NOT mifad.id IS NOT NULL THEN TRUE ELSE FALSE END AS reconciled,
  545. ro.id AS report_object_id,
  546. CASE
  547. WHEN %s = 'account' THEN COALESCE(init.balance, 0) + (SUM(aml.balance) OVER (PARTITION BY aml.account_id ORDER BY aml.account_id, aml.date, aml.id))
  548. WHEN %s = 'partner' THEN COALESCE(init.balance, 0) + (SUM(aml.balance) OVER (PARTITION BY aml.partner_id ORDER BY aml.partner_id, aml.date, aml.id))
  549. ELSE SUM(aml.balance) OVER (PARTITION BY aml.journal_id ORDER BY aml.journal_id, aml.date, aml.id)
  550. END AS cumul_balance,
  551. CASE WHEN aml.date_maturity > date_range.date_less_30_days THEN aml.balance END AS current,
  552. CASE WHEN aml.date_maturity > date_range.date_less_60_days AND aml.date_maturity <= date_range.date_less_30_days THEN aml.balance END AS age_30_days,
  553. CASE WHEN aml.date_maturity > date_range.date_less_90_days AND aml.date_maturity <= date_range.date_less_60_days THEN aml.balance END AS age_60_days,
  554. CASE WHEN aml.date_maturity > date_range.date_less_120_days AND aml.date_maturity <= date_range.date_less_90_days THEN aml.balance END AS age_90_days,
  555. CASE WHEN aml.date_maturity > date_range.date_older AND aml.date_maturity <= date_range.date_less_120_days THEN aml.balance END AS age_120_days,
  556. CASE WHEN aml.date_maturity <= date_range.date_older THEN aml.balance END AS older,
  557. %s AS company_currency_id
  558. FROM
  559. date_range,
  560. account_report_standard_ledger_report_object ro
  561. INNER JOIN account_move_line aml ON (
  562. CASE
  563. WHEN %s = 'account' THEN aml.account_id = ro.object_id
  564. WHEN %s = 'partner' THEN aml.partner_id = ro.object_id
  565. ELSE aml.journal_id = ro.object_id
  566. END)
  567. LEFT JOIN account_journal j ON (aml.journal_id = j.id)
  568. LEFT JOIN account_account acc ON (aml.account_id = acc.id)
  569. LEFT JOIN account_account_type acc_type ON (acc.user_type_id = acc_type.id)
  570. LEFT JOIN account_move m ON (aml.move_id = m.id)
  571. LEFT JOIN matching_in_futur_before_init mif ON (aml.full_reconcile_id = mif.id)
  572. LEFT JOIN matching_in_futur_after_date_to mifad ON (aml.full_reconcile_id = mifad.id)
  573. LEFT JOIN initial_balance init ON (ro.id = init.id)
  574. WHERE
  575. m.state IN %s
  576. AND ro.report_id = %s
  577. AND aml.company_id = %s
  578. AND (CASE
  579. WHEN %s = 'journal' THEN aml.date >= %s
  580. WHEN aml.date >= %s THEN %s != 'open'
  581. ELSE acc.type_third_parties IN ('supplier', 'customer') AND (aml.full_reconcile_id IS NULL OR mif.id IS NOT NULL)
  582. END)
  583. AND aml.date <= %s
  584. AND aml.journal_id IN %s
  585. AND aml.account_id IN %s
  586. AND (%s IN ('account','journal') OR aml.partner_id IN %s)
  587. AND NOT (%s AND acc.compacted = TRUE)
  588. AND (%s OR NOT (aml.full_reconcile_id is NOT NULL AND NOT mifad.id IS NOT NULL))
  589. ORDER BY
  590. aml.date, aml.id
  591. """
  592. params = [
  593. # matching_in_futur init
  594. self.company_id.id,
  595. self.report_id.date_from,
  596. # matching_in_futur date_to
  597. self.company_id.id,
  598. self.report_id.date_to,
  599. # initial_balance
  600. self.report_id.id,
  601. # date_range
  602. self.report_id.date_to, self.report_id.date_to, self.report_id.date_to, self.report_id.date_to, self.report_id.date_to, self.report_id.date_to,
  603. # lines_table
  604. # SELECT
  605. self.report_id.id,
  606. self.env.uid,
  607. self.report_id.date_from,
  608. self.report_id.date_from,
  609. self.type, self.type,
  610. self.company_currency_id.id,
  611. # FROM
  612. self.type, self.type,
  613. # WHERE
  614. ('posted',) if self.target_move == 'posted' else ('posted', 'draft',),
  615. self.report_id.id,
  616. self.company_id.id,
  617. self.type, self.report_id.date_from,
  618. self.report_id.date_from, self.type_ledger,
  619. self.report_id.date_to,
  620. tuple(self.journal_ids.ids) if self.journal_ids else (None,),
  621. tuple(self.account_ids.ids) if self.account_ids else (None,),
  622. self.type,
  623. tuple(self.partner_ids.ids) if self.partner_ids else (None,),
  624. self.compact_account,
  625. self.reconciled,
  626. ]
  627. self.env.cr.execute(query, tuple(params))
  628. def _sql_lines_compacted(self):
  629. query = """
  630. INSERT INTO account_report_standard_ledger_line
  631. (report_id, create_uid, create_date, account_id, type, type_view, date, debit, credit, balance, cumul_balance, company_currency_id, report_object_id)
  632. WITH initial_balance (id, balance) AS
  633. (
  634. SELECT
  635. MIN(report_object_id) AS id,
  636. COALESCE(SUM(balance), 0) AS balance
  637. FROM
  638. account_report_standard_ledger_line
  639. WHERE
  640. report_id = %s
  641. AND type = '0_init'
  642. GROUP BY
  643. report_object_id
  644. )
  645. SELECT
  646. %s AS report_id,
  647. %s AS create_uid,
  648. NOW() AS create_date,
  649. MIN(aml.account_id) AS account_id,
  650. '3_compact' AS type,
  651. 'normal' AS type_view,
  652. %s AS date,
  653. COALESCE(SUM(aml.debit), 0) AS debit,
  654. COALESCE(SUM(aml.credit), 0) AS credit,
  655. COALESCE(SUM(aml.balance), 0) AS balance,
  656. COALESCE(MIN(init.balance), 0) + COALESCE(SUM(aml.balance), 0) AS cumul_balance,
  657. %s AS company_currency_id,
  658. MIN(ro.id) AS report_object_id
  659. FROM
  660. account_report_standard_ledger_report_object ro
  661. INNER JOIN account_move_line aml ON (aml.account_id = ro.object_id)
  662. LEFT JOIN account_journal j ON (aml.journal_id = j.id)
  663. LEFT JOIN account_account acc ON (aml.account_id = acc.id)
  664. LEFT JOIN account_account_type acc_type ON (acc.user_type_id = acc_type.id)
  665. LEFT JOIN account_move m ON (aml.move_id = m.id)
  666. LEFT JOIN initial_balance init ON (ro.id = init.id)
  667. WHERE
  668. m.state IN %s
  669. AND ro.report_id = %s
  670. AND aml.company_id = %s
  671. AND aml.date >= %s
  672. AND aml.date <= %s
  673. AND aml.journal_id IN %s
  674. AND aml.account_id IN %s
  675. AND (%s AND acc.compacted = TRUE)
  676. GROUP BY
  677. aml.account_id
  678. """
  679. params = [
  680. # initial_balance
  681. self.report_id.id,
  682. # SELECT
  683. self.report_id.id,
  684. self.env.uid,
  685. self.report_id.date_from,
  686. self.company_currency_id.id,
  687. # FROM
  688. # WHERE
  689. ('posted',) if self.target_move == 'posted' else ('posted', 'draft',),
  690. self.report_id.id,
  691. self.company_id.id,
  692. self.report_id.date_from,
  693. self.report_id.date_to,
  694. tuple(self.journal_ids.ids) if self.journal_ids else (None,),
  695. tuple(self.account_ids.ids) if self.account_ids else (None,),
  696. self.compact_account,
  697. ]
  698. self.env.cr.execute(query, tuple(params))
  699. def _sql_total(self):
  700. query = """
  701. INSERT INTO account_report_standard_ledger_line
  702. (report_id, create_uid, create_date, account_id, partner_id, journal_id, type, type_view, date, debit, credit, balance, cumul_balance, report_object_id, current, age_30_days, age_60_days, age_90_days, age_120_days, older, company_currency_id)
  703. SELECT
  704. %s AS report_id,
  705. %s AS create_uid,
  706. NOW() AS create_date,
  707. CASE WHEN %s = 'account' THEN MIN(account_id) ELSE NULL END AS account_id,
  708. CASE WHEN %s = 'partner' THEN MIN(partner_id) ELSE NULL END AS partner_id,
  709. CASE WHEN %s = 'journal' THEN MIN(journal_id) ELSE NULL END AS journal_id,
  710. '4_total' AS type,
  711. 'total' AS type_view,
  712. %s AS date,
  713. COALESCE(SUM(debit), 0) AS debit,
  714. COALESCE(SUM(credit), 0) AS credit,
  715. COALESCE(SUM(balance), 0) AS balance,
  716. COALESCE(SUM(balance), 0) AS cumul_balance,
  717. MIN(report_object_id) AS report_object_id,
  718. COALESCE(SUM(current), 0) AS current,
  719. COALESCE(SUM(age_30_days), 0) AS age_30_days,
  720. COALESCE(SUM(age_60_days), 0) AS age_60_days,
  721. COALESCE(SUM(age_90_days), 0) AS age_90_days,
  722. COALESCE(SUM(age_120_days), 0) AS age_120_days,
  723. COALESCE(SUM(older), 0) AS older,
  724. %s AS company_currency_id
  725. FROM
  726. account_report_standard_ledger_line
  727. WHERE
  728. report_id = %s
  729. AND report_object_id IS NOT NULL
  730. GROUP BY
  731. report_object_id
  732. ORDER BY
  733. report_object_id
  734. """
  735. params = [
  736. # SELECT
  737. self.report_id.id,
  738. self.env.uid,
  739. self.type, self.type, self.type,
  740. self.report_id.date_from,
  741. self.company_currency_id.id,
  742. # WHERE
  743. self.report_id.id,
  744. ]
  745. self.env.cr.execute(query, tuple(params))
  746. def _sql_super_total(self):
  747. query = """
  748. INSERT INTO account_report_standard_ledger_line
  749. (report_id, create_uid, create_date, type, type_view, date, debit, credit, balance, cumul_balance, current, age_30_days, age_60_days, age_90_days, age_120_days, older, company_currency_id)
  750. SELECT
  751. %s AS report_id,
  752. %s AS create_uid,
  753. NOW() AS create_date,
  754. '5_super_total' AS type,
  755. 'total' AS type_view,
  756. %s AS date,
  757. COALESCE(SUM(debit), 0) AS debit,
  758. COALESCE(SUM(credit), 0) AS credit,
  759. COALESCE(SUM(balance), 0) AS balance,
  760. COALESCE(SUM(balance), 0) AS cumul_balance,
  761. COALESCE(SUM(current), 0) AS current,
  762. COALESCE(SUM(age_30_days), 0) AS age_30_days,
  763. COALESCE(SUM(age_60_days), 0) AS age_60_days,
  764. COALESCE(SUM(age_90_days), 0) AS age_90_days,
  765. COALESCE(SUM(age_120_days), 0) AS age_120_days,
  766. COALESCE(SUM(older), 0) AS older,
  767. %s AS company_currency_id
  768. FROM
  769. account_report_standard_ledger_line
  770. WHERE
  771. report_id = %s
  772. AND type = '4_total'
  773. """
  774. params = [
  775. # SELECT
  776. self.report_id.id,
  777. self.env.uid,
  778. self.report_id.date_from,
  779. self.company_currency_id.id,
  780. self.report_id.id,
  781. ]
  782. self.env.cr.execute(query, tuple(params))
  783. def _search_account(self):
  784. type_ledger = self.type_ledger
  785. domain = [('deprecated', '=', False), ('company_id', '=', self.company_id.id)]
  786. if type_ledger in ('partner', 'aged',):
  787. result_selection = self.result_selection
  788. if result_selection == 'supplier':
  789. acc_type = ('supplier',)
  790. elif result_selection == 'customer':
  791. acc_type = ('customer',)
  792. else:
  793. acc_type = ('supplier', 'customer',)
  794. domain.append(('type_third_parties', 'in', acc_type))
  795. account_in_ex_clude = self.account_in_ex_clude.ids
  796. acc_methode = self.account_methode
  797. if account_in_ex_clude:
  798. if acc_methode == 'include':
  799. domain.append(('id', 'in', account_in_ex_clude))
  800. elif acc_methode == 'exclude':
  801. domain.append(('id', 'not in', account_in_ex_clude))
  802. return self.env['account.account'].search(domain)
  803. def _search_partner(self):
  804. if self.type_ledger in ('partner', 'aged'):
  805. if self.partner_select_ids:
  806. return self.partner_select_ids
  807. return self.env['res.partner'].search([])
  808. return False
  809. def _get_name_report(self):
  810. report_name = D_LEDGER[self.type_ledger]['name']
  811. if self.summary:
  812. report_name += _(' Balance')
  813. return report_name
  814. def _sql_get_line_for_report(self, type_l, report_object=None):
  815. query = """SELECT
  816. aml.report_object_id AS report_object_id,
  817. aml.type_view AS type_view,
  818. CASE
  819. WHEN %s = 'account' THEN acc.code
  820. WHEN %s = 'journal' THEN acj.code
  821. ELSE rep.ref
  822. END AS code,
  823. CASE
  824. WHEN %s = 'account' THEN acc.name
  825. WHEN %s = 'journal' THEN acj.name
  826. ELSE rep.name
  827. END AS name,
  828. acj.code AS j_code,
  829. acc.code AS a_code,
  830. acc.name AS a_name,
  831. aml.current AS current,
  832. aml.age_30_days AS age_30_days,
  833. aml.age_60_days AS age_60_days,
  834. aml.age_90_days AS age_90_days,
  835. aml.age_120_days AS age_120_days,
  836. aml.older AS older,
  837. aml.credit AS credit,
  838. aml.debit AS debit,
  839. aml.cumul_balance AS cumul_balance,
  840. aml.balance AS balance,
  841. ml.name AS move_name,
  842. ml.ref AS displayed_name,
  843. rep.name AS partner_name,
  844. aml.date AS date,
  845. aml.date_maturity AS date_maturity,
  846. CASE
  847. WHEN aml.full_reconcile_id IS NOT NULL THEN (CASE WHEN aml.reconciled = TRUE THEN afr.name ELSE '*' END)
  848. ELSE ''
  849. END AS matching_number
  850. FROM
  851. account_report_standard_ledger_line aml
  852. LEFT JOIN account_account acc ON (acc.id = aml.account_id)
  853. LEFT JOIN account_journal acj ON (acj.id = aml.journal_id)
  854. LEFT JOIN res_partner rep ON (rep.id = aml.partner_id)
  855. LEFT JOIN account_move ml ON (ml.id = aml.move_id)
  856. LEFT JOIN account_full_reconcile afr ON (aml.full_reconcile_id = afr.id)
  857. WHERE
  858. aml.report_id = %s
  859. AND (%s OR aml.report_object_id = %s)
  860. AND aml.type IN %s
  861. ORDER BY
  862. aml.id
  863. """
  864. params = [
  865. self.type, self.type, self.type, self.type,
  866. self.report_id.id,
  867. True if report_object is None else False,
  868. report_object,
  869. type_l
  870. ]
  871. self.env.cr.execute(query, tuple(params))
  872. return self.env.cr.dictfetchall()
  873. def _format_total(self):
  874. if not self.company_currency_id:
  875. return
  876. lines = self.report_id.line_total_ids + self.report_id.line_super_total_id
  877. for line in lines:
  878. line.write({
  879. 'debit': self.company_currency_id.round(line.debit) + 0.0,
  880. 'credit': self.company_currency_id.round(line.credit) + 0.0,
  881. 'balance': self.company_currency_id.round(line.balance) + 0.0,
  882. 'current': self.company_currency_id.round(line.current) + 0.0,
  883. 'age_30_days': self.company_currency_id.round(line.age_30_days) + 0.0,
  884. 'age_60_days': self.company_currency_id.round(line.age_60_days) + 0.0,
  885. 'age_90_days': self.company_currency_id.round(line.age_90_days) + 0.0,
  886. 'age_120_days': self.company_currency_id.round(line.age_120_days) + 0.0,
  887. 'older': self.company_currency_id.round(line.older) + 0.0,
  888. })