Browse Source

[FIX] use openerp absolute imports and apply pep8 (excepted the lines length)

pull/7/merge
Guewen Baconnier @ Camptocamp 12 years ago
parent
commit
842b7f6000
  1. 12
      account_financial_report_webkit/account.py
  2. 12
      account_financial_report_webkit/account_move_line.py
  3. 17
      account_financial_report_webkit/report/common_balance_reports.py
  4. 13
      account_financial_report_webkit/report/common_partner_balance_reports.py
  5. 14
      account_financial_report_webkit/report/common_partner_reports.py
  6. 28
      account_financial_report_webkit/report/common_reports.py
  7. 13
      account_financial_report_webkit/report/general_ledger.py
  8. 18
      account_financial_report_webkit/report/open_invoices.py
  9. 10
      account_financial_report_webkit/report/partner_balance.py
  10. 14
      account_financial_report_webkit/report/partners_ledger.py
  11. 12
      account_financial_report_webkit/report/trial_balance.py
  12. 5
      account_financial_report_webkit/report/webkit_parser_header_fix.py
  13. 60
      account_financial_report_webkit/wizard/balance_common.py
  14. 26
      account_financial_report_webkit/wizard/general_ledger_wizard.py
  15. 33
      account_financial_report_webkit/wizard/open_invoices_wizard.py
  16. 15
      account_financial_report_webkit/wizard/partner_balance_wizard.py
  17. 12
      account_financial_report_webkit/wizard/partners_ledger_wizard.py

12
account_financial_report_webkit/account.py

@ -28,18 +28,20 @@
# #
############################################################################## ##############################################################################
from osv import osv, fields
from openerp.osv import fields, orm
class AccountAccount(osv.osv):
class AccountAccount(orm.Model):
_inherit = 'account.account' _inherit = 'account.account'
_columns = { _columns = {
'centralized': fields.boolean('Centralized', help="If flagged, no details will be displayed in the General Ledger report (the webkit one only), only centralized amounts per period.")
'centralized': fields.boolean(
'Centralized',
help="If flagged, no details will be displayed in "
"the General Ledger report (the webkit one only), "
"only centralized amounts per period.")
} }
_defaults = { _defaults = {
'centralized': False, 'centralized': False,
} }
AccountAccount()

12
account_financial_report_webkit/account_move_line.py

@ -19,11 +19,11 @@
# #
############################################################################## ##############################################################################
from osv import fields, osv
from tools.translate import _
from openerp.osv import fields, orm
from openerp.tools.translate import _
class AccountMoveLine(osv.osv):
class AccountMoveLine(orm.Model):
"""Overriding Account move line in order to add last_rec_date. """Overriding Account move line in order to add last_rec_date.
Last rec date is the date of the last reconciliation (full or partial) account move line""" Last rec date is the date of the last reconciliation (full or partial) account move line"""
_inherit = 'account.move.line' _inherit = 'account.move.line'
@ -46,7 +46,6 @@ class AccountMoveLine(osv.osv):
" ORDER BY date DESC LIMIT 1)" " ORDER BY date DESC LIMIT 1)"
" WHERE last_rec_date is null;") " WHERE last_rec_date is null;")
def _get_move_line_from_line_rec(self, cr, uid, ids, context=None): def _get_move_line_from_line_rec(self, cr, uid, ids, context=None):
moves = [] moves = []
for reconcile in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context): for reconcile in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context):
@ -79,11 +78,8 @@ class AccountMoveLine(osv.osv):
method=True, method=True,
string='Last reconciliation date', string='Last reconciliation date',
store={'account.move.line': (lambda self, cr, uid, ids, c={}: ids, ['date'], 20), store={'account.move.line': (lambda self, cr, uid, ids, c={}: ids, ['date'], 20),
'account.move.reconcile': (_get_move_line_from_line_rec, None ,20)},
'account.move.reconcile': (_get_move_line_from_line_rec, None, 20)},
type='date', type='date',
multi='all', multi='all',
help="the date of the last reconciliation (full or partial) account move line"), help="the date of the last reconciliation (full or partial) account move line"),
} }
AccountMoveLine()

17
account_financial_report_webkit/report/common_balance_reports.py

@ -22,7 +22,7 @@
from operator import add from operator import add
from common_reports import CommonReportHeaderWebkit
from .common_reports import CommonReportHeaderWebkit
class CommonBalanceReportHeaderWebkit(CommonReportHeaderWebkit): class CommonBalanceReportHeaderWebkit(CommonReportHeaderWebkit):
@ -73,12 +73,17 @@ class CommonBalanceReportHeaderWebkit(CommonReportHeaderWebkit):
'all_fiscalyear': True}) 'all_fiscalyear': True})
if use_period_ids: if use_period_ids:
ctx.update({'periods': period_ids,})
ctx.update({'periods': period_ids})
elif main_filter == 'filter_date': elif main_filter == 'filter_date':
ctx.update({'date_from': start, ctx.update({'date_from': start,
'date_to': stop}) 'date_to': stop})
accounts = account_obj.read(self.cursor, self.uid, account_ids, ['type','code','name','debit','credit', 'balance', 'parent_id','level','child_id'], ctx)
accounts = account_obj.read(
self.cursor,
self.uid,
account_ids,
['type', 'code', 'name', 'debit', 'credit', 'balance', 'parent_id', 'level', 'child_id'],
ctx)
accounts_by_id = {} accounts_by_id = {}
for account in accounts: for account in accounts:
@ -86,7 +91,11 @@ class CommonBalanceReportHeaderWebkit(CommonReportHeaderWebkit):
# sum for top level views accounts # sum for top level views accounts
child_ids = account_obj._get_children_and_consol(self.cursor, self.uid, account['id'], ctx) child_ids = account_obj._get_children_and_consol(self.cursor, self.uid, account['id'], ctx)
if child_ids: if child_ids:
child_init_balances = [init_bal['init_balance'] for acnt_id, init_bal in init_balance.iteritems() if acnt_id in child_ids ]
child_init_balances = [ \
init_bal['init_balance'] \
for acnt_id, init_bal \
in init_balance.iteritems() \
if acnt_id in child_ids]
top_init_balance = reduce(add, child_init_balances) top_init_balance = reduce(add, child_init_balances)
account['init_balance'] = top_init_balance account['init_balance'] = top_init_balance
else: else:

