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.

238 lines
11 KiB

  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Author: Nicolas Bessi, Guewen Baconnier
  5. # Copyright Camptocamp SA 2011
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU Affero General Public License as
  9. # published by the Free Software Foundation, either version 3 of the
  10. # License, or (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU Affero General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Affero General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. #
  20. ##############################################################################
  21. import pooler
  22. from collections import defaultdict
  23. from report import report_sxw
  24. from datetime import datetime
  25. from itertools import groupby
  26. from operator import itemgetter
  27. from mako.template import Template
  28. from tools.translate import _
  29. from openerp.osv import osv
  30. from common_partner_reports import CommonPartnersReportHeaderWebkit
  31. from webkit_parser_header_fix import HeaderFooterTextWebKitParser
  32. from openerp.addons.report_webkit import report_helper
  33. import addons
  34. def get_mako_template(obj, *args):
  35. template_path = addons.get_module_resource(*args)
  36. return Template(filename=template_path, input_encoding='utf-8')
  37. report_helper.WebKitHelper.get_mako_template = get_mako_template
  38. class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit):
  39. def __init__(self, cursor, uid, name, context):
  40. super(PartnersOpenInvoicesWebkit, self).__init__(cursor, uid, name, context=context)
  41. self.pool = pooler.get_pool(self.cr.dbname)
  42. self.cursor = self.cr
  43. company = self.pool.get('res.users').browse(self.cr, uid, uid, context=context).company_id
  44. header_report_name = ' - '.join((_('OPEN INVOICES REPORT'), company.name, company.currency_id.name))
  45. footer_date_time = self.formatLang(str(datetime.today()), date_time=True)
  46. self.localcontext.update({
  47. 'cr': cursor,
  48. 'uid': uid,
  49. 'report_name':_('Open Invoices Report'),
  50. 'display_account_raw': self._get_display_account_raw,
  51. 'filter_form': self._get_filter,
  52. 'target_move': self._get_target_move,
  53. 'amount_currency': self._get_amount_currency,
  54. 'display_partner_account': self._get_display_partner_account,
  55. 'display_target_move': self._get_display_target_move,
  56. 'additional_args': [
  57. ('--header-font-name', 'Helvetica'),
  58. ('--footer-font-name', 'Helvetica'),
  59. ('--header-font-size', '10'),
  60. ('--footer-font-size', '6'),
  61. ('--header-left', header_report_name),
  62. ('--header-spacing', '2'),
  63. ('--footer-left', footer_date_time),
  64. ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
  65. ('--footer-line',),
  66. ],
  67. })
  68. def _group_lines_by_currency(self, account_br):
  69. account_br.grouped_ledger_lines = {}
  70. if not account_br.ledger_lines:
  71. return
  72. for part_id, plane_lines in account_br.ledger_lines.items():
  73. account_br.grouped_ledger_lines[part_id] = []
  74. plane_lines.sort(key=itemgetter('currency_code'))
  75. for curr, lines in groupby(plane_lines, key=itemgetter('currency_code')):
  76. tmp = [x for x in lines]
  77. account_br.grouped_ledger_lines[part_id].append((curr, tmp)) #I want to reiter many times
  78. def set_context(self, objects, data, ids, report_type=None):
  79. """Populate a ledger_lines attribute on each browse record that will be used
  80. by mako template"""
  81. new_ids = data['form']['chart_account_id']
  82. # Account initial balance memoizer
  83. init_balance_memoizer = {}
  84. # Reading form
  85. main_filter = self._get_form_param('filter', data, default='filter_no')
  86. target_move = self._get_form_param('target_move', data, default='all')
  87. start_date = self._get_form_param('date_from', data)
  88. stop_date = self._get_form_param('date_to', data)
  89. start_period = self.get_start_period_br(data)
  90. stop_period = self.get_end_period_br(data)
  91. fiscalyear = self.get_fiscalyear_br(data)
  92. partner_ids = self._get_form_param('partner_ids', data)
  93. result_selection = self._get_form_param('result_selection', data)
  94. date_until = self._get_form_param('until_date', data)
  95. chart_account = self._get_chart_account_id_br(data)
  96. group_by_currency = self._get_form_param('group_by_currency', data)
  97. if main_filter == 'filter_no' and fiscalyear:
  98. start_period = self.get_first_fiscalyear_period(fiscalyear)
  99. stop_period = self.get_last_fiscalyear_period(fiscalyear)
  100. # Retrieving accounts
  101. filter_type = ('payable', 'receivable')
  102. if result_selection == 'customer':
  103. filter_type = ('receivable',)
  104. if result_selection == 'supplier':
  105. filter_type = ('payable',)
  106. account_ids = self.get_all_accounts(new_ids, exclude_type=['view'], only_type=filter_type)
  107. if not account_ids:
  108. raise osv.except_osv(_('Error'), _('No accounts to print.'))
  109. # computation of ledeger lines
  110. if main_filter == 'filter_date':
  111. start = start_date
  112. stop = stop_date
  113. else:
  114. start = start_period
  115. stop = stop_period
  116. ledger_lines_memoizer = self._compute_open_transactions_lines(account_ids,
  117. main_filter,
  118. target_move,
  119. start,
  120. stop,
  121. date_until,
  122. partner_filter=partner_ids)
  123. objects = []
  124. for account in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids):
  125. account.ledger_lines = ledger_lines_memoizer.get(account.id, {})
  126. account.init_balance = init_balance_memoizer.get(account.id, {})
  127. ## we have to compute partner order based on inital balance
  128. ## and ledger line as we may have partner with init bal
  129. ## that are not in ledger line and vice versa
  130. ledg_lines_pids = ledger_lines_memoizer.get(account.id, {}).keys()
  131. non_null_init_balances = dict([(ib, amounts) for ib, amounts in account.init_balance.iteritems()
  132. if amounts['init_balance'] or amounts['init_balance_currency']])
  133. init_bal_lines_pids = non_null_init_balances.keys()
  134. account.partners_order = self._order_partners(ledg_lines_pids, init_bal_lines_pids)
  135. account.ledger_lines = ledger_lines_memoizer.get(account.id, {})
  136. if group_by_currency:
  137. self._group_lines_by_currency(account)
  138. objects.append(account)
  139. self.localcontext.update({
  140. 'fiscalyear': fiscalyear,
  141. 'start_date': start_date,
  142. 'stop_date': stop_date,
  143. 'start_period': start_period,
  144. 'stop_period': stop_period,
  145. 'date_until': date_until,
  146. 'partner_ids': partner_ids,
  147. 'chart_account': chart_account,
  148. })
  149. return super(PartnersOpenInvoicesWebkit, self).set_context(objects, data, new_ids,
  150. report_type=report_type)
  151. def _compute_open_transactions_lines(self, accounts_ids, main_filter, target_move, start, stop, date_until=False, partner_filter=False):
  152. res = defaultdict(dict)
  153. ## we check if until date and date stop have the same value
  154. if main_filter in ('filter_period', 'filter_no'):
  155. date_stop = stop.date_stop
  156. date_until_match = (date_stop == date_until)
  157. elif main_filter == 'filter_date':
  158. date_stop = stop
  159. date_until_match = (stop == date_until)
  160. else:
  161. raise osv.except_osv(_('Unsuported filter'),
  162. _('Filter has to be in filter date, period, or none'))
  163. initial_move_lines_per_account = {}
  164. if main_filter in ('filter_period', 'filter_no'):
  165. initial_move_lines_per_account = self._tree_move_line_ids(
  166. self._partners_initial_balance_line_ids(accounts_ids,
  167. start,
  168. partner_filter,
  169. exclude_reconcile=True,
  170. force_period_ids=False,
  171. date_stop=date_stop), key='id')
  172. for account_id in accounts_ids:
  173. initial_move_lines_ids_per_partner = initial_move_lines_per_account.get(account_id, {})
  174. # We get the move line ids of the account
  175. move_line_ids_per_partner = self.get_partners_move_lines_ids(account_id,
  176. main_filter,
  177. start,
  178. stop,
  179. target_move,
  180. exclude_reconcile=True,
  181. partner_filter=partner_filter)
  182. if not initial_move_lines_ids_per_partner and not move_line_ids_per_partner:
  183. continue
  184. for partner_id in list(set(initial_move_lines_ids_per_partner.keys() + move_line_ids_per_partner.keys())):
  185. partner_line_ids = (move_line_ids_per_partner.get(partner_id, []) +
  186. initial_move_lines_ids_per_partner.get(partner_id, []))
  187. clearance_line_ids = []
  188. if date_until and not date_until_match and partner_line_ids:
  189. clearance_line_ids = self._get_clearance_move_line_ids(partner_line_ids, date_stop, date_until)
  190. partner_line_ids += clearance_line_ids
  191. lines = self._get_move_line_datas(list(set(partner_line_ids)))
  192. for line in lines:
  193. if line['id'] in initial_move_lines_ids_per_partner.get(partner_id, []):
  194. line['is_from_previous_periods'] = True
  195. if line['id'] in clearance_line_ids:
  196. line['is_clearance_line'] = True
  197. res[account_id][partner_id] = lines
  198. return res
  199. HeaderFooterTextWebKitParser('report.account.account_report_open_invoices_webkit',
  200. 'account.account',
  201. 'addons/account_financial_report_webkit/report/templates/account_report_open_invoices.mako',
  202. parser=PartnersOpenInvoicesWebkit)