13
account_financial_report_webkit/report/common_partner_balance_reports.py

@ -23,8 +23,8 @@
from collections import defaultdict from collections import defaultdict
from operator import add from operator import add
from common_balance_reports import CommonBalanceReportHeaderWebkit
from common_partner_reports import CommonPartnersReportHeaderWebkit
from .common_balance_reports import CommonBalanceReportHeaderWebkit
from .common_partner_reports import CommonPartnersReportHeaderWebkit
class CommonPartnerBalanceReportHeaderWebkit(CommonBalanceReportHeaderWebkit, CommonPartnersReportHeaderWebkit): class CommonPartnerBalanceReportHeaderWebkit(CommonBalanceReportHeaderWebkit, CommonPartnersReportHeaderWebkit):
@ -95,21 +95,22 @@ class CommonPartnerBalanceReportHeaderWebkit(CommonBalanceReportHeaderWebkit, Co
FROM account_move_line""" FROM account_move_line"""
sql_joins = '' sql_joins = ''
sql_where = "WHERE account_move_line.account_id = %(account_id)s AND account_move_line.state = 'valid' " sql_where = "WHERE account_move_line.account_id = %(account_id)s AND account_move_line.state = 'valid' "
sql_conditions, search_params = getattr(self, '_get_query_params_from_'+filter_from+'s')(start, stop, mode=mode)
method = getattr(self, '_get_query_params_from_' + filter_from + 's')
sql_conditions, search_params = method(start, stop, mode=mode)
sql_where += sql_conditions sql_where += sql_conditions
if partner_filter_ids: if partner_filter_ids:
sql_where += " AND account_move_line.partner_id in %(partner_ids)s" sql_where += " AND account_move_line.partner_id in %(partner_ids)s"
search_params.update({'partner_ids': tuple(partner_filter_ids),})
search_params.update({'partner_ids': tuple(partner_filter_ids)})
if target_move == 'posted': if target_move == 'posted':
sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id" sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id"
sql_where += " AND account_move.state = %(target_move)s" sql_where += " AND account_move.state = %(target_move)s"
search_params.update({'target_move': target_move,})
search_params.update({'target_move': target_move})
sql_groupby = "GROUP BY account_move_line.partner_id" sql_groupby = "GROUP BY account_move_line.partner_id"
search_params.update({'account_id': account_id,})
search_params.update({'account_id': account_id})
query = ' '.join((sql_select, sql_joins, sql_where, sql_groupby)) query = ' '.join((sql_select, sql_joins, sql_where, sql_groupby))
self.cursor.execute(query, search_params) self.cursor.execute(query, search_params)

14
account_financial_report_webkit/report/common_partner_reports.py

@ -26,7 +26,7 @@ from collections import defaultdict
from datetime import datetime from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from common_reports import CommonReportHeaderWebkit
from .common_reports import CommonReportHeaderWebkit
class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit): class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit):
@ -164,7 +164,8 @@ class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit):
sql_where = " WHERE account_move_line.account_id = %(account_ids)s " \ sql_where = " WHERE account_move_line.account_id = %(account_ids)s " \
" AND account_move_line.state = 'valid' " " AND account_move_line.state = 'valid' "
sql_conditions, search_params = getattr(self, '_get_query_params_from_'+filter_from+'s')(start, stop)
method = getattr(self, '_get_query_params_from_' + filter_from + 's')
sql_conditions, search_params = method(start, stop)
sql_where += sql_conditions sql_where += sql_conditions
@ -178,7 +179,7 @@ class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit):
if target_move == 'posted': if target_move == 'posted':
sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id" sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id"
sql_where += " AND account_move.state = %(target_move)s" sql_where += " AND account_move.state = %(target_move)s"
search_params.update({'target_move': target_move,})
search_params.update({'target_move': target_move})
search_params.update({ search_params.update({
'account_ids': account_id, 'account_ids': account_id,
@ -247,9 +248,11 @@ class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit):
if not period_ids: if not period_ids:
period_ids = [-1] period_ids = [-1]
search_param = {'date_start': start_period.date_start,
search_param = {
'date_start': start_period.date_start,
'period_ids': tuple(period_ids), 'period_ids': tuple(period_ids),
'account_ids': tuple(account_ids),}
'account_ids': tuple(account_ids),
}
sql = ("SELECT ml.id, ml.account_id, ml.partner_id " sql = ("SELECT ml.id, ml.account_id, ml.partner_id "
"FROM account_move_line ml " "FROM account_move_line ml "
"INNER JOIN account_account a " "INNER JOIN account_account a "
@ -325,4 +328,3 @@ class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit):
if not res: if not res:
return [] return []
return res return res

28
account_financial_report_webkit/report/common_reports.py

@ -24,25 +24,25 @@
import logging import logging
from openerp.osv import osv
from openerp.tools.translate import _
from openerp.addons.account.report.common_report_header import common_report_header from openerp.addons.account.report.common_report_header import common_report_header
from osv import osv
from tools.translate import _
_logger = logging.getLogger('financial.reports.webkit') _logger = logging.getLogger('financial.reports.webkit')
class CommonReportHeaderWebkit(common_report_header): class CommonReportHeaderWebkit(common_report_header):
"""Define common helper for financial report""" """Define common helper for financial report"""
####################From getter helper ##################################### ####################From getter helper #####################################
def get_start_period_br(self, data): def get_start_period_br(self, data):
return self._get_info(data,'period_from', 'account.period')
return self._get_info(data, 'period_from', 'account.period')
def get_end_period_br(self, data): def get_end_period_br(self, data):
return self._get_info(data,'period_to', 'account.period')
return self._get_info(data, 'period_to', 'account.period')
def get_fiscalyear_br(self, data): def get_fiscalyear_br(self, data):
return self._get_info(data,'fiscalyear_id', 'account.fiscalyear')
return self._get_info(data, 'fiscalyear_id', 'account.fiscalyear')
def _get_chart_account_id_br(self, data): def _get_chart_account_id_br(self, data):
return self._get_info(data, 'chart_account_id', 'account.account') return self._get_info(data, 'chart_account_id', 'account.account')
@ -109,8 +109,6 @@ class CommonReportHeaderWebkit(common_report_header):
def _get_form_param(self, param, data, default=False): def _get_form_param(self, param, data, default=False):
return data.get('form', {}).get(param, default) return data.get('form', {}).get(param, default)
####################Account and account line filter helper ################# ####################Account and account line filter helper #################
def sort_accounts_with_structure(self, root_account_ids, account_ids, context=None): def sort_accounts_with_structure(self, root_account_ids, account_ids, context=None):
@ -285,7 +283,7 @@ class CommonReportHeaderWebkit(common_report_header):
if not include_opening: if not include_opening:
periods_search += [('special', '=', False)] periods_search += [('special', '=', False)]
if fiscalyear :
if fiscalyear:
periods_search.append(('fiscalyear_id', '=', fiscalyear.id)) periods_search.append(('fiscalyear_id', '=', fiscalyear.id))
periods = period_obj.search(self.cursor, self.uid, periods_search) periods = period_obj.search(self.cursor, self.uid, periods_search)
if include_opening and opening_period_id: if include_opening and opening_period_id:
@ -305,12 +303,12 @@ class CommonReportHeaderWebkit(common_report_header):
period_obj = self.pool.get('account.period') period_obj = self.pool.get('account.period')
p_id = period_obj.search(self.cursor, p_id = period_obj.search(self.cursor,
self.uid, self.uid,
[('special','=', special),
[('special', '=', special),
('fiscalyear_id', '=', fiscalyear.id)], ('fiscalyear_id', '=', fiscalyear.id)],
limit=1, limit=1,
order='date_start %s' % (order,)) order='date_start %s' % (order,))
if not p_id: if not p_id:
raise osv.except_osv(_('No period found'),'')
raise osv.except_osv(_('No period found'), '')
return period_obj.browse(self.cursor, self.uid, p_id[0]) return period_obj.browse(self.cursor, self.uid, p_id[0])
####################Initial Balance helper ################################# ####################Initial Balance helper #################################
@ -435,7 +433,7 @@ class CommonReportHeaderWebkit(common_report_header):
return [] return []
if not isinstance(move_line_ids, list): if not isinstance(move_line_ids, list):
move_line_ids = [move_line_ids] move_line_ids = [move_line_ids]
monster ="""
monster = """
SELECT l.id AS id, SELECT l.id AS id,
l.date AS ldate, l.date AS ldate,
j.code AS jcode , j.code AS jcode ,
@ -473,7 +471,7 @@ FROM account_move_line l
monster += (" ORDER BY %s" % (order,)) monster += (" ORDER BY %s" % (order,))
try: try:
self.cursor.execute(monster, (tuple(move_line_ids),)) self.cursor.execute(monster, (tuple(move_line_ids),))
res= self.cursor.dictfetchall()
res = self.cursor.dictfetchall()
except Exception, exc: except Exception, exc:
self.cursor.rollback() self.cursor.rollback()
raise raise
@ -500,8 +498,8 @@ WHERE move_id in %s"""
try: try:
self.cursor.execute(sql, (account_id, limit, tuple(move_ids))) self.cursor.execute(sql, (account_id, limit, tuple(move_ids)))
res= self.cursor.fetchall()
except Exception, exc:
res = self.cursor.fetchall()
except Exception as exc:
self.cursor.rollback() self.cursor.rollback()
raise raise
return res and dict(res) or {} return res and dict(res) or {}

13
account_financial_report_webkit/report/general_ledger.py

@ -19,15 +19,16 @@
# #
############################################################################## ##############################################################################
from report import report_sxw
from tools.translate import _
import pooler
from operator import itemgetter from operator import itemgetter
from itertools import groupby from itertools import groupby
from datetime import datetime from datetime import datetime
from common_reports import CommonReportHeaderWebkit
from webkit_parser_header_fix import HeaderFooterTextWebKitParser
from openerp.report import report_sxw
from openerp import pooler
from openerp.tools.translate import _
from .common_reports import CommonReportHeaderWebkit
from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
class GeneralLedgerWebkit(report_sxw.rml_parse, CommonReportHeaderWebkit): class GeneralLedgerWebkit(report_sxw.rml_parse, CommonReportHeaderWebkit):
@ -158,7 +159,7 @@ class GeneralLedgerWebkit(report_sxw.rml_parse, CommonReportHeaderWebkit):
period_obj = self.pool.get('account.period') period_obj = self.pool.get('account.period')
# we need to sort the lines per period in order to use groupby # we need to sort the lines per period in order to use groupby
# unique ids of each used period id in lines # unique ids of each used period id in lines
period_ids = list(set([line['lperiod_id'] for line in ledger_lines ]))
period_ids = list(set([line['lperiod_id'] for line in ledger_lines]))
# search on account.period in order to sort them by date_start # search on account.period in order to sort them by date_start
sorted_period_ids = period_obj.search(self.cr, self.uid, sorted_period_ids = period_obj.search(self.cr, self.uid,
[('id', 'in', period_ids)], [('id', 'in', period_ids)],

18
account_financial_report_webkit/report/open_invoices.py

@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
import pooler
from collections import defaultdict from collections import defaultdict
from report import report_sxw from report import report_sxw
@ -27,21 +26,23 @@ from itertools import groupby
from operator import itemgetter from operator import itemgetter
from mako.template import Template from mako.template import Template
from tools.translate import _
import openerp.addons
from openerp import pooler
from openerp.osv import osv from openerp.osv import osv
from common_partner_reports import CommonPartnersReportHeaderWebkit
from webkit_parser_header_fix import HeaderFooterTextWebKitParser
from openerp.tools.translate import _
from openerp.addons.report_webkit import report_helper from openerp.addons.report_webkit import report_helper
import addons
from .common_partner_reports import CommonPartnersReportHeaderWebkit
from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
def get_mako_template(obj, *args): def get_mako_template(obj, *args):
template_path = addons.get_module_resource(*args)
template_path = openerp.addons.get_module_resource(*args)
return Template(filename=template_path, input_encoding='utf-8') return Template(filename=template_path, input_encoding='utf-8')
report_helper.WebKitHelper.get_mako_template = get_mako_template report_helper.WebKitHelper.get_mako_template = get_mako_template
class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit): class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit):
def __init__(self, cursor, uid, name, context): def __init__(self, cursor, uid, name, context):
@ -57,7 +58,7 @@ class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeade
self.localcontext.update({ self.localcontext.update({
'cr': cursor, 'cr': cursor,
'uid': uid, 'uid': uid,
'report_name':_('Open Invoices Report'),
'report_name': _('Open Invoices Report'),
'display_account_raw': self._get_display_account_raw, 'display_account_raw': self._get_display_account_raw,
'filter_form': self._get_filter, 'filter_form': self._get_filter,
'target_move': self._get_target_move, 'target_move': self._get_target_move,
@ -77,7 +78,6 @@ class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeade
], ],
}) })
def _group_lines_by_currency(self, account_br): def _group_lines_by_currency(self, account_br):
account_br.grouped_ledger_lines = {} account_br.grouped_ledger_lines = {}
if not account_br.ledger_lines: if not account_br.ledger_lines:
@ -87,7 +87,7 @@ class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeade
plane_lines.sort(key=itemgetter('currency_code')) plane_lines.sort(key=itemgetter('currency_code'))
for curr, lines in groupby(plane_lines, key=itemgetter('currency_code')): for curr, lines in groupby(plane_lines, key=itemgetter('currency_code')):
tmp = [x for x in lines] tmp = [x for x in lines]
account_br.grouped_ledger_lines[part_id].append((curr, tmp)) #I want to reiter many times
account_br.grouped_ledger_lines[part_id].append((curr, tmp)) # I want to reiter many times
def set_context(self, objects, data, ids, report_type=None): def set_context(self, objects, data, ids, report_type=None):
"""Populate a ledger_lines attribute on each browse record that will be used """Populate a ledger_lines attribute on each browse record that will be used

10
account_financial_report_webkit/report/partner_balance.py

@ -20,13 +20,13 @@
############################################################################## ##############################################################################
from report import report_sxw
from tools.translate import _
import pooler
from datetime import datetime from datetime import datetime
from common_partner_balance_reports import CommonPartnerBalanceReportHeaderWebkit
from webkit_parser_header_fix import HeaderFooterTextWebKitParser
from openerp import pooler
from openerp.report import report_sxw
from openerp.tools.translate import _
from .common_partner_balance_reports import CommonPartnerBalanceReportHeaderWebkit
from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
class PartnerBalanceWebkit(report_sxw.rml_parse, CommonPartnerBalanceReportHeaderWebkit): class PartnerBalanceWebkit(report_sxw.rml_parse, CommonPartnerBalanceReportHeaderWebkit):

14
account_financial_report_webkit/report/partners_ledger.py

@ -18,16 +18,16 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
import pooler
from collections import defaultdict from collections import defaultdict
from report import report_sxw
from osv import osv
from tools.translate import _
from datetime import datetime from datetime import datetime
from common_partner_reports import CommonPartnersReportHeaderWebkit
from webkit_parser_header_fix import HeaderFooterTextWebKitParser
from openerp import pooler
from openerp.osv import osv
from openerp.report import report_sxw
from openerp.tools.translate import _
from .common_partner_reports import CommonPartnersReportHeaderWebkit
from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
class PartnersLedgerWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit): class PartnersLedgerWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit):
@ -45,7 +45,7 @@ class PartnersLedgerWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebki
self.localcontext.update({ self.localcontext.update({
'cr': cursor, 'cr': cursor,
'uid': uid, 'uid': uid,
'report_name':_('Partner Ledger'),
'report_name': _('Partner Ledger'),
'display_account_raw': self._get_display_account_raw, 'display_account_raw': self._get_display_account_raw,
'filter_form': self._get_filter, 'filter_form': self._get_filter,
'target_move': self._get_target_move, 'target_move': self._get_target_move,

12
account_financial_report_webkit/report/trial_balance.py

@ -20,17 +20,19 @@
############################################################################## ##############################################################################
from report import report_sxw
from tools.translate import _
import pooler
from datetime import datetime from datetime import datetime
from common_balance_reports import CommonBalanceReportHeaderWebkit
from webkit_parser_header_fix import HeaderFooterTextWebKitParser
from openerp import pooler
from openerp.report import report_sxw
from openerp.tools.translate import _
from .common_balance_reports import CommonBalanceReportHeaderWebkit
from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
def sign(number): def sign(number):
return cmp(number, 0) return cmp(number, 0)
class TrialBalanceWebkit(report_sxw.rml_parse, CommonBalanceReportHeaderWebkit): class TrialBalanceWebkit(report_sxw.rml_parse, CommonBalanceReportHeaderWebkit):
def __init__(self, cursor, uid, name, context): def __init__(self, cursor, uid, name, context):

5
account_financial_report_webkit/report/webkit_parser_header_fix.py

@ -37,8 +37,8 @@ import logging
from mako import exceptions from mako import exceptions
from osv.osv import except_osv
from tools.translate import _
from openerp.osv.osv import except_osv
from openerp.tools.translate import _
from openerp import addons from openerp import addons
from openerp.addons.report_webkit import webkit_report from openerp.addons.report_webkit import webkit_report
from openerp.addons.report_webkit.webkit_report import mako_template from openerp.addons.report_webkit.webkit_report import mako_template
@ -232,4 +232,3 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser):
bin = self.get_lib(cursor, uid) bin = self.get_lib(cursor, uid)
pdf = self.generate_pdf(bin, report_xml, head, foot, htmls) pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)
return (pdf, 'pdf') return (pdf, 'pdf')

60
account_financial_report_webkit/wizard/balance_common.py

@ -30,10 +30,11 @@
import time import time
from osv import fields, osv
from lxml import etree from lxml import etree
from tools.translate import _
from datetime import datetime from datetime import datetime
from openerp.osv import fields, orm
from openerp.tools.translate import _
def previous_year_date(date, nb_prev=1): def previous_year_date(date, nb_prev=1):
if not date: if not date:
@ -44,7 +45,8 @@ def previous_year_date(date, nb_prev=1):
day=parsed_date.day) day=parsed_date.day)
return previous_date return previous_date
class AccountBalanceCommonWizard(osv.osv_memory):
class AccountBalanceCommonWizard(orm.TransientModel):
"""Will launch trial balance report and pass required args""" """Will launch trial balance report and pass required args"""
_inherit = "account.common.account.report" _inherit = "account.common.account.report"
@ -63,7 +65,7 @@ class AccountBalanceCommonWizard(osv.osv_memory):
M2O_DYNAMIC_FIELDS = [f % index for f in ["comp%s_fiscalyear_id", M2O_DYNAMIC_FIELDS = [f % index for f in ["comp%s_fiscalyear_id",
"comp%s_period_from", "comp%s_period_from",
"comp%s_period_to",]
"comp%s_period_to"]
for index in range(COMPARISON_LEVEL)] for index in range(COMPARISON_LEVEL)]
SIMPLE_DYNAMIC_FIELDS = [f % index for f in ["comp%s_filter", SIMPLE_DYNAMIC_FIELDS = [f % index for f in ["comp%s_filter",
"comp%s_date_from", "comp%s_date_from",
@ -83,17 +85,21 @@ class AccountBalanceCommonWizard(osv.osv_memory):
'filter': fields.selection([('filter_no', 'No Filters'), 'filter': fields.selection([('filter_no', 'No Filters'),
('filter_date', 'Date'), ('filter_date', 'Date'),
('filter_period', 'Periods'), ('filter_period', 'Periods'),
('filter_opening', 'Opening Only')], "Filter by", required=True, help='Filter by date : no opening balance will be displayed. (opening balance can only be calculated based on period to be correct).'),
('filter_opening', 'Opening Only')],
"Filter by",
required=True,
help='Filter by date : no opening balance will be displayed. '
'(opening balance can only be calculated based on period to be correct).'),
} }
for index in range(COMPARISON_LEVEL): for index in range(COMPARISON_LEVEL):
_columns.update( _columns.update(
{"comp%s_filter" % (index,): fields.selection(COMPARE_SELECTION, string='Compare By', required=True),
"comp%s_fiscalyear_id" % (index,): fields.many2one('account.fiscalyear', 'Fiscal Year'),
"comp%s_period_from" % (index,): fields.many2one('account.period', 'Start Period'),
"comp%s_period_to" % (index,): fields.many2one('account.period', 'End Period'),
"comp%s_date_from" % (index,): fields.date("Start Date"),
"comp%s_date_to" % (index,): fields.date("End Date"),})
{"comp%s_filter" % index: fields.selection(COMPARE_SELECTION, string='Compare By', required=True),
"comp%s_fiscalyear_id" % index: fields.many2one('account.fiscalyear', 'Fiscal Year'),
"comp%s_period_from" % index: fields.many2one('account.period', 'Start Period'),
"comp%s_period_to" % index: fields.many2one('account.period', 'End Period'),
"comp%s_date_from" % index: fields.date("Start Date"),
"comp%s_date_to" % index: fields.date("End Date")})
_defaults = { _defaults = {
'account_ids': _get_account_ids, 'account_ids': _get_account_ids,
@ -141,9 +147,13 @@ class AccountBalanceCommonWizard(osv.osv_memory):
if placeholder: if placeholder:
placeholder = placeholder[0] placeholder = placeholder[0]
for index in range(self.COMPARISON_LEVEL): for index in range(self.COMPARISON_LEVEL):
page = etree.Element('page', {'name': "comp%s" % (index,), 'string': _("Comparison %s") % (index+1,)})
page = etree.Element(
'page',
{'name': "comp%s" % index,
'string': _("Comparison %s") % (index + 1, )})
group = etree.Element('group') group = etree.Element('group')
page.append(group) page.append(group)
def modifiers_and_append(elem): def modifiers_and_append(elem):
orm.setup_modifiers(elem) orm.setup_modifiers(elem)
group.append(elem) group.append(elem)
@ -159,7 +169,6 @@ class AccountBalanceCommonWizard(osv.osv_memory):
"{'required': [('comp%(index)s_filter','in',('filter_year','filter_opening'))]," \ "{'required': [('comp%(index)s_filter','in',('filter_year','filter_opening'))]," \
" 'invisible': [('comp%(index)s_filter','not in',('filter_year','filter_opening'))]}" % {'index': index}})) " 'invisible': [('comp%(index)s_filter','not in',('filter_year','filter_opening'))]}" % {'index': index}}))
dates_attrs = "{'required': [('comp%(index)s_filter','=','filter_date')], " \ dates_attrs = "{'required': [('comp%(index)s_filter','=','filter_date')], " \
" 'invisible': [('comp%(index)s_filter','!=','filter_date')]}" % {'index': index} " 'invisible': [('comp%(index)s_filter','!=','filter_date')]}" % {'index': index}
modifiers_and_append(etree.Element( modifiers_and_append(etree.Element(
@ -203,7 +212,7 @@ class AccountBalanceCommonWizard(osv.osv_memory):
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None):
res = {} res = {}
if filter == 'filter_no': if filter == 'filter_no':
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False}
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False, 'date_to': False}
if filter == 'filter_date': if filter == 'filter_date':
if fiscalyear_id: if fiscalyear_id:
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context)
@ -258,15 +267,28 @@ class AccountBalanceCommonWizard(osv.osv_memory):
date_to_field = "comp%s_date_to" % (index,) date_to_field = "comp%s_date_to" % (index,)
if comp_filter == 'filter_no': if comp_filter == 'filter_no':
res['value'] = {fy_id_field: False, period_from_field: False, period_to_field: False, date_from_field: False ,date_to_field: False}
res['value'] = {
fy_id_field: False,
period_from_field: False,
period_to_field: False,
date_from_field: False,
date_to_field: False
}
if comp_filter in ('filter_year', 'filter_opening'): if comp_filter in ('filter_year', 'filter_opening'):
res['value'] = {fy_id_field: last_fiscalyear_id, period_from_field: False, period_to_field: False, date_from_field: False ,date_to_field: False}
res['value'] = {
fy_id_field: last_fiscalyear_id,
period_from_field: False,
period_to_field: False,
date_from_field: False,
date_to_field: False
}
if comp_filter == 'filter_date': if comp_filter == 'filter_date':
dates = {} dates = {}
if main_filter == 'filter_date': if main_filter == 'filter_date':
dates = { dates = {
'date_start': previous_year_date(start_date, index + 1).strftime('%Y-%m-%d'), 'date_start': previous_year_date(start_date, index + 1).strftime('%Y-%m-%d'),
'date_stop': previous_year_date(stop_date, index + 1).strftime('%Y-%m-%d'),}
'date_stop': previous_year_date(stop_date, index + 1).strftime('%Y-%m-%d'),
}
elif last_fiscalyear_id: elif last_fiscalyear_id:
dates = fy_obj.read(cr, uid, last_fiscalyear_id, ['date_start', 'date_stop'], context=context) dates = fy_obj.read(cr, uid, last_fiscalyear_id, ['date_start', 'date_stop'], context=context)
@ -311,7 +333,7 @@ class AccountBalanceCommonWizard(osv.osv_memory):
# will be used to attach the report on the main account # will be used to attach the report on the main account
data['ids'] = [data['form']['chart_account_id']] data['ids'] = [data['form']['chart_account_id']]
fields_to_read = ['account_ids',]
fields_to_read = ['account_ids', ]
fields_to_read += self.DYNAMIC_FIELDS fields_to_read += self.DYNAMIC_FIELDS
vals = self.read(cr, uid, ids, fields_to_read, context=context)[0] vals = self.read(cr, uid, ids, fields_to_read, context=context)[0]
@ -323,5 +345,3 @@ class AccountBalanceCommonWizard(osv.osv_memory):
vals['max_comparison'] = self.COMPARISON_LEVEL vals['max_comparison'] = self.COMPARISON_LEVEL
data['form'].update(vals) data['form'].update(vals)
return data return data
AccountBalanceCommonWizard()

26
account_financial_report_webkit/wizard/general_ledger_wizard.py

@ -21,12 +21,11 @@
import time import time
from osv import fields, osv
from openerp.osv import fields, orm
class AccountReportGeneralLedgerWizard(osv.osv_memory):
"""Will launch general ledger report and pass requiered args"""
class AccountReportGeneralLedgerWizard(orm.TransientModel):
"""Will launch general ledger report and pass required args"""
_inherit = "account.common.account.report" _inherit = "account.common.account.report"
_name = "general.ledger.webkit" _name = "general.ledger.webkit"
@ -69,8 +68,6 @@ class AccountReportGeneralLedgerWizard(osv.osv_memory):
def pre_print_report(self, cr, uid, ids, data, context=None): def pre_print_report(self, cr, uid, ids, data, context=None):
data = super(AccountReportGeneralLedgerWizard, self).pre_print_report(cr, uid, ids, data, context) data = super(AccountReportGeneralLedgerWizard, self).pre_print_report(cr, uid, ids, data, context)
if context is None:
context = {}
# will be used to attach the report on the main account # will be used to attach the report on the main account
data['ids'] = [data['form']['chart_account_id']] data['ids'] = [data['form']['chart_account_id']]
vals = self.read(cr, uid, ids, vals = self.read(cr, uid, ids,
@ -85,7 +82,12 @@ class AccountReportGeneralLedgerWizard(osv.osv_memory):
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None):
res = {} res = {}
if filter == 'filter_no': if filter == 'filter_no':
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False}
res['value'] = {
'period_from': False,
'period_to': False,
'date_from': False,
'date_to': False,
}
if filter == 'filter_date': if filter == 'filter_date':
if fiscalyear_id: if fiscalyear_id:
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context)
@ -93,7 +95,12 @@ class AccountReportGeneralLedgerWizard(osv.osv_memory):
date_to = fyear.date_stop > time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or fyear.date_stop date_to = fyear.date_stop > time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or fyear.date_stop
else: else:
date_from, date_to = time.strftime('%Y-01-01'), time.strftime('%Y-%m-%d') date_from, date_to = time.strftime('%Y-01-01'), time.strftime('%Y-%m-%d')
res['value'] = {'period_from': False, 'period_to': False, 'date_from': date_from, 'date_to': date_to}
res['value'] = {
'period_from': False,
'period_to': False,
'date_from': date_from,
'date_to': date_to
}
if filter == 'filter_period' and fiscalyear_id: if filter == 'filter_period' and fiscalyear_id:
start_period = end_period = False start_period = end_period = False
cr.execute(''' cr.execute('''
@ -122,11 +129,8 @@ class AccountReportGeneralLedgerWizard(osv.osv_memory):
return res return res
def _print_report(self, cursor, uid, ids, data, context=None): def _print_report(self, cursor, uid, ids, data, context=None):
context = context or {}
# we update form with display account value # we update form with display account value
data = self.pre_print_report(cursor, uid, ids, data, context=context) data = self.pre_print_report(cursor, uid, ids, data, context=context)
return {'type': 'ir.actions.report.xml', return {'type': 'ir.actions.report.xml',
'report_name': 'account.account_report_general_ledger_webkit', 'report_name': 'account.account_report_general_ledger_webkit',
'datas': data} 'datas': data}
AccountReportGeneralLedgerWizard()

33
account_financial_report_webkit/wizard/open_invoices_wizard.py

@ -18,10 +18,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
############################################################################## ##############################################################################
from osv import fields, osv
from openerp.osv import fields, orm
class AccountReportOpenInvoicesWizard(osv.osv_memory):
class AccountReportOpenInvoicesWizard(orm.TransientModel):
"""Will launch partner ledger report and pass required args""" """Will launch partner ledger report and pass required args"""
_inherit = "partners.ledger.webkit" _inherit = "partners.ledger.webkit"
@ -29,7 +29,7 @@ class AccountReportOpenInvoicesWizard(osv.osv_memory):
_description = "Open Invoices Report" _description = "Open Invoices Report"
_columns = { _columns = {
'group_by_currency':fields.boolean('Group Partner by currency'),
'group_by_currency': fields.boolean('Group Partner by currency'),
'until_date': fields.date("Clearance date", 'until_date': fields.date("Clearance date",
required=True, required=True,
help="""The clearance date is essentially a tool used for debtors provisionning calculation. help="""The clearance date is essentially a tool used for debtors provisionning calculation.
@ -57,38 +57,38 @@ By amending the clearance date, you will be, for instance, able to answer the qu
(_check_until_date, 'Clearance date must be the very last date of the last period or later.', ['until_date']), (_check_until_date, 'Clearance date must be the very last date of the last period or later.', ['until_date']),
] ]
def default_until_date(self, cursor, uid, ids, fiscalyear_id=False, period_id=False, date_to=False, context=None):
def default_until_date(self, cr, uid, ids, fiscalyear_id=False, period_id=False, date_to=False, context=None):
res_date = False res_date = False
# first priority: period or date filters # first priority: period or date filters
if period_id: if period_id:
res_date = self.pool.get('account.period').read(cursor, uid, period_id, ['date_stop'], context=context)['date_stop']
res_date = self.pool.get('account.period').read(cr, uid, period_id, ['date_stop'], context=context)['date_stop']
elif date_to: elif date_to:
res_date = date_to res_date = date_to
elif fiscalyear_id: elif fiscalyear_id:
res_date = self.pool.get('account.fiscalyear').read(cursor, uid, fiscalyear_id, ['date_stop'], context=context)['date_stop']
res_date = self.pool.get('account.fiscalyear').read(cr, uid, fiscalyear_id, ['date_stop'], context=context)['date_stop']
return res_date return res_date
def onchange_fiscalyear(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
def onchange_fiscalyear(self, cr, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
res = {'value': {}} res = {'value': {}}
res['value']['until_date'] = self.default_until_date(cursor, uid, ids,
res['value']['until_date'] = self.default_until_date(cr, uid, ids,
fiscalyear_id=fiscalyear, fiscalyear_id=fiscalyear,
period_id=period_id, period_id=period_id,
date_to=date_to, date_to=date_to,
context=context) context=context)
return res return res
def onchange_date_to(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
def onchange_date_to(self, cr, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
res = {'value': {}} res = {'value': {}}
res['value']['until_date'] = self.default_until_date(cursor, uid, ids,
res['value']['until_date'] = self.default_until_date(cr, uid, ids,
fiscalyear_id=fiscalyear, fiscalyear_id=fiscalyear,
period_id=period_id, period_id=period_id,
date_to=date_to, date_to=date_to,
context=context) context=context)
return res return res
def onchange_period_to(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
def onchange_period_to(self, cr, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None):
res = {'value': {}} res = {'value': {}}
res['value']['until_date'] = self.default_until_date(cursor, uid, ids,
res['value']['until_date'] = self.default_until_date(cr, uid, ids,
fiscalyear_id=fiscalyear, fiscalyear_id=fiscalyear,
period_id=period_id, period_id=period_id,
date_to=date_to, date_to=date_to,
@ -107,20 +107,15 @@ By amending the clearance date, you will be, for instance, able to answer the qu
def pre_print_report(self, cr, uid, ids, data, context=None): def pre_print_report(self, cr, uid, ids, data, context=None):
data = super(AccountReportOpenInvoicesWizard, self).pre_print_report(cr, uid, ids, data, context) data = super(AccountReportOpenInvoicesWizard, self).pre_print_report(cr, uid, ids, data, context)
if context is None:
context = {}
vals = self.read(cr, uid, ids, vals = self.read(cr, uid, ids,
['until_date', 'group_by_currency'], ['until_date', 'group_by_currency'],
context=context)[0] context=context)[0]
data['form'].update(vals) data['form'].update(vals)
return data return data
def _print_report(self, cursor, uid, ids, data, context=None):
context = context or {}
def _print_report(self, cr, uid, ids, data, context=None):
# we update form with display account value # we update form with display account value
data = self.pre_print_report(cursor, uid, ids, data, context=context)
data = self.pre_print_report(cr, uid, ids, data, context=context)
return {'type': 'ir.actions.report.xml', return {'type': 'ir.actions.report.xml',
'report_name': 'account.account_report_open_invoices_webkit', 'report_name': 'account.account_report_open_invoices_webkit',
'datas': data} 'datas': data}
AccountReportOpenInvoicesWizard()

15
account_financial_report_webkit/wizard/partner_balance_wizard.py

@ -19,10 +19,10 @@
# #
############################################################################## ##############################################################################
from osv import fields, osv
from openerp.osv import fields, orm
class AccountPartnerBalanceWizard(osv.osv_memory):
class AccountPartnerBalanceWizard(orm.TransientModel):
"""Will launch partner balance report and pass required args""" """Will launch partner balance report and pass required args"""
_inherit = "account.common.balance.report" _inherit = "account.common.balance.report"
@ -30,9 +30,9 @@ class AccountPartnerBalanceWizard(osv.osv_memory):
_description = "Partner Balance Report" _description = "Partner Balance Report"
_columns = { _columns = {
'result_selection': fields.selection([('customer','Receivable Accounts'),
('supplier','Payable Accounts'),
('customer_supplier','Receivable and Payable Accounts')],
'result_selection': fields.selection([('customer', 'Receivable Accounts'),
('supplier', 'Payable Accounts'),
('customer_supplier', 'Receivable and Payable Accounts')],
"Partner's", required=True), "Partner's", required=True),
'partner_ids': fields.many2many('res.partner', string='Filter on partner', 'partner_ids': fields.many2many('res.partner', string='Filter on partner',
help="Only selected partners will be printed. Leave empty to print all partners."), help="Only selected partners will be printed. Leave empty to print all partners."),
@ -44,8 +44,6 @@ class AccountPartnerBalanceWizard(osv.osv_memory):
def pre_print_report(self, cr, uid, ids, data, context=None): def pre_print_report(self, cr, uid, ids, data, context=None):
data = super(AccountPartnerBalanceWizard, self).pre_print_report(cr, uid, ids, data, context) data = super(AccountPartnerBalanceWizard, self).pre_print_report(cr, uid, ids, data, context)
if context is None:
context = {}
vals = self.read(cr, uid, ids, vals = self.read(cr, uid, ids,
['result_selection', 'partner_ids'], ['result_selection', 'partner_ids'],
context=context)[0] context=context)[0]
@ -53,12 +51,9 @@ class AccountPartnerBalanceWizard(osv.osv_memory):
return data return data
def _print_report(self, cursor, uid, ids, data, context=None): def _print_report(self, cursor, uid, ids, data, context=None):
context = context or {}
# we update form with display account value # we update form with display account value
data = self.pre_print_report(cursor, uid, ids, data, context=context) data = self.pre_print_report(cursor, uid, ids, data, context=context)
return {'type': 'ir.actions.report.xml', return {'type': 'ir.actions.report.xml',
'report_name': 'account.account_report_partner_balance_webkit', 'report_name': 'account.account_report_partner_balance_webkit',
'datas': data} 'datas': data}
AccountPartnerBalanceWizard()

12
account_financial_report_webkit/wizard/partners_ledger_wizard.py

@ -20,10 +20,10 @@
############################################################################## ##############################################################################
import time import time
from osv import fields, osv
from openerp.osv import fields, orm
class AccountReportPartnersLedgerWizard(osv.osv_memory):
class AccountReportPartnersLedgerWizard(orm.TransientModel):
"""Will launch partner ledger report and pass required args""" """Will launch partner ledger report and pass required args"""
_inherit = "account.common.partner.report" _inherit = "account.common.partner.report"
@ -57,7 +57,8 @@ class AccountReportPartnersLedgerWizard(osv.osv_memory):
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None):
res = {} res = {}
if filter == 'filter_no': if filter == 'filter_no':
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False}
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False, 'date_to': False}
if filter == 'filter_date': if filter == 'filter_date':
if fiscalyear_id: if fiscalyear_id:
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context)
@ -100,17 +101,14 @@ class AccountReportPartnersLedgerWizard(osv.osv_memory):
# will be used to attach the report on the main account # will be used to attach the report on the main account
data['ids'] = [data['form']['chart_account_id']] data['ids'] = [data['form']['chart_account_id']]
vals = self.read(cr, uid, ids, vals = self.read(cr, uid, ids,
['amount_currency', 'partner_ids',],
['amount_currency', 'partner_ids'],
context=context)[0] context=context)[0]
data['form'].update(vals) data['form'].update(vals)
return data return data
def _print_report(self, cursor, uid, ids, data, context=None): def _print_report(self, cursor, uid, ids, data, context=None):
context = context or {}
# we update form with display account value # we update form with display account value
data = self.pre_print_report(cursor, uid, ids, data, context=context) data = self.pre_print_report(cursor, uid, ids, data, context=context)
return {'type': 'ir.actions.report.xml', return {'type': 'ir.actions.report.xml',
'report_name': 'account.account_report_partners_ledger_webkit', 'report_name': 'account.account_report_partners_ledger_webkit',
'datas': data} 'datas': data}
AccountReportPartnersLedgerWizard()
Loading…
Cancel
Save