diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 95ecdc8c35a..1a222b2f83c 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -49,7 +49,7 @@ for a particular financial year and for preparation of vouchers there is a modul """, 'website': 'http://www.openerp.com', 'images' : ['images/accounts.jpeg','images/bank_statement.jpeg','images/cash_register.jpeg','images/chart_of_accounts.jpeg','images/customer_invoice.jpeg','images/journal_entries.jpeg'], - 'depends' : ['base_setup', 'product', 'analytic', 'process', 'board', 'edi'], + 'depends' : ['base_setup', 'product', 'analytic', 'process', 'board', 'edi', 'report'], 'data': [ 'security/account_security.xml', 'security/ir.model.access.csv', @@ -126,6 +126,24 @@ for a particular financial year and for preparation of vouchers there is a modul 'account_pre_install.yml', 'views/report_vat.xml', + 'views/report_invoice.xml', + 'views/report_trialbalance.xml', + 'views/report_centraljournal.xml', + 'views/report_overdue.xml', + 'views/report_generaljournal.xml', + 'views/report_journal.xml', + 'views/report_salepurchasejournal.xml', + 'views/report_partnerbalance.xml', + 'views/report_agedpartnerbalance.xml', + 'views/report_partnerledger.xml', + 'views/report_partnerledgerother.xml', + 'views/report_financial.xml', + 'views/report_generalledger.xml', + 'project/views/report_analyticbalance.xml', + 'project/views/report_analyticjournal.xml', + 'project/views/report_analyticcostledgerquantity.xml', + 'project/views/report_analyticcostledger.xml', + 'project/views/report_invertedanalyticbalance.xml', ], 'js': [ 'static/src/js/account_move_reconciliation.js', @@ -157,8 +175,6 @@ for a particular financial year and for preparation of vouchers there is a modul 'test/account_period_close.yml', 'test/account_use_model.yml', 'test/account_validate_account_move.yml', - #'test/account_bank_statement.yml', - #'test/account_cash_statement.yml', 'test/test_edi_invoice.yml', 'test/account_report.yml', 'test/account_fiscalyear_close.yml', #last test, as it will definitively close the demo fiscalyear @@ -166,4 +182,5 @@ for a particular financial year and for preparation of vouchers there is a modul 'installable': True, 'auto_install': False, } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 5a0e1411fe8..a9a9e9a98ec 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -409,17 +409,9 @@ class account_invoice(osv.osv): ''' assert len(ids) == 1, 'This option should only be used for a single id at a time.' self.write(cr, uid, ids, {'sent': True}, context=context) - datas = { - 'ids': ids, - 'model': 'account.invoice', - 'form': self.read(cr, uid, ids[0], context=context) - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.invoice', - 'datas': datas, - 'nodestroy' : True - } + context2 = context.copy() + context2['active_ids'] = ids + return self.pool['report'].get_action(cr, uid, [], 'account.report_invoice', context=context2) def action_invoice_sent(self, cr, uid, ids, context=None): ''' diff --git a/addons/account/account_report.xml b/addons/account/account_report.xml index 4f9ad1b5c56..90d2c1637fb 100644 --- a/addons/account/account_report.xml +++ b/addons/account/account_report.xml @@ -1,45 +1,168 @@ - - - - - - - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + parent="account.menu_finance_generic_reporting" + sequence="3" + /> diff --git a/addons/account/project/project_report.xml b/addons/account/project/project_report.xml index 3ee449e01b5..de2e2feee5a 100644 --- a/addons/account/project/project_report.xml +++ b/addons/account/project/project_report.xml @@ -1,29 +1,54 @@ - + - + - + - - - + + diff --git a/addons/account/project/report/account_journal.py b/addons/account/project/report/account_journal.py deleted file mode 100644 index 50f98fd0ee0..00000000000 --- a/addons/account/project/report/account_journal.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - - -import time -from openerp.report import report_sxw - -# -# Use period and Journal for selection or resources -# -class journal_print(report_sxw.rml_parse): - def lines(self, journal_id, *args): - self.cr.execute('select id from account_analytic_line where journal_id=%s order by date,id', (journal_id,)) - ids = map(lambda x: x[0], self.cr.fetchall()) - res = self.pool.get('account.analytic.line').browse(self.cr, self.uid, ids) - return res - def _sum_lines(self, journal_id): - self.cr.execute('select sum(amount) from account_analytic_line where journal_id=%s', (journal_id,)) - return self.cr.fetchone()[0] or 0.0 - def __init__(self, cr, uid, name, context): - super(journal_print, self).__init__(cr, uid, name, context=context) - self.localcontext = { - 'time': time, - 'lines': self.lines, - 'sum_lines': self._sum_lines, - } -report_sxw.report_sxw('report.account.analytic.journal.print', 'account.analytic.journal', 'addons/account/project/report/analytic_journal.rml',parser=journal_print) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/analytic_balance.py b/addons/account/project/report/analytic_balance.py index 2aa9f2c549e..7c333b84c45 100644 --- a/addons/account/project/report/analytic_balance.py +++ b/addons/account/project/report/analytic_balance.py @@ -20,7 +20,7 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw @@ -56,7 +56,6 @@ class account_analytic_balance(report_sxw.rml_parse): self.get_children(data['child_ids']) return True - def _get_objects(self, empty_acc): if self.read_data: return self.read_data @@ -143,18 +142,16 @@ class account_analytic_balance(report_sxw.rml_parse): WHERE account_id IN %s AND date>=%s AND date<=%s",query_params) return self.cr.fetchone()[0] or 0.0 - - def _sum_balance(self, accounts, date1, date2): debit = self._sum_all(accounts, date1, date2, 'debit') or 0.0 credit = self._sum_all(accounts, date1, date2, 'credit') or 0.0 return (debit-credit) -report_sxw.report_sxw('report.account.analytic.account.balance', - 'account.analytic.account', 'addons/account/project/report/analytic_balance.rml', - parser=account_analytic_balance, header="internal") - +class report_analyticbalance(osv.AbstractModel): + _name = 'report.account.report_analyticbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticbalance' + _wrapped_report_class = account_analytic_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/analytic_balance.rml b/addons/account/project/report/analytic_balance.rml deleted file mode 100644 index 1754988f7d6..00000000000 --- a/addons/account/project/report/analytic_balance.rml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - Account Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - - Analytic Balance - [[ company.currency_id.name ]] - - - - - - - - - - Code - - - Account Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - Total - - - - - - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'debit')) ]] - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'credit')) ]] - - - [[ formatLang(sum_balance(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'quantity')) ]] - - - -
- [[ repeatIn(get_objects(data['form']['empty_acc']),'o') ]] - - - - [[ o['code'] ]] - - - [[ o['complete_name'] ]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'debit')) ]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'credit')) ]] - - - [[ formatLang(move_sum_balance(o['id'],data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'quantity')) ]] - - - -
- [[ repeatIn(lines_g(o['id'],data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang(move_g['debit'])]] - - - [[ formatLang(move_g['credit']) ]] - - - [[ formatLang(move_g['balance'], currency_obj = company.currency_id) ]] - - - [[ formatLang(move_g['quantity']) ]] - - - - - - -
-
- - - - - - -
-
-
\ No newline at end of file diff --git a/addons/account/project/report/analytic_journal.py b/addons/account/project/report/analytic_journal.py index 1ca1ffb3ca4..c59efb057d7 100644 --- a/addons/account/project/report/analytic_journal.py +++ b/addons/account/project/report/analytic_journal.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + # # Use period and Journal for selection or resources # @@ -57,8 +58,11 @@ class account_analytic_journal(report_sxw.rml_parse): res = self.cr.dictfetchone() return res['sum'] or 0 -report_sxw.report_sxw('report.account.analytic.journal', 'account.analytic.journal', 'addons/account/project/report/analytic_journal.rml',parser=account_analytic_journal,header="internal") +class report_analyticjournal(osv.AbstractModel): + _name = 'report.account.report_analyticjournal' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticjournal' + _wrapped_report_class = account_analytic_journal # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/analytic_journal.rml b/addons/account/project/report/analytic_journal.rml deleted file mode 100644 index 719851252b5..00000000000 --- a/addons/account/project/report/analytic_journal.rml +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - - - - Analytic Journal - - - - - - - Period from - - - Period to - - - Currency - - - - - - - [[ formatLang(data['form']['date1'],date=True) ]] - - - [[ formatLang(data['form']['date2'],date=True) ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Date - - - Code - - - Move Name - - - Account n° - - - General - - - Analytic - - - - - - - - - - [[ o.code ]] - [[ o.name ]] - - - - - - - - - - - - - - - - - - [[ formatLang(sum_general(o.id,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang(sum_analytic(o.id,data['form']['date1'],data['form']['date2'])) ]] - - - - - - -
- [[ repeatIn(lines(o.id,data['form']['date1'],data['form']['date2']), 'move') ]] - - - - - - - - - - - - - - [[ move.name ]] KI - - - [[ move.account_id.code ]] [[ move.account_id.name ]] - - - [[ formatLang(move.debit-move.credit) ]] - - - - - - - - - - - -
- [[ repeatIn(lines_a(move.id,o.id,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ formatLang(move_a.date,date = True) ]] - - - [[ move_a.code ]] - - - [[ move_a.name ]] - - - [[ move_a.account_id.code ]] - [[ move_a.account_id.name ]] - - - - - - - - [[ formatLang( move_a.amount) ]] - - - - - - -
- - - - - - -
- - - -
- [[ repeatIn(lines_a(False,o.id,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ formatLang(move_a.date,date = True) ]] - - - [[ move_a.code ]] - - - [[ move_a.name ]] - - - [[ move_a.account_id.code ]] - [[ move_a.account_id.name ]] - - - - - - - - [[ formatLang( move_a.amount) ]] - - - - - - -
- - - -
-
diff --git a/addons/account/project/report/cost_ledger.py b/addons/account/project/report/cost_ledger.py index e594ab92a63..5eef375eaab 100644 --- a/addons/account/project/report/cost_ledger.py +++ b/addons/account/project/report/cost_ledger.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class account_analytic_cost_ledger(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(account_analytic_cost_ledger, self).__init__(cr, uid, name, context=context) @@ -100,8 +101,11 @@ class account_analytic_cost_ledger(report_sxw.rml_parse): credit = self._sum_credit(accounts, date1, date2) return (debit-credit) -report_sxw.report_sxw('report.account.analytic.account.cost_ledger', 'account.analytic.account', 'addons/account/project/report/cost_ledger.rml',parser=account_analytic_cost_ledger, header="internal") +class report_analyticcostledger(osv.AbstractModel): + _name = 'report.account.report_analyticcostledger' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticcostledger' + _wrapped_report_class = account_analytic_cost_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/cost_ledger.rml b/addons/account/project/report/cost_ledger.rml deleted file mode 100644 index 1099a8b8b4e..00000000000 --- a/addons/account/project/report/cost_ledger.rml +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date/Code - - - J.C. /Move name - - - Debit - - - Credit - - - Balance - - - - - - - - - - - - - Cost Ledger - - - - - - - - - - - - Period from - - - Period to - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date = True) ]] - - - [[ formatLang(data['form']['date2'],date = True) ]] - - - [[ formatLang(time.strftime('%Y-%m-%d %H:%M:%S'),date_time = True) ]] - - - - - - - - - - Date/Code - - - J.C. /Move name - - - Debit - - - Credit - - - Balance - - - - - - - Total: - - - - - - - - [[ formatLang (sum_debit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (sum_credit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (sum_balance(objects,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id) ]] - - - -
- [[ repeatIn(objects,'account') ]] - - - - [[ account.code ]] - - - [[ account.complete_name ]] - - - [[ formatLang (account_sum_debit(account,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (account_sum_credit(account,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (account_sum_balance(account,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id) ]] - - - -
- [[ repeatIn(lines_g(account,data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang( move_g['debit']) ]] - - - [[ formatLang( move_g['credit']) ]] - - - [[ formatLang( move_g['balance'], currency_obj = company.currency_id) ]] - - - -
- [[ repeatIn(lines_a(move_g,account,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ formatLang(move_a['date'],date = True) ]] - - - [[ move_a['cj'] ]] - - - [[ move_a['name'] ]] - - - [[ formatLang( move_a['debit'] )]] - - - [[ formatLang( move_a['credit']) ]] - - - [[ formatLang( move_a['balance'], currency_obj = company.currency_id)]] - - - - - - -
-
-
-
-
-
diff --git a/addons/account/project/report/inverted_analytic_balance.py b/addons/account/project/report/inverted_analytic_balance.py index bd86bcfe257..23129144555 100644 --- a/addons/account/project/report/inverted_analytic_balance.py +++ b/addons/account/project/report/inverted_analytic_balance.py @@ -20,7 +20,7 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw class account_inverted_analytic_balance(report_sxw.rml_parse): @@ -120,8 +120,11 @@ class account_inverted_analytic_balance(report_sxw.rml_parse): WHERE account_id IN %s AND date>=%s AND date<=%s", (tuple(ids),date1, date2,)) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.analytic.account.inverted.balance', 'account.analytic.account', 'addons/account/project/report/inverted_analytic_balance.rml',parser=account_inverted_analytic_balance, header="internal") +class report_invertedanalyticbalance(osv.AbstractModel): + _name = 'report.account.report_invertedanalyticbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_invertedanalyticbalance' + _wrapped_report_class = account_inverted_analytic_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/inverted_analytic_balance.rml b/addons/account/project/report/inverted_analytic_balance.rml deleted file mode 100644 index 54b6878c407..00000000000 --- a/addons/account/project/report/inverted_analytic_balance.rml +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - Inverted Analytic Balance - [[ company.currency_id.name ]] - - - - - - - - - - Code - - - Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - - - Total - - - - - - - - [[ formatLang(sum_debit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang(sum_credit(objects,data['form']['date1'],data['form']['date2']))]] - - - [[ formatLang(sum_balance(objects,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(sum_quantity(objects,data['form']['date1'],data['form']['date2'])) ]] - - - -
- [[ repeatIn(lines_g(objects,data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ (not move_g) and removeParentNode('blockTable') ]] [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang(move_g['debit'])]] - - - [[formatLang(move_g['credit'])]] - - - [[ formatLang(move_g['balance'], currency_obj = company.currency_id)]] - - - [[formatLang(move_g['quantity']) ]] - - - -
- [[ repeatIn(lines_a(objects,move_g['id'],data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ move_a['code'] ]] - - - [[ move_a['complete_name'] ]] - - - [[ formatLang(move_a['debit']) ]] - - - [[ formatLang(move_a['credit']) ]] - - - [[ formatLang(move_a['balance'], currency_obj = company.currency_id)]] - - - [[ formatLang(move_a['quantity']) ]] - - - - - - -
-
-
-
-
\ No newline at end of file diff --git a/addons/account/project/report/quantity_cost_ledger.py b/addons/account/project/report/quantity_cost_ledger.py index b22558b900f..d3ed1cdc3a8 100644 --- a/addons/account/project/report/quantity_cost_ledger.py +++ b/addons/account/project/report/quantity_cost_ledger.py @@ -19,9 +19,10 @@ # ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class account_analytic_quantity_cost_ledger(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(account_analytic_quantity_cost_ledger, self).__init__(cr, uid, name, context=context) @@ -116,9 +117,11 @@ class account_analytic_quantity_cost_ledger(report_sxw.rml_parse): AND journal_id IN %s",(tuple(ids), date1, date2, tuple(journal_ids))) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.analytic.account.quantity_cost_ledger', - 'account.analytic.account', - 'addons/account/project/report/quantity_cost_ledger.rml', - parser=account_analytic_quantity_cost_ledger, header="internal") + +class report_analyticcostledgerquantity(osv.AbstractModel): + _name = 'report.account.report_analyticcostledgerquantity' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticcostledgerquantity' + _wrapped_report_class = account_analytic_quantity_cost_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/report/quantity_cost_ledger.rml b/addons/account/project/report/quantity_cost_ledger.rml deleted file mode 100644 index 9f99f50ccc2..00000000000 --- a/addons/account/project/report/quantity_cost_ledger.rml +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code/Date - - - J.C./Move name - - - Quantity - - - Total - - - - - - - - - - - - - Cost Ledger - - - - - - - - - - - - Period from - - - Period to - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date = True) ]] - - - [[ formatLang(data['form']['date2'],date = True) ]] - - - [[ formatLang(time.strftime('%Y-%m-%d %H:%M:%S'),date_time = True) ]] - - - - - - - - - - - - - Code/Date - - - J.C./Move name - - - Quantity - - - Total - - - - - - - Total: - - - - - - - - - - - - - [[ formatLang (sum_quantity(objects,data['form']['date1'],data['form']['date2'], data['form']['journal']) ) ]] - - - -
- [[ repeatIn(objects,'o') ]] - - - - [[ o.code ]] - - - [[ o.complete_name ]] - - - Max Qty: [[ formatLang (o.quantity_max )]] - - - [[ formatLang (account_sum_quantity(o.id,data['form']['date1'],data['form']['date2'], data['form']['journal']) )]] - - - -
- [[ repeatIn(lines_g(o.id,data['form']['date1'],data['form']['date2'],data['form']['journal']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang (move_g['quantity']) ]] - - - - - - - [[ repeatIn(lines_a(move_g['id'],o.id,data['form']['date1'],data['form']['date2'],data['form']['journal']),'move_a') ]] - [[ formatLang(move_a['date'],date = True) ]] - - - [[ move_a['cj'] ]] - - - [[ move_a['name'] ]] - - - [[ formatLang (move_a['quantity'] )]] - - - - - - -
-
-
-
-
\ No newline at end of file diff --git a/addons/account/project/views/report_analyticbalance.xml b/addons/account/project/views/report_analyticbalance.xml new file mode 100644 index 00000000000..09cd56fc83f --- /dev/null +++ b/addons/account/project/views/report_analyticbalance.xml @@ -0,0 +1,62 @@ + + + + + + diff --git a/addons/account/project/views/report_analyticcostledger.xml b/addons/account/project/views/report_analyticcostledger.xml new file mode 100644 index 00000000000..cda37d4158f --- /dev/null +++ b/addons/account/project/views/report_analyticcostledger.xml @@ -0,0 +1,90 @@ + + + + + + \ No newline at end of file diff --git a/addons/account/project/views/report_analyticcostledgerquantity.xml b/addons/account/project/views/report_analyticcostledgerquantity.xml new file mode 100644 index 00000000000..de49d4972e5 --- /dev/null +++ b/addons/account/project/views/report_analyticcostledgerquantity.xml @@ -0,0 +1,87 @@ + + + + + + \ No newline at end of file diff --git a/addons/account/project/views/report_analyticjournal.xml b/addons/account/project/views/report_analyticjournal.xml new file mode 100644 index 00000000000..1b3a4fda97c --- /dev/null +++ b/addons/account/project/views/report_analyticjournal.xml @@ -0,0 +1,90 @@ + + + + + + diff --git a/addons/account/project/views/report_invertedanalyticbalance.xml b/addons/account/project/views/report_invertedanalyticbalance.xml new file mode 100644 index 00000000000..e545ec8525b --- /dev/null +++ b/addons/account/project/views/report_invertedanalyticbalance.xml @@ -0,0 +1,91 @@ + + + + + + diff --git a/addons/account/project/wizard/account_analytic_balance_report.py b/addons/account/project/wizard/account_analytic_balance_report.py index 02b2eb6e95d..3a3c301cffc 100644 --- a/addons/account/project/wizard/account_analytic_balance_report.py +++ b/addons/account/project/wizard/account_analytic_balance_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_balance(osv.osv_memory): _name = 'account.analytic.balance' _description = 'Account Analytic Balance' @@ -42,16 +43,13 @@ class account_analytic_balance(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.balance', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticbalance', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py index 814cbb8cacc..125dfda46fb 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_cost_ledger_journal_report(osv.osv_memory): _name = 'account.analytic.cost.ledger.journal.report' _description = 'Account Analytic Cost Ledger For Journal Report' @@ -42,14 +43,12 @@ class account_analytic_cost_ledger_journal_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.quantity_cost_ledger', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + + datas['form']['active_ids'] = context.get('active_ids', False) + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticcostledgerquantity', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_report.py index ffd56352382..5f00c3c9ac5 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_report.py @@ -20,9 +20,9 @@ ############################################################################## import time - from openerp.osv import osv, fields + class account_analytic_cost_ledger(osv.osv_memory): _name = 'account.analytic.cost.ledger' _description = 'Account Analytic Cost Ledger' @@ -42,14 +42,13 @@ class account_analytic_cost_ledger(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.cost_ledger', - 'datas': datas, - } + 'ids': context.get('active_ids',[]), + 'model': 'account.analytic.account', + 'form': data + } + + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticcostledger', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_inverted_balance_report.py b/addons/account/project/wizard/account_analytic_inverted_balance_report.py index 9e54f4f848d..ad79c0b33f6 100644 --- a/addons/account/project/wizard/account_analytic_inverted_balance_report.py +++ b/addons/account/project/wizard/account_analytic_inverted_balance_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_inverted_balance(osv.osv_memory): _name = 'account.analytic.inverted.balance' _description = 'Account Analytic Inverted Balance' @@ -41,14 +42,11 @@ class account_analytic_inverted_balance(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.inverted.balance', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + datas['form']['active_ids'] = context.get('active_ids', False) + return self.pool['report'].get_action(cr, uid, ids, 'account.report_invertedanalyticbalance', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_journal_report.py b/addons/account/project/wizard/account_analytic_journal_report.py index 61fe2cd318a..f2e406bc3a5 100644 --- a/addons/account/project/wizard/account_analytic_journal_report.py +++ b/addons/account/project/wizard/account_analytic_journal_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_journal_report(osv.osv_memory): _name = 'account.analytic.journal.report' _description = 'Account Analytic Journal' @@ -49,16 +50,15 @@ class account_analytic_journal_report(osv.osv_memory): for analytic_record in record.analytic_account_journal_id: ids_list.append(analytic_record.id) datas = { - 'ids': ids_list, - 'model': 'account.analytic.journal', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.journal', - 'datas': datas, - } - + 'ids': ids_list, + 'model': 'account.analytic.journal', + 'form': data + } + context2 = context.copy() + context2['active_model'] = 'account.analytic.journal' + context2['active_ids'] = ids_list + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticjournal', data=datas, context=context2) + def default_get(self, cr, uid, fields, context=None): if context is None: context = {} diff --git a/addons/account/report/__init__.py b/addons/account/report/__init__.py index 544aa9e262e..ed8cc0aa8b3 100644 --- a/addons/account/report/__init__.py +++ b/addons/account/report/__init__.py @@ -26,12 +26,8 @@ import account_balance import account_partner_balance import account_general_ledger import account_partner_ledger -#import invoice -import account_print_invoice -#import overdue import account_print_overdue import account_aged_partner_balance -#import tax_report import report_vat import account_invoice_report import account_report diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py index 3b000e40592..3fd83c19207 100644 --- a/addons/account/report/account_aged_partner_balance.py +++ b/addons/account/report/account_aged_partner_balance.py @@ -20,9 +20,11 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class aged_trial_report(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context): @@ -375,8 +377,11 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header): return self._translate('Receivable and Payable Accounts') return '' -report_sxw.report_sxw('report.account.aged_trial_balance', 'res.partner', - 'addons/account/report/account_aged_partner_balance.rml',parser=aged_trial_report, header="internal landscape") +class report_agedpartnerbalance(osv.AbstractModel): + _name = 'report.account.report_agedpartnerbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_agedpartnerbalance' + _wrapped_report_class = aged_trial_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_aged_partner_balance.rml b/addons/account/report/account_aged_partner_balance.rml deleted file mode 100644 index 5b5404e9c86..00000000000 --- a/addons/account/report/account_aged_partner_balance.rml +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Aged Trial Balance - - - - - - - Chart of Accounts - - - Fiscal Year - - - Start Date - - - Period Length(days) - - - Partner's - - - Analysis Direction - - - Target Moves - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[ formatLang(data['form']['date_from'],date=True) ]] - - - [[ data['form']['period_length'] ]] - - - Receivable Accounts[[ data['form']['result_selection'] == 'customer' or removeParentNode('para') ]] - Payable Accounts[[ data['form']['result_selection'] == 'supplier' or removeParentNode('para') ]] - Receivable and Payable Accounts[[ data['form']['result_selection'] == 'customer_supplier' or removeParentNode('para') ]] - - - [[ data['form']['direction_selection'] ]] - - - [[ get_target_move(data) ]] - - - - - - - - - - Partners - - - Due[[ data['form']['direction_selection'] == 'future' and ' ' or removeParentNode('para') ]] - Not due[[ data['form']['direction_selection'] != 'future' and ' ' or removeParentNode('para') ]] - - - [[ data['form']['4']['name'] ]] - - - [[ data['form']['3']['name'] ]] - - - [[ data['form']['2']['name'] ]] - - - [[ data['form']['1']['name'] ]] - - - [[ data['form']['0']['name'] ]] - - - Total - - - - - - - [[ (get_lines(data['form']), 'partner') == False or removeParentNode('para') ]] - [[ (get_lines_with_out_partner(data['form']), 'not_partner') == False or removeParentNode('para') ]] - Account Total - - - [[ formatLang(get_direction('6'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('4'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('3'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('2'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('1'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('0'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_total('5'), currency_obj=company.currency_id) ]] - - - - - - [[ repeatIn(get_lines(data['form']), 'partner') ]] - [[ partner['name'] ]] - - - [[ formatLang(partner['direction'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['4'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['3'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['2'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['1'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['0'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['total'], currency_obj=company.currency_id) ]] - - - - - [[ repeatIn(get_lines_with_out_partner(data['form']), 'not_partner') ]] - [[ not_partner['name'] ]] - - - [[ formatLang(not_partner['direction'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['4'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['3'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['2'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['1'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['0'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['total'], currency_obj=company.currency_id) ]] - - - - - - - - - - diff --git a/addons/account/report/account_balance.py b/addons/account/report/account_balance.py index 2a445984b27..af2c37fc610 100644 --- a/addons/account/report/account_balance.py +++ b/addons/account/report/account_balance.py @@ -21,9 +21,11 @@ import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class account_balance(report_sxw.rml_parse, common_report_header): _name = 'report.account.account.balance' @@ -58,11 +60,6 @@ class account_balance(report_sxw.rml_parse, common_report_header): objects = self.pool.get('account.account').browse(self.cr, self.uid, new_ids) return super(account_balance, self).set_context(objects, data, new_ids, report_type=report_type) - #def _add_header(self, node, header=1): - # if header == 0: - # self.rml_header = "" - # return True - def _get_account(self, data): if data['model']=='account.account': return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['id']).company_id.name @@ -131,6 +128,11 @@ class account_balance(report_sxw.rml_parse, common_report_header): _process_child(accounts,form['display_account'],parent) return self.result_acc -report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header="internal") + +class report_trialbalance(osv.AbstractModel): + _name = 'report.account.report_trialbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_trialbalance' + _wrapped_report_class = account_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_balance.rml b/addons/account/report/account_balance.rml deleted file mode 100644 index 08c05c65fa8..00000000000 --- a/addons/account/report/account_balance.rml +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Trial Balance - - - - - - - - - - - - - Company[[ data['model']=='account.account' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - - - Fiscal Year - - - Display Account - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Target Moves - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - All[[ data['form']['display_account']=='all' and ' ' or removeParentNode('para') ]] - With movements[[ data['form']['display_account']=='movement' and ' ' or removeParentNode('para') ]] - With balance is not equal to 0[[ data['form']['display_account']=='not_zero' and ' ' or removeParentNode('para') ]] - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - [[ get_target_move(data) ]] - - - - - - - - - - - - Code - Account - Debit - Credit - Balance - - - [[ repeatIn(lines(data['form']), 'a') ]][[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['code'] or removeParentNode('tr') ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ '..'*(a['level']-1) ]][[ a['name'] ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['debit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[formatLang(a['debit']) ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font')]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['credit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['credit']) ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['balance'], currency_obj=company.currency_id) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['balance'], currency_obj=company.currency_id) ]] - - - - - - - diff --git a/addons/account/report/account_central_journal.py b/addons/account/report/account_central_journal.py index 8dae208a7a5..28892d0730e 100644 --- a/addons/account/report/account_central_journal.py +++ b/addons/account/report/account_central_journal.py @@ -20,11 +20,14 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header # # Use period and Journal for selection or resources # + + class journal_print(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context=None): @@ -103,6 +106,11 @@ class journal_print(report_sxw.rml_parse, common_report_header): return True return data['form']['amount_currency'] -report_sxw.report_sxw('report.account.central.journal', 'account.journal.period', 'addons/account/report/account_central_journal.rml', parser=journal_print, header='external') + +class report_agedpartnerbalance(osv.AbstractModel): + _name = 'report.account.report_centraljournal' + _inherit = 'report.abstract_report' + _template = 'account.report_centraljournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_central_journal.rml b/addons/account/report/account_central_journal.rml deleted file mode 100644 index 6d350b5fe8f..00000000000 --- a/addons/account/report/account_central_journal.rml +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - - Centralized Journal - - - - - - Chart of Accounts - Fiscal Year - Journal - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[o.journal_id.name ]] - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_target_move(data) ]] - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - A/C No. - Account Name - Debit - Credit - Balance - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - A/C No. - Account Name - Debit - Credit - Balance - Currency - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - Total: - - [[ formatLang( sum_debit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)-sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id ) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - Total: - - [[ formatLang( sum_debit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)-sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id ) ]] - - - -
- [[ repeatIn(lines(o.period_id.id,o.journal_id.id),'line') ]] - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit']) ]] - [[ formatLang(line['credit'])]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit']) ]] - [[ formatLang(line['credit'])]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - -
- -
-
diff --git a/addons/account/report/account_entries_report.py b/addons/account/report/account_entries_report.py index 6060d97c182..df2d92c9f12 100644 --- a/addons/account/report/account_entries_report.py +++ b/addons/account/report/account_entries_report.py @@ -94,7 +94,7 @@ class account_entries_report(osv.osv): return super(account_entries_report, self).search(cr, uid, args=args, offset=offset, limit=limit, order=order, context=context, count=count) - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False,lazy=True): if context is None: context = {} fiscalyear_obj = self.pool.get('account.fiscalyear') @@ -108,7 +108,7 @@ class account_entries_report(osv.osv): domain.append(['period_id','in',ids]) else: domain = domain - return super(account_entries_report, self).read_group(cr, uid, domain, fields, groupby, offset, limit, context, orderby) + return super(account_entries_report, self).read_group(cr, uid, domain, fields, groupby, offset, limit, context, orderby,lazy) def init(self, cr): tools.drop_view_if_exists(cr, 'account_entries_report') diff --git a/addons/account/report/account_financial_report.py b/addons/account/report/account_financial_report.py index 2b1f5af4d68..064f02c5fbf 100644 --- a/addons/account/report/account_financial_report.py +++ b/addons/account/report/account_financial_report.py @@ -23,6 +23,8 @@ import time from openerp.report import report_sxw from common_report_header import common_report_header from openerp.tools.translate import _ +from openerp.osv import osv + class report_account_common(report_sxw.rml_parse, common_report_header): @@ -105,8 +107,11 @@ class report_account_common(report_sxw.rml_parse, common_report_header): lines.append(vals) return lines -report_sxw.report_sxw('report.account.financial.report', 'account.financial.report', - 'addons/account/report/account_financial_report.rml', parser=report_account_common, header='internal') +class report_financial(osv.AbstractModel): + _name = 'report.account.report_financial' + _inherit = 'report.abstract_report' + _template = 'account.report_financial' + _wrapped_report_class = report_account_common # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_financial_report.rml b/addons/account/report/account_financial_report.rml deleted file mode 100644 index 7949077e43f..00000000000 --- a/addons/account/report/account_financial_report.rml +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ data['form']['account_report_id'][1] ]] - - - - - - - - - - Chart of Accounts - Fiscal Year - Filter By [[ get_filter(data)!='No Filters' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[ get_filter(data)=='No Filters' and get_filter(data) or removeParentNode('para') ]] - [[ get_filter(data)=='Date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ get_filter(data)=='Periods' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - [[ get_target_move(data) ]] - - - - - - - - - - - - - [[ data['form']['debit_credit'] == 1 or removeParentNode('blockTable') ]] - - - Name - - - Debit - - - Credit - - - Balance - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('debit',0.0), currency_obj = company.currency_id) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('credit',0.0), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - - - - - - [[ (not data['form']['enable_filter'] and not data['form']['debit_credit']) or removeParentNode('blockTable') ]] - - - Name - - - Balance - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - - - - - - - - - [[ (data['form']['enable_filter'] == 1 and not data['form']['debit_credit']) or removeParentNode('blockTable') ]] - - - Name - - - Balance - - - [[ data['form']['label_filter'] ]] - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance_cmp'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance_cmp'), currency_obj = company.currency_id) ]] - - - - - - - diff --git a/addons/account/report/account_general_journal.py b/addons/account/report/account_general_journal.py index 4f63411478c..ada615e31fa 100644 --- a/addons/account/report/account_general_journal.py +++ b/addons/account/report/account_general_journal.py @@ -20,8 +20,10 @@ ############################################################################## import time -from common_report_header import common_report_header +from openerp.osv import osv from openerp.report import report_sxw +from common_report_header import common_report_header + class journal_print(report_sxw.rml_parse, common_report_header): @@ -156,6 +158,11 @@ class journal_print(report_sxw.rml_parse, common_report_header): (tuple(move_state), period_id, tuple(journals))) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.general.journal', 'account.journal.period', 'addons/account/report/general_journal.rml', parser=journal_print, header='internal') + +class report_generaljournal(osv.AbstractModel): + _name = 'report.account.report_generaljournal' + _inherit = 'report.abstract_report' + _template = 'account.report_generaljournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_general_journal.rml b/addons/account/report/account_general_journal.rml deleted file mode 100644 index dce30e59918..00000000000 --- a/addons/account/report/account_general_journal.rml +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn( periods(objects), 'o') ]] - - - - - - - - - - General Journal - - - - - - - - - - - Company[[ data['model']=='account.journal.period' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - Fiscal Year - Journals - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True)]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_target_move(data) ]] - - - - - - - [[ display_currency(data)==False or removeParentNode('blockTable') ]] - - Code - Journal Name - Debit - Credit - Balance - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang( sum_credit()) ]] - [[ formatLang( sum_debit()- sum_credit(), currency_obj=company.currency_id) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - Code - Journal Name - Debit - Credit - Balance - Currency - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang( sum_credit()) ]] - [[ formatLang( sum_credit()- sum_debit(), currency_obj=company.currency_id) ]] - - - -
- [[ display_currency(data) or removeParentNode('blockTable') ]] - - - [[ o.name ]] : - - - - - - - [[ formatLang(sum_debit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)-sum_debit_period(o.id), currency_obj=company.currency_id) ]] - - - - - - - - - - [[ display_currency(data)==False or removeParentNode('blockTable') ]] - - - [[ o.name ]] : - - - - - - - [[ formatLang(sum_debit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)-sum_debit_period(o.id), currency_obj=company.currency_id) ]] - - - -
- [[ repeatIn(lines(o.id),'line')]] - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - [[ line['code'] ]] - - - [[ line['name'] ]] - - - [[ formatLang(line['debit'] )]] - - - [[ formatLang(line['credit']) ]] - - - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - - - -
-
- [[ repeatIn(lines(o.id),'line')]] - [[ display_currency(data) or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit'] )]] - [[ formatLang(line['credit']) ]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - -
- - - -
- - - -
-
diff --git a/addons/account/report/account_general_ledger.py b/addons/account/report/account_general_ledger.py index 4f712ad58cc..ffccbec300d 100644 --- a/addons/account/report/account_general_ledger.py +++ b/addons/account/report/account_general_ledger.py @@ -28,9 +28,11 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class general_ledger(report_sxw.rml_parse, common_report_header): _name = 'report.account.general.ledger' @@ -304,7 +306,11 @@ class general_ledger(report_sxw.rml_parse, common_report_header): return self._translate('Journal & Partner') return self._translate('Date') -report_sxw.report_sxw('report.account.general.ledger', 'account.account', 'addons/account/report/account_general_ledger.rml', parser=general_ledger, header='internal') -report_sxw.report_sxw('report.account.general.ledger_landscape', 'account.account', 'addons/account/report/account_general_ledger_landscape.rml', parser=general_ledger, header='internal landscape') + +class report_generalledger(osv.AbstractModel): + _name = 'report.account.report_generalledger' + _inherit = 'report.abstract_report' + _template = 'account.report_generalledger' + _wrapped_report_class = general_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_general_ledger.rml b/addons/account/report/account_general_ledger.rml deleted file mode 100644 index 6897e15078d..00000000000 --- a/addons/account/report/account_general_ledger.rml +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - - - [[ repeatIn(objects, 'a') ]] - General Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - [[ get_target_move(data) ]] - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - -
- [[ repeatIn(get_children_accounts(a), 'o') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - [[ o.currency_id and formatLang(sum_currency_amount_account(o), digits=get_digits(dp='Account'),currency_obj=o.currency_id) or '' ]] - - - -
- [[ repeatIn(lines(o), 'line') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],10) ]] - - - [[ line['lref'] and strip_name(line['lref'],9) ]] - - - [[ strip_name(line['move'],9) ]] - - - [[ strip_name(line['lname'],10) ]] - - - [[ strip_name(line['line_corresp'].replace(', ',','),10) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - [[ (line.has_key('currency_id') and line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'])]] [[ line['currency_code'] or '']] - - - -
-
- [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - -
- [[ repeatIn(get_children_accounts(a), 'o') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
- [[ repeatIn(lines(o), 'line') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],20) ]] - - - [[ line['lref'] and strip_name(line['lref'],9) ]] - - - [[ strip_name(line['move'],9) ]] - - - [[ strip_name(line['lname'],18) ]] - - - [[ strip_name(line['line_corresp'].replace(', ',','),20) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
-
-
-
-
diff --git a/addons/account/report/account_general_ledger_landscape.rml b/addons/account/report/account_general_ledger_landscape.rml deleted file mode 100644 index c5d24343148..00000000000 --- a/addons/account/report/account_general_ledger_landscape.rml +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - - - [[ repeatIn(objects, 'a') ]] - General Ledger - - - - - - - Company[[ data['model']=='account.account' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - - Fiscal Year - - - Journals - - - Display Account - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Entries Sorted By - - - Target Moves - - - - - - - [[ get_account(data) or removeParentNode('para') ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - All[[ data['form']['display_account']=='all' and ' ' or removeParentNode('para') ]] - With movements[[ data['form']['display_account']=='movement' and ' ' or removeParentNode('para') ]] - With balance is not equal to 0[[ data['form']['display_account']=='not_zero' and ' ' or removeParentNode('para') ]] - - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - [[ get_sortby(data) ]] - - - [[ get_target_move(data) ]] - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - -
- [[ repeatIn(get_children_accounts(a), 'o') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency_obj= company.currency_id) ]] - - - [[ o.currency_id and formatLang(sum_currency_amount_account(o), digits=get_digits(dp='Account'),currency_obj=o.currency_id) or '' ]] - - - -
- [[ repeatIn(lines(o), 'line') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['period_code'] ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],20) ]] - - - [[ line['lref'] and strip_name(line['lref'],17) ]] - - - [[ line['move'] ]] - - - [[ strip_name(line['lname'],22) ]] - - - [[ strip_name(line['line_corresp'],18) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (line.has_key('currency_id') and line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'])]] [[ line['currency_code'] or '']] - - - -
-
- [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - -
- [[ repeatIn(get_children_accounts(a), 'o') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - -
- [[ repeatIn(lines(o), 'line') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['period_code'] ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],24) ]] - - - [[ strip_name(line['lref'],21) ]] - - - [[ line['move'] ]] - - - [[ strip_name(line['lname'],28) ]] - - - [[ strip_name(line['line_corresp'],23) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
-
-
-
-
diff --git a/addons/account/report/account_journal.py b/addons/account/report/account_journal.py index 97e19be4b0c..13dfd538f4a 100644 --- a/addons/account/report/account_journal.py +++ b/addons/account/report/account_journal.py @@ -20,8 +20,10 @@ ############################################################################## import time -from common_report_header import common_report_header +from openerp.osv import osv from openerp.report import report_sxw +from common_report_header import common_report_header + class journal_print(report_sxw.rml_parse, common_report_header): @@ -196,7 +198,18 @@ class journal_print(report_sxw.rml_parse, common_report_header): return self._translate('Reference Number') return self._translate('Date') -report_sxw.report_sxw('report.account.journal.period.print', 'account.journal.period', 'addons/account/report/account_journal.rml', parser=journal_print, header='external') -report_sxw.report_sxw('report.account.journal.period.print.sale.purchase', 'account.journal.period', 'addons/account/report/account_journal_sale_purchase.rml', parser=journal_print, header='external') + +class report_journal(osv.AbstractModel): + _name = 'report.account.report_journal' + _inherit = 'report.abstract_report' + _template = 'account.report_journal' + _wrapped_report_class = journal_print + + +class report_salepurchasejournal(osv.AbstractModel): + _name = 'report.account.report_salepurchasejournal' + _inherit = 'report.abstract_report' + _template = 'account.report_salepurchasejournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_journal.rml b/addons/account/report/account_journal.rml deleted file mode 100644 index 6d606ed1937..00000000000 --- a/addons/account/report/account_journal.rml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - Journal - - - - - - - - Company[[ data['model']=='account.journal.period'and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - Fiscal Year - Journal - Period - Entries Sorted By - Target Moves - - - [[ get_account(data) or '' ]] - [[ get_fiscalyear(data) or '' ]] - [[ o.journal_id.name ]] - [[ o.period_id.name ]] - - Date[[ data['form'].get('sort_selection', 'date') == 'date' and ' ' or removeParentNode('para') ]] - Reference Number[[ data['form'].get('sort_selection', 'date') == 'ref' and ' ' or removeParentNode('para') ]] - - - - - - - - - - [[ set_last_move_id(False)]] -
- [[ display_currency(data) == False or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Debit - Credit - - -
- [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,23) ]] - [[ strip_name(line.name,35) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
- - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - -
- -
- [[ display_currency(data) or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Debit - Credit - Currency - - -
- [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,17) ]] - [[ strip_name(line.name,28) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - [[ line.currency_id and formatLang(line.amount_currency, currency_obj=line.currency_id) or '' ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
- - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - - - -
-
-
diff --git a/addons/account/report/account_journal_sale_purchase.rml b/addons/account/report/account_journal_sale_purchase.rml deleted file mode 100644 index 3ee0b484c9a..00000000000 --- a/addons/account/report/account_journal_sale_purchase.rml +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - Journal - - - - - - - - [[ data['model']=='account.journal.period'and 'Company' or removeParentNode('para') ]] - [[ data['model']=='ir.ui.menu' and 'Chart of Accounts' or removeParentNode('para') ]] - Fiscal Year - Journal - Period - Entries Sorted By - Target Moves - - - [[ get_account(data) or '' ]] - [[ get_fiscalyear(data) or '' ]] - [[ o.journal_id.name ]] - [[ o.period_id.name ]] - [[ get_sortby(data) ]] - [[ get_target_move(data) ]] - - - - - - - - - [[ set_last_move_id(False) ]] -
- [[ display_currency(data) == False or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Tax - - Debit - Credit - - -
- [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,15) ]] - [[ strip_name(line.name,25) ]] - [[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]] - [[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
- - - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - -
- -
- [[ display_currency(data) or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Tax - - Debit - Credit - Currency - - -
- [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,12) ]] - [[ strip_name(line.name,16) ]] - [[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]] - [[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - [[ line.currency_id and formatLang(line.amount_currency, currency_obj=line.currency_id) or '' ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
- - - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - - - -
- - - - - - - -
- - - - - - Tax Declaration - - - - - [[ repeatIn(tax_codes(o.period_id.id,o.journal_id.id), 't') ]][[ t.code + ': ' ]] - [[ formatLang(sum_vat( o.period_id.id, o.journal_id.id, t.id)) ]] - - [[ t.name ]] - - -
-
-
diff --git a/addons/account/report/account_partner_balance.py b/addons/account/report/account_partner_balance.py index 53edbbe9685..ecd287551e5 100644 --- a/addons/account/report/account_partner_balance.py +++ b/addons/account/report/account_partner_balance.py @@ -20,11 +20,12 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.tools.translate import _ from openerp.report import report_sxw from common_report_header import common_report_header + class partner_balance(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context=None): @@ -301,6 +302,11 @@ class partner_balance(report_sxw.rml_parse, common_report_header): return _('Receivable and Payable Accounts') return '' -report_sxw.report_sxw('report.account.partner.balance', 'res.partner', 'account/report/account_partner_balance.rml',parser=partner_balance, header="internal") + +class report_partnerbalance(osv.AbstractModel): + _name = 'report.account.report_partnerbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerbalance' + _wrapped_report_class = partner_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_partner_balance.rml b/addons/account/report/account_partner_balance.rml deleted file mode 100644 index a99a7f062ec..00000000000 --- a/addons/account/report/account_partner_balance.rml +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Partner Balance - - - - - - - - - Chart of Accounts - Fiscal Year - Journals - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Partner's - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_partners() ]] - [[ get_target_move(data) ]] - - - - - - - - - - Code - (Account/Partner) Name - Debit - Credit - Balance - In dispute - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang(sum_credit()) ]] - [[ formatLang((sum_debit()-sum_credit()), currency_obj=company.currency_id) ]] - [[ formatLang(sum_litige(), currency_obj=company.currency_id) ]] - - - [[ repeatIn(lines(), 'a') ]][[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['ref'] ]] [[ a['type']==3 and a['code'] ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['name'] ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['debit']) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['credit']) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['balance'], currency_obj=company.currency_id) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['enlitige'] or 0.0, currency_obj=company.currency_id) ]] - - - - diff --git a/addons/account/report/account_partner_ledger.py b/addons/account/report/account_partner_ledger.py index d21323e02fc..f02ac96b6fc 100644 --- a/addons/account/report/account_partner_ledger.py +++ b/addons/account/report/account_partner_ledger.py @@ -20,10 +20,11 @@ ############################################################################## import time -import re +from openerp.osv import osv +from openerp.tools.translate import _ from openerp.report import report_sxw from common_report_header import common_report_header -from openerp.tools.translate import _ + class third_party_ledger(report_sxw.rml_parse, common_report_header): @@ -297,12 +298,18 @@ class third_party_ledger(report_sxw.rml_parse, common_report_header): return True return False -report_sxw.report_sxw('report.account.third_party_ledger', 'res.partner', - 'addons/account/report/account_partner_ledger.rml',parser=third_party_ledger, - header='internal') -report_sxw.report_sxw('report.account.third_party_ledger_other', 'res.partner', - 'addons/account/report/account_partner_ledger_other.rml',parser=third_party_ledger, - header='internal') +class report_partnerledger(osv.AbstractModel): + _name = 'report.account.report_partnerledger' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerledger' + _wrapped_report_class = third_party_ledger + + +class report_partnerledgerother(osv.AbstractModel): + _name = 'report.account.report_partnerledgerother' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerledgerother' + _wrapped_report_class = third_party_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_partner_ledger.rml b/addons/account/report/account_partner_ledger.rml deleted file mode 100644 index 48ed6d4afe3..00000000000 --- a/addons/account/report/account_partner_ledger.rml +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - - - Partner Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filters By [[ data['form']['filter'] not in ('filter_no','unreconciled') and get_filter(data) ]] - - - Partner's - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter'] in ('filter_no','unreconciled') and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - Receivable Accounts[[ data['form'].get('result_selection', 'customer') == 'customer' or removeParentNode('para') ]] - Payable Accounts[[ data['form'].get('result_selection', 'customer') == 'supplier' or removeParentNode('para') ]] - Receivable and Payable Accounts[[ data['form'].get('result_selection', 'customer') == 'customer_supplier' or removeParentNode('para') ]] - - - [[ get_target_move(data) ]] - - - - - - -
- - [[ display_currency(data) == False or removeParentNode('section') ]] - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - -
- - [[data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - -
-
- [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - -
-
-
- - [[ display_currency(data) == True or removeParentNode('section') ]] - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - - - - - - -
- [[ data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - - - - - - -
-
- [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ strip_name(line['ref'],8) ]] - [[ strip_name(line['name'],7) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - - - -
-
-
-
-
diff --git a/addons/account/report/account_partner_ledger_other.rml b/addons/account/report/account_partner_ledger_other.rml deleted file mode 100644 index b878ab44e47..00000000000 --- a/addons/account/report/account_partner_ledger_other.rml +++ /dev/null @@ -1,665 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - [[ display_currency(data) == True or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - - - - - Partner Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filters By [[ data['form']['filter'] not in ('filter_no','unreconciled') and get_filter(data) ]] - - - Partner's - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter'] in ('filter_no','unreconciled') and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - [[ get_partners() ]] - - - [[ get_target_move(data) ]] - - - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - -
- [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - [[ display_currency(data) == False or removeParentNode('section') ]] - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - -
- - [[data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - -
-
- [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - -
-
- - [[ display_currency(data) == True or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - -
- [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - [[ display_currency(data) == True or removeParentNode('section') ]] - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - - - - - - -
- [[ data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - - - - - - -
-
- [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ strip_name(line['ref'],8) ]] - [[ strip_name(line['name'],7) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - - - -
-
-
-
-
diff --git a/addons/account/report/account_print_invoice.rml b/addons/account/report/account_print_invoice.rml deleted file mode 100644 index 6914adfaf20..00000000000 --- a/addons/account/report/account_print_invoice.rml +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.partner_id.lang) ]] - - - - Description - Taxes - Quantity - Unit Price - Disc.(%) - Price - - - - - - - - - - - - [[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]] - [[ display_address(o.partner_id) ]] - - - - Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]] - Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]] - TIN : [[ (o.partner_id.vat) or removeParentNode('para') ]] - - - - Invoice [[ ((o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')) or removeParentNode('para')) and '' ]] [[ o.number ]] - PRO-FORMA [[ ((o.type == 'out_invoice' and o.state == 'proforma2') or removeParentNode('para')) and '' ]] - Draft Invoice [[ ((o.type == 'out_invoice' and o.state == 'draft') or removeParentNode('para')) and '' ]] - Cancelled Invoice [[ ((o.type == 'out_invoice' and o.state == 'cancel') or removeParentNode('para')) and '' ]] [[ o.number ]] - Refund [[ (o.type=='out_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Refund [[ (o.type=='in_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Invoice [[ (o.type=='in_invoice' or removeParentNode('para')) and '' ]] [[ o.number ]] - - - - - - - Description - - - Invoice Date - - - Source - - - Customer Code - - - - - - - [[ o.name or ' ' ]] - - - [[ formatLang(o.date_invoice,date=True) ]] - - - [[ o.origin or '' ]] - - - [[ (o.partner_id.ref) or ' ' ]] - - - - - - - - - - Description - - - Taxes - - - Quantity - - - Unit Price - - - Disc.(%) - - - Price - - - -
- [[ repeatIn(o.invoice_line,'l') ]] - - - - [[ format(l.name) ]] - - - [[ ', '.join([ lt.name or '' for lt in l.invoice_line_tax_id ]) ]] - - - [[ formatLang(l.quantity)]] [[ (l.uos_id and l.uos_id.name) or '' ]] - - - [[ formatLang(l.price_unit) ]] - - - [[ formatLang(l.discount, dp='Account') ]] - - - [[ formatLang(l.price_subtotal, dp='Account', currency_obj=o.currency_id) ]] - - - -
- - - - - - - - - Net Total: - - - [[ formatLang(o.amount_untaxed, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - - - Taxes: - - - [[ formatLang(o.amount_tax, dp='Account', currency_obj=o.currency_id) ]] - - - - - - - - - - Total: - - - [[ formatLang(o.amount_total, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - - - Tax [[ o.tax_line==[] and removeParentNode('blockTable') ]] - - - Base - - - Amount - - - - - - - - -
- [[ repeatIn(o.tax_line,'t') ]] - - - - [[ t.name ]] - - - [[ formatLang(t.base, dp='Account', currency_obj=o.currency_id) ]] - - - [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - -
- - - - [[ (o.comment and format(o.comment )) or removeParentNode('para') ]] - - - - [[ (o.payment_term and o.payment_term.note and format(o.payment_term and o.payment_term.note)) or removeParentNode('para') ]] - - - - - - - Fiscal Position Remark : - - - [[ (o.fiscal_position and o.fiscal_position.note and format(o.fiscal_position.note)) or removeParentNode('blockTable') ]] - - - - - - -
-
-
diff --git a/addons/account/report/account_print_overdue.py b/addons/account/report/account_print_overdue.py index e135f41309d..26192d39949 100644 --- a/addons/account/report/account_print_overdue.py +++ b/addons/account/report/account_print_overdue.py @@ -22,15 +22,36 @@ import time from openerp.report import report_sxw +from openerp.osv import osv + class Overdue(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(Overdue, self).__init__(cr, uid, name, context=context) - self.localcontext.update( { + ids = context.get('active_ids') + partner_obj = self.pool['res.partner'] + docs = partner_obj.browse(cr, uid, ids, context) + + due = {} + paid = {} + mat = {} + + for partner in docs: + due[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), self._lines_get(partner), 0) + paid[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), self._lines_get(partner), 0) + mat[partner.id] = reduce(lambda x, y: x + (y['debit'] - y['credit']), filter(lambda x: x['date_maturity'] < time.strftime('%Y-%m-%d'), self._lines_get(partner)), 0) + + addresses = self.pool['res.partner']._address_display(cr, uid, ids, None, None) + self.localcontext.update({ + 'docs': docs, 'time': time, 'getLines': self._lines_get, 'tel_get': self._tel_get, 'message': self._message, + 'due': due, + 'paid': paid, + 'mat': mat, + 'addresses': addresses }) self.context = context @@ -41,7 +62,7 @@ class Overdue(report_sxw.rml_parse): addresses = res_partner.address_get(self.cr, self.uid, [partner.id], ['invoice']) adr_id = addresses and addresses['invoice'] or False if adr_id: - adr=res_partner_address.read(self.cr, self.uid, [adr_id])[0] + adr=res_partner.read(self.cr, self.uid, [adr_id])[0] return adr['phone'] else: return partner.phone or False @@ -62,5 +83,10 @@ class Overdue(report_sxw.rml_parse): return message.split('\n') -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +class report_overdue(osv.AbstractModel): + _name = 'report.account.report_overdue' + _inherit = 'report.abstract_report' + _template = 'account.report_overdue' + _wrapped_report_class = Overdue +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_print_overdue.rml b/addons/account/report/account_print_overdue.rml deleted file mode 100644 index 9d1898572ba..00000000000 --- a/addons/account/report/account_print_overdue.rml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date - - - Description - - - Ref - - - Maturity date - - - Due - - - Paid - - - Maturity - - - Li. - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.lang) ]] - - - - - - [[ o.title.name or '' ]] [[ o.name ]] - [[ display_address(o) ]] - - - - VAT: [[ o.vat or removeParentNode('para') ]] - - - - - - - - - - Document: Customer account statement - Date: [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] - Customer Ref: [[ o.ref or ' ']] - - - - - - -
- [[ not getLines(o) and removeParentNode('section')]] -
- [[repeatIn(message(o, company), 'message_line') ]] - [[ message_line ]] - - - -
- - - - Date - - - Description - - - Ref - - - Maturity date - - - Due - - - Paid - - - Maturity - - - Li. - - - -
[[repeatIn(getLines(o), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['name'] ]] - - - [[ line['ref'] ]] - - - [[ line['date_maturity'] and formatLang(line['date_maturity'],date=True) or '' ]] - - - [[ (line['account_id']['type'] == 'receivable' and formatLang(line['debit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['credit'] * -1) or ' ') ]] - - - [[ (line['account_id']['type'] == 'receivable' and formatLang(line['credit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['debit'] * -1) or 0) ]] - - - [[ (time.strftime('%Y-%m-%d') > line['date_maturity']) and formatLang(line['debit'] - line['credit'], currency_obj = company.currency_id) ]] - - - [[ line['blocked'] and 'X' or '' ]] - - - -
- - - - - - - - - Sub-Total : - - - [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), getLines(o), 0))) ]] - - - [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), getLines(o), 0))) ]] - - - [[ formatLang((reduce(lambda x, y: x + (y['debit'] - y['credit']), filter(lambda x: x['date_maturity'] < time.strftime('%Y-%m-%d'), getLines(o)), 0)), currency_obj=company.currency_id) ]] - - - - - - - - - - - - - - - - - Balance : - - - [[ formatLang((reduce(lambda x, y: x +(y['debit'] - y['credit']), getLines(o), 0)), currency_obj = company.currency_id) ]] - - - - - - - - - - - - - - - Total amount due: [[ formatLang((reduce(lambda x, y: x + (y['debit'] - y['credit']), getLines(o), 0)), currency_obj=company.currency_id) ]] -
- - - -
- [[ getLines(o) and removeParentNode('section')]]There is nothing due with this customer. -
- - - - - - -
-
-
diff --git a/addons/account/report/report_vat.py b/addons/account/report/report_vat.py index 3a0950ac62f..be2b6244f7d 100644 --- a/addons/account/report/report_vat.py +++ b/addons/account/report/report_vat.py @@ -19,24 +19,16 @@ # ############################################################################## +import time from openerp.osv import osv -from openerp.addons.web import http -from openerp.addons.web.http import request +from openerp.report import report_sxw from common_report_header import common_report_header -try: - import cStringIO as StringIO -except ImportError: - import StringIO -import xlwt -class tax_report(osv.AbstractModel, common_report_header): - _name = 'report.account.report_vat' - - def render_html(self, cr, uid, ids, data=None, context=None): - report_obj = request.registry['report'] - self.cr, self.uid, self.context = cr, uid, context +class tax_report(report_sxw.rml_parse, common_report_header): + def set_context(self, objects, data, ids, report_type=None): + new_ids = ids res = {} self.period_ids = [] period_obj = self.pool.get('account.period') @@ -46,30 +38,42 @@ class tax_report(osv.AbstractModel, common_report_header): if data['form'].get('period_from', False) and data['form'].get('period_to', False): self.period_ids = period_obj.build_ctx_periods(self.cr, self.uid, data['form']['period_from'], data['form']['period_to']) + periods_l = period_obj.read(self.cr, self.uid, self.period_ids, ['name']) + for period in periods_l: + if res['periods'] == '': + res['periods'] = period['name'] + else: + res['periods'] += ", "+ period['name'] + return super(tax_report, self).set_context(objects, data, new_ids, report_type=report_type) - docargs = { - 'fiscalyear': self._get_fiscalyear(data), - 'account': self._get_account(data), - 'based_on': self._get_basedon(data), - 'period_from': self.get_start_period(data), - 'period_to': self.get_end_period(data), - 'taxlines': self._get_lines(self._get_basedon(data), company_id=data['form']['company_id'], cr=cr, uid=uid), - } - return report_obj.render(self.cr, self.uid, [], 'account.report_vat', docargs, context=context) + def __init__(self, cr, uid, name, context=None): + super(tax_report, self).__init__(cr, uid, name, context=context) + self.localcontext.update({ + 'time': time, + 'get_codes': self._get_codes, + 'get_general': self._get_general, + 'get_currency': self._get_currency, + 'get_lines': self._get_lines, + 'get_fiscalyear': self._get_fiscalyear, + 'get_account': self._get_account, + 'get_start_period': self.get_start_period, + 'get_end_period': self.get_end_period, + 'get_basedon': self._get_basedon, + }) def _get_basedon(self, form): return form['form']['based_on'] - def _get_lines(self, based_on, company_id=False, parent=False, level=0, context=None, cr=None, uid=None): + def _get_lines(self, based_on, company_id=False, parent=False, level=0, context=None): period_list = self.period_ids - res = self._get_codes(based_on, company_id, parent, level, period_list, cr=cr, uid=uid, context=context) + res = self._get_codes(based_on, company_id, parent, level, period_list, context=context) if period_list: res = self._add_codes(based_on, res, period_list, context=context) else: - cr.execute ("select id from account_fiscalyear") - fy = cr.fetchall() - cr.execute ("select id from account_period where fiscalyear_id = %s",(fy[0][0],)) - periods = cr.fetchall() + self.cr.execute ("select id from account_fiscalyear") + fy = self.cr.fetchall() + self.cr.execute ("select id from account_period where fiscalyear_id = %s",(fy[0][0],)) + periods = self.cr.fetchall() for p in periods: period_list.append(p[0]) res = self._add_codes(based_on, res, period_list, context=context) @@ -89,7 +93,7 @@ class tax_report(osv.AbstractModel, common_report_header): } top_result.append(res_dict) - res_general = self._get_general(res[i][1].id, period_list, company_id, based_on, cr=cr, uid=uid, context=context) + res_general = self._get_general(res[i][1].id, period_list, company_id, based_on, context=context) ind_general = 0 while ind_general < len(res_general): res_general[ind_general]['type'] = 2 @@ -100,14 +104,14 @@ class tax_report(osv.AbstractModel, common_report_header): i+=1 return top_result - def _get_general(self, tax_code_id, period_list, company_id, based_on, cr=None, uid=None, context=None): + def _get_general(self, tax_code_id, period_list, company_id, based_on, context=None): if not self.display_detail: return [] res = [] obj_account = self.pool.get('account.account') periods_ids = tuple(period_list) if based_on == 'payments': - cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ + self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ SUM(line.debit) AS debit, \ SUM(line.credit) AS credit, \ COUNT(*) AS count, \ @@ -131,7 +135,7 @@ class tax_report(osv.AbstractModel, common_report_header): company_id, periods_ids, 'paid',)) else: - cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ + self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ SUM(line.debit) AS debit, \ SUM(line.credit) AS credit, \ COUNT(*) AS count, \ @@ -148,21 +152,23 @@ class tax_report(osv.AbstractModel, common_report_header): AND account.active \ GROUP BY account.id,account.name,account.code', ('draft', tax_code_id, company_id, periods_ids,)) - res = cr.dictfetchall() + res = self.cr.dictfetchall() i = 0 while i= int(accounts[bcl_rup_ind]['level']) and bcl_rup_ind >= 0 ): - res_tot = { - 'code': accounts[bcl_rup_ind]['code'], + res_tot = { 'code': accounts[bcl_rup_ind]['code'], 'name': '', 'debit': 0, 'credit': 0, @@ -225,40 +234,10 @@ class tax_report(osv.AbstractModel, common_report_header): return result_accounts -class tax_report_xls(http.Controller): - - @http.route(['/report/account.report_vat_xls'], type='http', auth='user', website=True, multilang=True) - def report_account_tax_xls(self, **data): - - # Very ugly lines, only for the proof of concept of 'controller' report - taxreport_obj = request.registry['report.account.report_vat'] - from openerp.addons.report.controllers.main import ReportController - eval_params = ReportController()._eval_params - - cr, uid = request.cr, request.uid - data = eval_params(data) - data = {'form': data} - - taxreport_obj.render_html(cr, uid, [], data=data) - lines = taxreport_obj._get_lines(taxreport_obj._get_basedon(data), company_id=data['form']['company_id'], cr=cr, uid=uid) - - if lines: - xls = StringIO.StringIO() - xls_workbook = xlwt.Workbook() - vat_sheet = xls_workbook.add_sheet('report_vat') - - for x in range(0, len(lines)): - for y in range(0, len(lines[0])): - vat_sheet.write(x, y, lines[x].values()[y]) - - xls_workbook.save(xls) - xls.seek(0) - content = xls.read() - - response = request.make_response(content, headers=[ - ('Content-Type', 'application/vnd.ms-excel'), - ('Content-Disposition', 'attachment; filename=report_vat.xls;') - ]) - return response +class report_vat(osv.AbstractModel): + _name = 'report.account.report_vat' + _inherit = 'report.abstract_report' + _template = 'account.report_vat' + _wrapped_report_class = tax_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/test/account_report.yml b/addons/account/test/account_report.yml index 7a2d09486e4..9173c37b61e 100644 --- a/addons/account/test/account_report.yml +++ b/addons/account/test/account_report.yml @@ -16,10 +16,9 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('account.account_invoice_customer0')], 'account.invoice', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('account.account_invoice_customer0')], 'account.report_invoice', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-invoice.'+format), 'wb+').write(data) - - In order to test the PDF reports defined on a partner, we will print the Overdue Report - @@ -27,7 +26,7 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], 'account.overdue', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], 'account.report_overdue', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-report_overdue.'+format), 'wb+').write(data) - @@ -86,8 +85,8 @@ Print the General Ledger Report in Landscape Mode - !python {model: account.account}: | - ctx={} - data_dict = {'chart_account_id':ref('account.chart0'),'landscape':True} + ctx={'landscape': True} + data_dict = {'chart_account_id':ref('account.chart0')} from openerp.tools import test_reports test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu',wiz_data=data_dict, context=ctx, our_module='account') - diff --git a/addons/account/views/report_agedpartnerbalance.xml b/addons/account/views/report_agedpartnerbalance.xml new file mode 100644 index 00000000000..019f32a35de --- /dev/null +++ b/addons/account/views/report_agedpartnerbalance.xml @@ -0,0 +1,133 @@ + + + + + + diff --git a/addons/account/views/report_centraljournal.xml b/addons/account/views/report_centraljournal.xml new file mode 100644 index 00000000000..e939fa98fc3 --- /dev/null +++ b/addons/account/views/report_centraljournal.xml @@ -0,0 +1,93 @@ + + + + + + diff --git a/addons/account/views/report_financial.xml b/addons/account/views/report_financial.xml new file mode 100644 index 00000000000..69802331a5b --- /dev/null +++ b/addons/account/views/report_financial.xml @@ -0,0 +1,128 @@ + + + + + + diff --git a/addons/account/views/report_generaljournal.xml b/addons/account/views/report_generaljournal.xml new file mode 100644 index 00000000000..062c9ec2554 --- /dev/null +++ b/addons/account/views/report_generaljournal.xml @@ -0,0 +1,98 @@ + + + + + + diff --git a/addons/account/views/report_generalledger.xml b/addons/account/views/report_generalledger.xml new file mode 100644 index 00000000000..d873571dee3 --- /dev/null +++ b/addons/account/views/report_generalledger.xml @@ -0,0 +1,133 @@ + + + + + + + diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml new file mode 100644 index 00000000000..6757095a7d4 --- /dev/null +++ b/addons/account/views/report_invoice.xml @@ -0,0 +1,153 @@ + + + + + + + + diff --git a/addons/account/views/report_journal.xml b/addons/account/views/report_journal.xml new file mode 100644 index 00000000000..0771b5f5fe9 --- /dev/null +++ b/addons/account/views/report_journal.xml @@ -0,0 +1,88 @@ + + + + + + diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml new file mode 100644 index 00000000000..bc522aa8b9d --- /dev/null +++ b/addons/account/views/report_overdue.xml @@ -0,0 +1,118 @@ + + + + + + + + diff --git a/addons/account/views/report_partnerbalance.xml b/addons/account/views/report_partnerbalance.xml new file mode 100644 index 00000000000..11948905fe9 --- /dev/null +++ b/addons/account/views/report_partnerbalance.xml @@ -0,0 +1,125 @@ + + + + + + diff --git a/addons/account/views/report_partnerledger.xml b/addons/account/views/report_partnerledger.xml new file mode 100644 index 00000000000..333fab7aa5c --- /dev/null +++ b/addons/account/views/report_partnerledger.xml @@ -0,0 +1,131 @@ + + + + + + diff --git a/addons/account/views/report_partnerledgerother.xml b/addons/account/views/report_partnerledgerother.xml new file mode 100644 index 00000000000..b8f3d525f51 --- /dev/null +++ b/addons/account/views/report_partnerledgerother.xml @@ -0,0 +1,131 @@ + + + + + + diff --git a/addons/account/views/report_salepurchasejournal.xml b/addons/account/views/report_salepurchasejournal.xml new file mode 100644 index 00000000000..f1d8724f285 --- /dev/null +++ b/addons/account/views/report_salepurchasejournal.xml @@ -0,0 +1,107 @@ + + + + + + diff --git a/addons/account/views/report_trialbalance.xml b/addons/account/views/report_trialbalance.xml new file mode 100644 index 00000000000..6a27b957971 --- /dev/null +++ b/addons/account/views/report_trialbalance.xml @@ -0,0 +1,94 @@ + + + + + + diff --git a/addons/account/views/report_vat.xml b/addons/account/views/report_vat.xml index 03664045ef4..f88d45e5c44 100644 --- a/addons/account/views/report_vat.xml +++ b/addons/account/views/report_vat.xml @@ -39,7 +39,7 @@ - + diff --git a/addons/account/wizard/account_financial_report.py b/addons/account/wizard/account_financial_report.py index 48bdfd33081..6c1b57fa428 100644 --- a/addons/account/wizard/account_financial_report.py +++ b/addons/account/wizard/account_financial_report.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class accounting_report(osv.osv_memory): _name = "accounting.report" _inherit = "account.common.report" @@ -83,16 +84,11 @@ class accounting_report(osv.osv_memory): if isinstance(data['form'][field], tuple): data['form'][field] = data['form'][field][0] comparison_context = self._build_comparison_context(cr, uid, ids, data, context=context) - res['datas']['form']['comparison_context'] = comparison_context + res['data']['form']['comparison_context'] = comparison_context return res def _print_report(self, cr, uid, ids, data, context=None): data['form'].update(self.read(cr, uid, ids, ['date_from_cmp', 'debit_credit', 'date_to_cmp', 'fiscalyear_id_cmp', 'period_from_cmp', 'period_to_cmp', 'filter_cmp', 'account_report_id', 'enable_filter', 'label_filter','target_move'], context=context)[0]) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.financial.report', - 'datas': data, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_financial', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_account_balance.py b/addons/account/wizard/account_report_account_balance.py index fd3c966e306..3b9d3c21777 100644 --- a/addons/account/wizard/account_report_account_balance.py +++ b/addons/account/wizard/account_report_account_balance.py @@ -36,7 +36,6 @@ class account_balance_report(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return {'type': 'ir.actions.report.xml', 'report_name': 'account.account.balance', 'datas': data} - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_trialbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_aged_partner_balance.py b/addons/account/wizard/account_report_aged_partner_balance.py index c483487b78f..c918a1119fd 100644 --- a/addons/account/wizard/account_report_aged_partner_balance.py +++ b/addons/account/wizard/account_report_aged_partner_balance.py @@ -25,6 +25,7 @@ from dateutil.relativedelta import relativedelta from openerp.osv import fields, osv from openerp.tools.translate import _ + class account_aged_trial_balance(osv.osv_memory): _inherit = 'account.common.partner.report' _name = 'account.aged.trial.balance' @@ -80,11 +81,6 @@ class account_aged_trial_balance(osv.osv_memory): data['form'].update(res) if data.get('form',False): data['ids']=[data['form'].get('chart_account_id',False)] - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.aged_trial_balance', - 'datas': data - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_agedpartnerbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_central_journal.py b/addons/account/wizard/account_report_central_journal.py index a6bc111fa35..9f22d49afac 100644 --- a/addons/account/wizard/account_report_central_journal.py +++ b/addons/account/wizard/account_report_central_journal.py @@ -32,13 +32,6 @@ class account_central_journal(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.central.journal', - 'datas': data, - } - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_centraljournal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_journal.py b/addons/account/wizard/account_report_general_journal.py index e5e516b1f38..3d9d55b19c1 100644 --- a/addons/account/wizard/account_report_general_journal.py +++ b/addons/account/wizard/account_report_general_journal.py @@ -32,9 +32,6 @@ class account_general_journal(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return {'type': 'ir.actions.report.xml', 'report_name': 'account.general.journal', 'datas': data} - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_generaljournal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_ledger.py b/addons/account/wizard/account_report_general_ledger.py index fae60df63fb..c75477da40a 100644 --- a/addons/account/wizard/account_report_general_ledger.py +++ b/addons/account/wizard/account_report_general_ledger.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_report_general_ledger(osv.osv_memory): _inherit = "account.common.account.report" _name = "account.report.general.ledger" @@ -54,9 +55,10 @@ class account_report_general_ledger(osv.osv_memory): data['form'].update(self.read(cr, uid, ids, ['landscape', 'initial_balance', 'amount_currency', 'sortby'])[0]) if not data['form']['fiscalyear_id']:# GTK client problem onchange does not consider in save record data['form'].update({'initial_balance': False}) - if data['form']['landscape']: - return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger_landscape', 'datas': data} - return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger', 'datas': data} + if data['form']['landscape'] is False: + data['form'].pop('landscape') + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_generalledger', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_balance.py b/addons/account/wizard/account_report_partner_balance.py index fbe18f27d69..d4b5fb27d14 100644 --- a/addons/account/wizard/account_report_partner_balance.py +++ b/addons/account/wizard/account_report_partner_balance.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_partner_balance(osv.osv_memory): """ This wizard will provide the partner balance report by periods, between any two dates. @@ -35,7 +36,6 @@ class account_partner_balance(osv.osv_memory): } _defaults = { -# 'initial_balance': True, 'display_partner': 'non-zero_balance', } @@ -44,11 +44,6 @@ class account_partner_balance(osv.osv_memory): context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['display_partner'])[0]) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.partner.balance', - 'datas': data, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_ledger.py b/addons/account/wizard/account_report_partner_ledger.py index fdabe49ff17..eb743e32e4f 100644 --- a/addons/account/wizard/account_report_partner_ledger.py +++ b/addons/account/wizard/account_report_partner_ledger.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_partner_ledger(osv.osv_memory): """ This wizard will provide the partner Ledger report by periods, between any two dates. @@ -37,6 +38,7 @@ class account_partner_ledger(osv.osv_memory): 'amount_currency': fields.boolean("With Currency", help="It adds the currency column on report if the currency differs from the company currency."), 'journal_ids': fields.many2many('account.journal', 'account_partner_ledger_journal_rel', 'account_id', 'journal_id', 'Journals', required=True), } + _defaults = { 'initial_balance': False, 'page_split': False, @@ -45,8 +47,8 @@ class account_partner_ledger(osv.osv_memory): def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): res = super(account_partner_ledger, self).onchange_filter(cr, uid, ids, filter=filter, fiscalyear_id=fiscalyear_id, context=context) if filter in ['filter_no', 'unreconciled']: - if filter == 'unreconciled': - res['value'].update({'fiscalyear_id': False}) + if filter == 'unreconciled': + res['value'].update({'fiscalyear_id': False}) res['value'].update({'initial_balance': False, 'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False}) return res @@ -55,17 +57,8 @@ class account_partner_ledger(osv.osv_memory): context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['initial_balance', 'filter', 'page_split', 'amount_currency'])[0]) - if data['form']['page_split']: - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.third_party_ledger', - 'datas': data, - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.third_party_ledger_other', - 'datas': data, - } - + if data['form'].get('page_split') is True: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerledgerother', data=data, context=context) + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerledger', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_print_journal.py b/addons/account/wizard/account_report_print_journal.py index 3ad45268248..3aafc63acf4 100644 --- a/addons/account/wizard/account_report_print_journal.py +++ b/addons/account/wizard/account_report_print_journal.py @@ -22,6 +22,7 @@ from openerp.osv import fields, osv from lxml import etree + class account_print_journal(osv.osv_memory): _inherit = "account.common.journal.report" _name = 'account.print.journal' @@ -60,19 +61,14 @@ class account_print_journal(osv.osv_memory): res['arch'] = etree.tostring(doc) return res - def _print_report(self, cr, uid, ids, data, context=None): if context is None: context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['sort_selection'], context=context)[0]) if context.get('sale_purchase_only'): - report_name = 'account.journal.period.print.sale.purchase' + return self.pool['report'].get_action(cr, uid, ids, 'account.report_salepurchasejournal', data=data, context=context) else: - report_name = 'account.journal.period.print' - return {'type': 'ir.actions.report.xml', 'report_name': report_name, 'datas': data} - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_journal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_validate_account_move.py b/addons/account/wizard/account_validate_account_move.py index 297f3445606..7a7a74be04b 100644 --- a/addons/account/wizard/account_validate_account_move.py +++ b/addons/account/wizard/account_validate_account_move.py @@ -34,7 +34,7 @@ class validate_account_move(osv.osv_memory): if context is None: context = {} data = self.read(cr, uid, ids[0], context=context) - ids_move = obj_move.search(cr, uid, [('state','=','draft'),('journal_id','in',tuple(data['journal_ids'])),('period_id','in',tuple(data['period_ids']))]) + ids_move = obj_move.search(cr, uid, [('state','=','draft'),('journal_id','in',tuple(data['journal_ids'])),('period_id','in',tuple(data['period_ids']))], order='date') if not ids_move: raise osv.except_osv(_('Warning!'), _('Specified journals do not have any account move entries in draft state for the specified periods.')) obj_move.button_validate(cr, uid, ids_move, context=context) diff --git a/addons/account/wizard/account_vat.py b/addons/account/wizard/account_vat.py index 6fbfcc9ddf5..5cc5c678df1 100644 --- a/addons/account/wizard/account_vat.py +++ b/addons/account/wizard/account_vat.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_vat_declaration(osv.osv_memory): _name = 'account.vat.declaration' _description = 'Account Vat Declaration' @@ -60,6 +61,6 @@ class account_vat_declaration(osv.osv_memory): taxcode = taxcode_obj.browse(cr, uid, [taxcode_id], context=context)[0] datas['form']['company_id'] = taxcode.company_id.id - return self.pool['report'].get_action(cr, uid, ids, 'account.report_vat', datas=datas, context=context) + return self.pool['report'].get_action(cr, uid, ids, 'account.report_vat', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_plans/__openerp__.py b/addons/account_analytic_plans/__openerp__.py index af5b5654b99..7ca7c00e6c0 100644 --- a/addons/account_analytic_plans/__openerp__.py +++ b/addons/account_analytic_plans/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Multiple Analytic Plans', 'version': '1.0', @@ -74,6 +73,7 @@ The analytic plan validates the minimum and maximum percentage at the time of cr 'account_analytic_plans_report.xml', 'wizard/analytic_plan_create_model_view.xml', 'wizard/account_crossovered_analytic_view.xml', + 'views/report_crossoveredanalyticplans.xml', ], 'demo': [], 'test': ['test/acount_analytic_plans_report.yml'], diff --git a/addons/account_analytic_plans/account_analytic_plans_report.xml b/addons/account_analytic_plans/account_analytic_plans_report.xml index 05d4c5b445c..608a22d1d96 100644 --- a/addons/account_analytic_plans/account_analytic_plans_report.xml +++ b/addons/account_analytic_plans/account_analytic_plans_report.xml @@ -1,16 +1,15 @@ - - + report_type="qweb-pdf" + name="account_analytic_plans.report_crossoveredanalyticplans" + file="account_analytic_plans.report_crossoveredanalyticplans" + menu="False" + /> diff --git a/addons/account_analytic_plans/report/crossovered_analytic.py b/addons/account_analytic_plans/report/crossovered_analytic.py index b1a8f965d6b..ef7589fda8e 100644 --- a/addons/account_analytic_plans/report/crossovered_analytic.py +++ b/addons/account_analytic_plans/report/crossovered_analytic.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class crossovered_analytic(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(crossovered_analytic, self).__init__(cr, uid, name, context = context) @@ -173,7 +174,11 @@ class crossovered_analytic(report_sxw.rml_parse): final.append(item) return final -report_sxw.report_sxw('report.account.analytic.account.crossovered.analytic', 'account.analytic.account', 'addons/account_analytic_plans/report/crossovered_analytic.rml',parser = crossovered_analytic, header='internal') + +class report_crossoveredanalyticplans(osv.AbstractModel): + _name = 'report.account_analytic_plans.report_crossoveredanalyticplans' + _inherit = 'report.abstract_report' + _template = 'account_analytic_plans.report_crossoveredanalyticplans' + _wrapped_report_class = crossovered_analytic # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_analytic_plans/report/crossovered_analytic.rml b/addons/account_analytic_plans/report/crossovered_analytic.rml deleted file mode 100644 index 48e7c13b0a1..00000000000 --- a/addons/account_analytic_plans/report/crossovered_analytic.rml +++ /dev/null @@ -1,304 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Perc(%) - - - - - - - - Crossovered Analytic - - - - - - - From Date - - - To Date - - - Company - - - Currency - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date=True) ]] - - - [[ formatLang(data['form']['date2'],date=True) ]] - - - [[ company.name ]] - - - [[ company.currency_id.name ]] - - - [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] at [[ time.strftime('%H:%M:%S') ]] - - - - - - - Analytic Account Reference: - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Perc(%) - - - -
- [[ repeatIn(ref_lines(data['form']),'a') ]] - - - - [[ a['ref_name'] ]] - - - [[ a['ref_code'] ]] - - - [[ a['ref_qty'] and formatLang(a['ref_qty']) ]] - - - [[ a['ref_amt'] and formatLang(a['ref_amt'], currency_obj=company.currency_id) ]] - - - 100.00% - - - -
- - - - Analytic Account : - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Percentage - - - -
- [[ repeatIn(lines(data['form']),'a') ]] - - - - [[ a['acc_name'] ]] - - - [[ a['code'] ]] - - - [[formatLang(a['qty']) ]] - - - [[ formatLang(a['amt'], currency_obj=company.currency_id) ]] - - - [[ formatLang(a['perc']) ]]% - - - - - - -
-
-
-
diff --git a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml index 6aa67a3052a..cae58583793 100644 --- a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml +++ b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml @@ -6,6 +6,6 @@ import openerp.report from openerp import tools data_dict = {'model': 'account.analytic.account', 'form': {'date1':time.strftime("%Y-01-01"),'date2':time.strftime('%Y-%m-%d'),'journal_ids':[6,0,(ref('account.cose_journal_sale'))],'ref':ref('account.analytic_root'),'empty_line':True,'id':ref('account.analytic_root'),'context':{}}} - data, format = openerp.report.render_report(cr, uid, [ref('account.analytic_root')], 'account.analytic.account.crossovered.analytic', data_dict, {}) + data, format = openerp.report.render_report(cr, uid, [ref('account.analytic_root')], 'account_analytic_plans.report_crossoveredanalyticplans', data_dict, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_analytic_plans-crossovered_analyitic.'+format), 'wb+').write(data) diff --git a/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml new file mode 100644 index 00000000000..b4470ea2913 --- /dev/null +++ b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml @@ -0,0 +1,66 @@ + + + + + + diff --git a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py index d3581d6c457..ccac123c681 100644 --- a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py +++ b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py @@ -65,11 +65,6 @@ class account_crossovered_analytic(osv.osv_memory): 'model': 'account.analytic.account', 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.crossovered.analytic', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_analytic_plans.report_crossoveredanalyticplans', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/__openerp__.py b/addons/account_bank_statement_extensions/__openerp__.py index 7571eef3e54..203011c46c5 100644 --- a/addons/account_bank_statement_extensions/__openerp__.py +++ b/addons/account_bank_statement_extensions/__openerp__.py @@ -50,6 +50,7 @@ This module adds: 'wizard/confirm_statement_line_wizard.xml', 'wizard/cancel_statement_line_wizard.xml', 'data/account_bank_statement_extensions_data.xml', + 'views/report_bankstatementbalance.xml', ], 'auto_install': False, 'installable': True, diff --git a/addons/account_bank_statement_extensions/account_bank_statement_report.xml b/addons/account_bank_statement_extensions/account_bank_statement_report.xml index b4dafbfd9a7..861c3822520 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement_report.xml +++ b/addons/account_bank_statement_extensions/account_bank_statement_report.xml @@ -1,16 +1,13 @@ - - - - - + + + diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py index 59b8efb23e1..f0b63bf148c 100644 --- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py +++ b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py @@ -21,15 +21,14 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class bank_statement_balance_report(report_sxw.rml_parse): def set_context(self, objects, data, ids, report_type=None): cr = self.cr - uid = self.uid - context = self.context cr.execute('SELECT s.name as s_name, s.date AS s_date, j.code as j_code, s.balance_end_real as s_balance ' \ 'FROM account_bank_statement s ' \ @@ -46,7 +45,6 @@ class bank_statement_balance_report(report_sxw.rml_parse): }) super(bank_statement_balance_report, self).set_context(objects, data, ids, report_type=report_type) - def __init__(self, cr, uid, name, context): if context is None: context = {} @@ -56,12 +54,11 @@ class bank_statement_balance_report(report_sxw.rml_parse): }) self.context = context -report_sxw.report_sxw( - 'report.bank.statement.balance.report', - 'account.bank.statement', - 'addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml', - parser=bank_statement_balance_report, - header='internal' -) + +class report_bankstatementbalance(osv.AbstractModel): + _name = 'report.account_bank_statement_extensions.report_bankstatementbalance' + _inherit = 'report.abstract_report' + _template = 'account_bank_statement_extensions.report_bankstatementbalance' + _wrapped_report_class = bank_statement_balance_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml deleted file mode 100644 index 963b5d9dd68..00000000000 --- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ ]] - - - - - - - Bank Statement Balances Report - - - - - - - - - - - - - Name - - - Date - - - Journal - - - Closing Balance - - - - - - -
- [[ repeatIn(lines, 'l') ]] - - - - [[ l['s_name'] ]] - - - [[ l['s_date'] ]] - - - [[ l['j_code'] ]] - - - [[ formatLang(l['s_balance']) ]] - - - - - - -
- - - -
-
- diff --git a/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml b/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml new file mode 100644 index 00000000000..111912a7507 --- /dev/null +++ b/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml @@ -0,0 +1,35 @@ + + + + + + diff --git a/addons/account_budget/__openerp__.py b/addons/account_budget/__openerp__.py index 222178b940c..695fd794b9f 100644 --- a/addons/account_budget/__openerp__.py +++ b/addons/account_budget/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Budgets Management', 'version': '1.0', @@ -61,13 +60,18 @@ Three reports are available: 'wizard/account_budget_report_view.xml', 'wizard/account_budget_crossovered_summary_report_view.xml', 'wizard/account_budget_crossovered_report_view.xml', + + 'views/report_analyticaccountbudget.xml', + 'views/report_budget.xml', + 'views/report_crossoveredbudget.xml', ], 'demo': ['account_budget_demo.xml'], - 'test':[ + 'test': [ 'test/account_budget.yml', 'test/account_budget_report.yml', ], 'installable': True, 'auto_install': False, } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/account_budget_report.xml b/addons/account_budget/account_budget_report.xml index 9cc38154ef9..7855deb9ccc 100644 --- a/addons/account_budget/account_budget_report.xml +++ b/addons/account_budget/account_budget_report.xml @@ -1,24 +1,34 @@ - - - - - - - + /> + + + + - \ No newline at end of file + diff --git a/addons/account_budget/report/analytic_account_budget_report.py b/addons/account_budget/report/analytic_account_budget_report.py index 6701fc06a2b..4e3feaf06b7 100644 --- a/addons/account_budget/report/analytic_account_budget_report.py +++ b/addons/account_budget/report/analytic_account_budget_report.py @@ -20,10 +20,10 @@ ############################################################################## import time -import datetime - +from openerp.osv import osv from openerp.report import report_sxw + class analytic_account_budget_report(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(analytic_account_budget_report, self).__init__(cr, uid, name, context=context) @@ -166,6 +166,11 @@ class analytic_account_budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.account.analytic.account.budget', 'account.analytic.account', 'addons/account_budget/report/analytic_account_budget_report.rml',parser=analytic_account_budget_report,header='internal') + +class report_analyticaccountbudget(osv.AbstractModel): + _name = 'report.account_budget.report_analyticaccountbudget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_analyticaccountbudget' + _wrapped_report_class = analytic_account_budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/analytic_account_budget_report.rml b/addons/account_budget/report/analytic_account_budget_report.rml deleted file mode 100644 index 15fddebd02d..00000000000 --- a/addons/account_budget/report/analytic_account_budget_report.rml +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - - - [[repeatIn(objects,'o')]] - Analytic Budget - - - - - - - Analysis from - - - Analytic Account - - - Currency - - - - - - - [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - [[ o.name ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
- [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]] [[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc']) ]]% - - - -
- - - - [[ repeatIn(funct_total(data['form']),'b') ]] Total: - - - [[ formatLang(b['tot_theo'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc']) ]]% - - - - - - -
-
-
diff --git a/addons/account_budget/report/budget_report.py b/addons/account_budget/report/budget_report.py index f00eb8a3713..f8f812639b0 100644 --- a/addons/account_budget/report/budget_report.py +++ b/addons/account_budget/report/budget_report.py @@ -20,6 +20,7 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw tot = {} @@ -187,6 +188,11 @@ class budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.account.budget', 'account.budget.post', 'addons/account_budget/report/budget_report.rml', parser=budget_report, header='internal') + +class report_budget(osv.AbstractModel): + _name = 'report.account_budget.report_budget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_budget' + _wrapped_report_class = budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/budget_report.rml b/addons/account_budget/report/budget_report.rml deleted file mode 100644 index 789c3ed1ffb..00000000000 --- a/addons/account_budget/report/budget_report.rml +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - - - - Budget - - - - - - - Currency: [[ company.currency_id.name ]] - - - Printed at: [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] at [[ time.strftime('%H:%M:%S')]] - - - - - Analysis from [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - Budget : [[ o.name ]] - - - - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
- [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]][[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc'], digits=2) ]]% - - - -
- - - - [[ repeatIn(funct_total(data['form']),'b') ]]Total: - - - [[ formatLang(b['tot_theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc'], digits=2) ]]% - - - - - - -
-
diff --git a/addons/account_budget/report/crossovered_budget_report.py b/addons/account_budget/report/crossovered_budget_report.py index 70cbdecb713..8a001aafb39 100644 --- a/addons/account_budget/report/crossovered_budget_report.py +++ b/addons/account_budget/report/crossovered_budget_report.py @@ -20,11 +20,9 @@ ############################################################################## import time -import datetime - +from openerp.osv import osv from openerp.report import report_sxw -import operator -from openerp import osv + class budget_report(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): @@ -191,7 +189,11 @@ class budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.crossovered.budget.report', 'crossovered.budget', 'addons/account_budget/report/crossovered_budget_report.rml',parser=budget_report,header='internal') + +class report_crossoveredbudget(osv.AbstractModel): + _name = 'report.account_budget.report_crossoveredbudget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_crossoveredbudget' + _wrapped_report_class = budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_budget/report/crossovered_budget_report.rml b/addons/account_budget/report/crossovered_budget_report.rml deleted file mode 100644 index a63920a4c9f..00000000000 --- a/addons/account_budget/report/crossovered_budget_report.rml +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - Budget - - - - - - - Analysis from - - - Budget - - - Currency - - - - - - - [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - [[ o.name ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
- [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]][[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc'],digits=2) ]]% - - - -
- - - - [[ repeatIn(funct_total(data['form']),'b') ]] Total : - - - [[ formatLang(b['tot_theo'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc'],digits=2) ]]% - - - - - - -
-
diff --git a/addons/account_budget/test/account_budget_report.yml b/addons/account_budget/test/account_budget_report.yml index 80ab9b36b34..a36c2d87d04 100644 --- a/addons/account_budget/test/account_budget_report.yml +++ b/addons/account_budget/test/account_budget_report.yml @@ -2,35 +2,22 @@ Print the Analytic Budget Report through wizard - !python {model: account.analytic.account}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.analytic.account','active_ids': [ref('account.analytic_root')]}) - data_dict = {} + ctx = {'model': 'account.analytic.account','active_ids': [ref('account.analytic_root')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_analytic',wiz_data=data_dict, context=ctx, our_module='account_budget') + test_reports.try_report_action(cr, uid, 'action_account_budget_analytic',wiz_data={}, context=ctx, our_module='account_budget') - Print the Budget Report through wizard - !python {model: account.budget.post}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.budget.post','active_ids': [ref('account_budget.account_budget_post_sales0')]}) - data_dict = {} + ctx = {'model': 'account.budget.post','active_ids': [ref('account_budget.account_budget_post_sales0')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_report',wiz_data=data_dict, context=ctx, our_module='account_budget') + test_reports.try_report_action(cr, uid, 'action_account_budget_report',wiz_data={}, context=ctx, our_module='account_budget') - Print the CrossOvered Budget Report mode through wizard - !python {model: crossovered.budget}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.budget.post','active_ids': [ref('account_budget.crossovered_budget_budgetoptimistic0')]}) - data_dict = {} + ctx = {'model': 'account.budget.post','active_ids': [ref('account_budget.crossovered_budget_budgetoptimistic0')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_crossvered_report',wiz_data=data_dict, context=ctx, our_module='account_budget') - + test_reports.try_report_action(cr, uid, 'action_account_budget_crossvered_report',wiz_data={}, context=ctx, our_module='account_budget') diff --git a/addons/account_budget/views/report_analyticaccountbudget.xml b/addons/account_budget/views/report_analyticaccountbudget.xml new file mode 100644 index 00000000000..dab987d6099 --- /dev/null +++ b/addons/account_budget/views/report_analyticaccountbudget.xml @@ -0,0 +1,69 @@ + + + + + + \ No newline at end of file diff --git a/addons/account_budget/views/report_budget.xml b/addons/account_budget/views/report_budget.xml new file mode 100644 index 00000000000..6bc72fc9dca --- /dev/null +++ b/addons/account_budget/views/report_budget.xml @@ -0,0 +1,77 @@ + + + + + + diff --git a/addons/account_budget/views/report_crossoveredbudget.xml b/addons/account_budget/views/report_crossoveredbudget.xml new file mode 100644 index 00000000000..412c2aac8ed --- /dev/null +++ b/addons/account_budget/views/report_crossoveredbudget.xml @@ -0,0 +1,81 @@ + + + + + + diff --git a/addons/account_budget/wizard/account_budget_analytic.py b/addons/account_budget/wizard/account_budget_analytic.py index 90285b90d1e..a58b804ebbf 100644 --- a/addons/account_budget/wizard/account_budget_analytic.py +++ b/addons/account_budget/wizard/account_budget_analytic.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + # -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_analytic(osv.osv_memory): _name = 'account.budget.analytic' @@ -30,7 +31,7 @@ class account_budget_analytic(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -40,15 +41,11 @@ class account_budget_analytic(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.budget', - 'datas': datas, - } - + datas['form']['ids'] = datas['ids'] + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_analyticaccountbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_report.py b/addons/account_budget/wizard/account_budget_crossovered_report.py index 6f89a3cd95c..96561df5af0 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_crossvered_report(osv.osv_memory): _name = "account.budget.crossvered.report" @@ -40,16 +41,12 @@ class account_budget_crossvered_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'crossovered.budget', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'crossovered.budget', + 'form': data } + datas['form']['ids'] = datas['ids'] datas['form']['report'] = 'analytic-full' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'crossovered.budget.report', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py index 6e3131b584c..6b676ecc684 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_crossvered_summary_report(osv.osv_memory): """ This wizard provides the crossovered budget summary report' @@ -32,7 +33,7 @@ class account_budget_crossvered_summary_report(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -42,17 +43,12 @@ class account_budget_crossvered_summary_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'crossovered.budge', - 'form': data + 'ids': context.get('active_ids',[]), + 'model': 'crossovered.budge', + 'form': data } + datas['form']['ids'] = datas['ids'] datas['form']['report'] = 'analytic-one' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'crossovered.budget.report', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_budget/wizard/account_budget_report.py b/addons/account_budget/wizard/account_budget_report.py index 54c3180ee0d..2308b5ff9ac 100644 --- a/addons/account_budget/wizard/account_budget_report.py +++ b/addons/account_budget/wizard/account_budget_report.py @@ -18,8 +18,8 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv @@ -31,7 +31,7 @@ class account_budget_report(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -41,16 +41,12 @@ class account_budget_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.budget.post', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'account.budget.post', + 'form': data } - datas['form']['report']='analytic-full' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.budget', - 'datas': datas, - } - + datas['form']['ids'] = datas['ids'] + datas['form']['report'] = 'analytic-full' + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_budget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_check_writing/__openerp__.py b/addons/account_check_writing/__openerp__.py index e01c17d66a7..3311a7c03b3 100644 --- a/addons/account_check_writing/__openerp__.py +++ b/addons/account_check_writing/__openerp__.py @@ -31,10 +31,12 @@ Module for the Check Writing and Check Printing. 'depends' : ['account_voucher'], 'data': [ 'wizard/account_check_batch_printing_view.xml', - 'account_check_writing_report.xml', 'account_view.xml', 'account_voucher_view.xml', 'account_check_writing_data.xml', + 'data/report_paperformat.xml', + 'views/report_check.xml', + 'account_check_writing_report.xml', ], 'demo': ['account_demo.xml'], 'test': [], diff --git a/addons/account_check_writing/account_check_writing_report.xml b/addons/account_check_writing/account_check_writing_report.xml index eece4e4a5da..d32dd77bc8f 100644 --- a/addons/account_check_writing/account_check_writing_report.xml +++ b/addons/account_check_writing/account_check_writing_report.xml @@ -1,29 +1,17 @@ - + - - - - - + + + + diff --git a/addons/account_check_writing/data/report_paperformat.xml b/addons/account_check_writing/data/report_paperformat.xml new file mode 100644 index 00000000000..3782b8bde40 --- /dev/null +++ b/addons/account_check_writing/data/report_paperformat.xml @@ -0,0 +1,20 @@ + + + + + French Bank Check + + custom + 80 + 175 + Portrait + 3 + 3 + 3 + 3 + + 3 + 80 + + + diff --git a/addons/account_check_writing/report/check_print.py b/addons/account_check_writing/report/check_print.py index add79fcc35a..be5feb4662b 100644 --- a/addons/account_check_writing/report/check_print.py +++ b/addons/account_check_writing/report/check_print.py @@ -20,8 +20,9 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw -from openerp.tools import amount_to_text_en + class report_print_check(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): @@ -33,13 +34,14 @@ class report_print_check(report_sxw.rml_parse): 'get_lines': self.get_lines, 'fill_stars' : self.fill_stars, }) + def fill_stars(self, amount): if len(amount) < 100: stars = 100 - len(amount) return ' '.join([amount,'*'*stars]) else: return amount - + def get_lines(self, voucher_lines): result = [] self.number_lines = len(voucher_lines) @@ -63,24 +65,11 @@ class report_print_check(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw( - 'report.account.print.check.top', - 'account.voucher', - 'addons/account_check_writing/report/check_print_top.rml', - parser=report_print_check,header=False -) -report_sxw.report_sxw( - 'report.account.print.check.middle', - 'account.voucher', - 'addons/account_check_writing/report/check_print_middle.rml', - parser=report_print_check,header=False -) +class report_check(osv.AbstractModel): + _name = 'report.account_check_writing.report_check' + _inherit = 'report.abstract_report' + _template = 'account_check_writing.report_check' + _wrapped_report_class = report_print_check -report_sxw.report_sxw( - 'report.account.print.check.bottom', - 'account.voucher', - 'addons/account_check_writing/report/check_print_bottom.rml', - parser=report_print_check,header=False -) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_check_writing/report/check_print_bottom.rml b/addons/account_check_writing/report/check_print_bottom.rml deleted file mode 100644 index f9add2fe60b..00000000000 --- a/addons/account_check_writing/report/check_print_bottom.rml +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - [[ fill_stars(voucher.amount_in_word) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/report/check_print_middle.rml b/addons/account_check_writing/report/check_print_middle.rml deleted file mode 100644 index b1fffca662d..00000000000 --- a/addons/account_check_writing/report/check_print_middle.rml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - - - - - - [[ str(fill_stars(voucher.amount_in_word)) ]] - - - - - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/report/check_print_top.rml b/addons/account_check_writing/report/check_print_top.rml deleted file mode 100644 index 9a4d633e680..00000000000 --- a/addons/account_check_writing/report/check_print_top.rml +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - [[ fill_stars(voucher.amount_in_word) ]] - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - - - - - - - - - [[ voucher.name ]] - - - - - - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Open Balance - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_due'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_unreconciled']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Open Balance - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_due'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_unreconciled']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/views/report_check.xml b/addons/account_check_writing/views/report_check.xml new file mode 100644 index 00000000000..d740de1a0a4 --- /dev/null +++ b/addons/account_check_writing/views/report_check.xml @@ -0,0 +1,48 @@ + + + + + + diff --git a/addons/account_followup/__openerp__.py b/addons/account_followup/__openerp__.py index dbb4ea6583e..61e9ea2d4ae 100644 --- a/addons/account_followup/__openerp__.py +++ b/addons/account_followup/__openerp__.py @@ -55,11 +55,12 @@ Note that if you want to check the follow-up level for a given partner/account e 'account_followup_view.xml', 'account_followup_customers.xml', 'wizard/account_followup_print_view.xml', + 'views/report_followup.xml', + 'account_followup_reports.xml' ], 'demo': ['account_followup_demo.xml'], 'test': [ 'test/account_followup.yml', - #TODO 'test/account_followup_report.yml', --> Need to wait for second step in order to check report (expects after first) ], 'installable': True, 'auto_install': False, diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py index 9237282ad80..eae361913ad 100644 --- a/addons/account_followup/account_followup.py +++ b/addons/account_followup/account_followup.py @@ -21,7 +21,6 @@ from openerp.osv import fields, osv from lxml import etree - from openerp.tools.translate import _ class followup(osv.osv): @@ -189,11 +188,7 @@ class res_partner(osv.osv): 'model': 'account_followup.followup', 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account_followup.followup.print', - 'datas': datas, - } + return self.pool['report'].get_action(cr, uid, wizard_partner_ids, 'account_followup.report_followup', data=datas, context=context) def do_partner_mail(self, cr, uid, partner_ids, context=None): if context is None: @@ -274,6 +269,9 @@ class res_partner(osv.osv): strbegin = "" strend = "" followup_table +="" + strbegin + str(aml['date']) + strend + strbegin + aml['name'] + strend + strbegin + aml['ref'] + strend + strbegin + str(date) + strend + strbegin + str(aml['balance']) + strend + strbegin + block + strend + "" + + total = reduce(lambda x, y: x+y['balance'], currency_dict['line'], 0.00) + total = rml_parse.formatLang(total, dp='Account', currency_obj=currency) followup_table += ''' diff --git a/addons/account_followup/account_followup_reports.xml b/addons/account_followup/account_followup_reports.xml new file mode 100644 index 00000000000..16149a5fd47 --- /dev/null +++ b/addons/account_followup/account_followup_reports.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/addons/account_followup/account_followup_view.xml b/addons/account_followup/account_followup_view.xml index e233feb489e..57f71566db0 100644 --- a/addons/account_followup/account_followup_view.xml +++ b/addons/account_followup/account_followup_view.xml @@ -132,7 +132,6 @@ id="menu_manual_reconcile_followup"/> - account.move.line.partner.tree diff --git a/addons/account_followup/report/account_followup_print.py b/addons/account_followup/report/account_followup_print.py index eecba81acb9..4e856853915 100644 --- a/addons/account_followup/report/account_followup_print.py +++ b/addons/account_followup/report/account_followup_print.py @@ -21,9 +21,10 @@ import time from collections import defaultdict - +from openerp.osv import osv from openerp.report import report_sxw + class report_rappel(report_sxw.rml_parse): _name = "account_followup.report.rappel" @@ -108,8 +109,11 @@ class report_rappel(report_sxw.rml_parse): } return text -report_sxw.report_sxw('report.account_followup.followup.print', - 'account_followup.stat.by.partner', 'addons/account_followup/report/account_followup_print.rml', - parser=report_rappel) + +class report_followup(osv.AbstractModel): + _name = 'report.account_followup.report_followup' + _inherit = 'report.abstract_report' + _template = 'account_followup.report_followup' + _wrapped_report_class = report_rappel # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_followup/report/account_followup_print.rml b/addons/account_followup/report/account_followup_print.rml deleted file mode 100644 index 6eadaed8675..00000000000 --- a/addons/account_followup/report/account_followup_print.rml +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(ids_to_objects(data['form']['partner_ids']),'o') ]] - [[ setLang(o.partner_id.lang) ]] - - - - - - - [[ o.partner_id.name or '' ]] - [[ display_address(o.partner_id) or '']] - - - - VAT: [[ o.partner_id.vat or removeParentNode('para') ]] - - - - - - - Document : Customer account statement - Date : [[ formatLang(data['form']['date'],date=True) ]] - Customer Ref : [[ o.partner_id.ref or '' ]] - - - -
[[ format(get_text(o,data['form']['followup_id'])) ]]
- - - -
- - - [[repeatIn(getLines(o), 'cur_lines') ]] - - - Invoice Date - - - Description - - - Ref - - - Maturity Date - - - Amount - - - Li. - - - - - - [[repeatIn(cur_lines['line'], 'line') ]] - - [[ formatLang(line['date'],date = True) ]] - - - [[ line['name'] ]] - - - [[ line['ref'] ]] - - - [[ line['date_maturity'] and formatLang(line['date_maturity'], date=True) ]] - - - [[ formatLang(line['balance'], currency_obj=line['currency_id']) ]] - - - [[ line['blocked'] and 'X' or '' ]] - - - - - - - - - - - - Total: - - - [[formatLang(reduce(lambda x,y: x+y['balance'], cur_lines['line'], 0.00), currency_obj=line['currency_id']) ]] - - - - - - - - - - - - - - - - - - - -
- -
-
diff --git a/addons/account_followup/tests/test_account_followup.py b/addons/account_followup/tests/test_account_followup.py index 9e70430c518..b3025021278 100644 --- a/addons/account_followup/tests/test_account_followup.py +++ b/addons/account_followup/tests/test_account_followup.py @@ -59,7 +59,6 @@ class TestAccountFollowup(TransactionCase): self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id}) self.assertFalse(self.partner.browse(cr, uid, self.partner_id).latest_followup_level_id) - def run_wizard_three_times(self): cr, uid = self.cr, self.uid current_date = datetime.datetime.utcnow() @@ -131,7 +130,7 @@ class TestAccountFollowup(TransactionCase): self.run_wizard_three_times() self.assertEqual(self.partner.browse(cr, uid, self.partner_id).latest_followup_level_id.id, self.last_followup_line_id, "Lines are not equal") - + def test_06_pay_the_invoice(self): """Run wizard until manual action, pay the invoice and check that partner has no follow-up level anymore and after running the wizard the action is empty""" cr, uid = self.cr, self.uid @@ -148,7 +147,6 @@ class TestAccountFollowup(TransactionCase): 'followup_id': self.followup_id }, context={"followup_id": self.followup_id}) self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id}) - partner_ref = self.partner.browse(cr, uid, self.partner_id) self.assertEqual(0, self.partner.browse(cr, uid, self.partner_id).payment_amount_due, "Amount Due != 0") self.assertFalse(self.partner.browse(cr, uid, self.partner_id).payment_next_action_date, "Next action date not cleared") diff --git a/addons/account_followup/views/report_followup.xml b/addons/account_followup/views/report_followup.xml new file mode 100644 index 00000000000..6c79fe4cc55 --- /dev/null +++ b/addons/account_followup/views/report_followup.xml @@ -0,0 +1,58 @@ + + + + + + diff --git a/addons/account_followup/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py index 00ecab7b860..7b7cb8fc77e 100644 --- a/addons/account_followup/wizard/account_followup_print.py +++ b/addons/account_followup/wizard/account_followup_print.py @@ -218,18 +218,18 @@ class account_followup_print(osv.osv_memory): #Update partners self.do_update_followup_level(cr, uid, to_update, partner_list, date, context=context) #process the partners (send mails...) - restot = self.process_partners(cr, uid, partner_list, data, context=context) + restot_context = context.copy() + restot = self.process_partners(cr, uid, partner_list, data, context=restot_context) + context.update(restot_context) #clear the manual actions if nothing is due anymore nbactionscleared = self.clear_manual_actions(cr, uid, partner_list, context=context) if nbactionscleared > 0: restot['resulttext'] = restot['resulttext'] + "
  • " + _("%s partners have no credits and as such the action is cleared") %(str(nbactionscleared)) + "
  • " - res = restot['action'] - #return the next action mod_obj = self.pool.get('ir.model.data') model_data_ids = mod_obj.search(cr, uid, [('model','=','ir.ui.view'),('name','=','view_account_followup_sending_results')], context=context) resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] - context.update({'description': restot['resulttext'], 'needprinting': restot['needprinting'], 'report_data': res}) + context.update({'description': restot['resulttext'], 'needprinting': restot['needprinting'], 'report_data': restot['action']}) return { 'name': _('Send Letters and Emails: Actions Summary'), 'view_type': 'form', diff --git a/addons/account_payment/__openerp__.py b/addons/account_payment/__openerp__.py index 4c3c8f045e3..c5cccc38c26 100644 --- a/addons/account_payment/__openerp__.py +++ b/addons/account_payment/__openerp__.py @@ -54,6 +54,8 @@ have a new option to import payment orders as bank statement lines. 'account_payment_workflow.xml', 'account_payment_sequence.xml', 'account_payment_report.xml', + + 'views/report_paymentorder.xml', ], 'demo': ['account_payment_demo.xml'], 'test': [ diff --git a/addons/account_payment/account_payment_report.xml b/addons/account_payment/account_payment_report.xml index 699207e1733..3a57abe901f 100644 --- a/addons/account_payment/account_payment_report.xml +++ b/addons/account_payment/account_payment_report.xml @@ -1,6 +1,13 @@ - + diff --git a/addons/account_payment/report/order.rml b/addons/account_payment/report/order.rml deleted file mode 100644 index 02675baf0b2..00000000000 --- a/addons/account_payment/report/order.rml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Partner - - - Bank Account - - - Invoice Ref - - - Value Date - - - Amount - - - Currency - - - - - [[ repeatIn(objects, 'o') ]] - - - - - - - - - - - - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.name or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.street or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.street2 or removeParentNode('para')]] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.zip or '']] [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.city or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.state and o.mode.bank_id.bank.state.name or removeParentNode('para') ]] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.country and o.mode.bank_id.bank.country.name or '']] - - - - - - - Payment Order / Payment - - - - - - - Payment Type - - - Reference - - - Used Account - - - Execution Type - - - Company Currency - - - - - - - [[ o.mode and o.mode.name or '-' ]] - - - [[ o.reference or '-' ]] - - - [[get_account_name(o.mode.bank_id.id)]] - - - [[ o.date_prefered == 'now' and 'Now' or removeParentNode('para') ]] - [[ o.date_prefered == 'due' and 'Due date' or removeParentNode('para') ]] - [[ o.date_prefered == 'fixed' and 'Fixed date' or removeParentNode('para') ]] - - - [[ o.user_id and o.user_id.company_id and o.user_id.company_id.currency_id and o.user_id.company_id.currency_id.name or '' ]] - - - - - - - - - - Partner - - - Bank Account - - - Invoice Ref - - - Value Date - - - Amount - - - Currency - - - -
    - [[repeatIn(o.line_ids, 'line') ]] - - - - [[line.partner_id and line.partner_id.name or '-' ]] - - - [[get_account_name(line.bank_id.id) or '-']] - - - [[ get_invoice_name(line.ml_inv_ref.id) or '-' ]] - - - [[not line.date and '-' or formatLang(line.date,date=True) ]] - - - [[ formatLang(line.amount or 0.0, currency_obj=line.company_currency) ]] - - - [[ formatLang(line.amount_currency, currency_obj=line.currency) ]] - - - -
    - - - - - - - - - Total: - - - [[ formatLang(get_amount_total(o), currency_obj=o.company_id.currency_id) or '' ]] - - - [[ formatLang(get_amount_total_in_currency(o), currency_obj=(o.line_ids and o.line_ids[0].currency or None)) or '' ]] - - - - - - -
    -
    -
    diff --git a/addons/account_payment/report/payment_order.py b/addons/account_payment/report/payment_order.py index a851a54ecbb..292d0e11bf4 100644 --- a/addons/account_payment/report/payment_order.py +++ b/addons/account_payment/report/payment_order.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class payment_order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context=None): @@ -70,6 +71,11 @@ class payment_order(report_sxw.rml_parse): return value_name[0][1] return False -report_sxw.report_sxw('report.payment.order', 'payment.order', 'addons/account_payment/report/payment_order.rml', parser=payment_order, header="external") + +class report_paymentorder(osv.AbstractModel): + _name = 'report.account_payment.report_paymentorder' + _inherit = 'report.abstract_report' + _template = 'account_payment.report_paymentorder' + _wrapped_report_class = payment_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/test/account_payment_report.yml b/addons/account_payment/test/account_payment_report.yml index 3def62de429..922d2502203 100644 --- a/addons/account_payment/test/account_payment_report.yml +++ b/addons/account_payment/test/account_payment_report.yml @@ -5,6 +5,6 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('payment_order_1')], 'payment.order', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('payment_order_1')], 'account_payment.report_paymentorder', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_payment-payment_order_report.'+format), 'wb+').write(data) diff --git a/addons/account_payment/views/report_paymentorder.xml b/addons/account_payment/views/report_paymentorder.xml new file mode 100644 index 00000000000..42a2cbe989a --- /dev/null +++ b/addons/account_payment/views/report_paymentorder.xml @@ -0,0 +1,109 @@ + + + + + + diff --git a/addons/account_test/__openerp__.py b/addons/account_test/__openerp__.py index cfd4007fed0..51b47bace7a 100644 --- a/addons/account_test/__openerp__.py +++ b/addons/account_test/__openerp__.py @@ -19,11 +19,12 @@ # along with this program. If not, see . # ############################################################################## + { - 'name' : 'Accounting Consistency Tests', - 'version' : '1.0', - 'author' : 'OpenERP', - 'category' : 'Accounting & Finance', + 'name': 'Accounting Consistency Tests', + 'version': '1.0', + 'author': 'OpenERP', + 'category': 'Accounting & Finance', 'website': 'http://www.openerp.com', 'description': """ Asserts on accounting. @@ -34,14 +35,16 @@ You can write a query in order to create Consistency Test and you will get the r in PDF format which can be accessed by Menu Reporting -> Accounting Tests, then select the test and print the report from Print button in header area. """, - 'depends' : ['account'], - 'data' : [ + 'depends': ['account'], + 'data': [ 'security/ir.model.access.csv', 'account_test_view.xml', 'account_test_report.xml', 'account_test_data.xml', + 'views/report_accounttest.xml', ], 'active': False, 'installable': True } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/account_test_report.xml b/addons/account_test/account_test_report.xml index 480507b6072..732b9e9fbdb 100644 --- a/addons/account_test/account_test_report.xml +++ b/addons/account_test/account_test_report.xml @@ -1,14 +1,13 @@ - - - - - + + + diff --git a/addons/account_test/report/account_test.rml b/addons/account_test/report/account_test.rml deleted file mode 100644 index 1efa12fd5cb..00000000000 --- a/addons/account_test/report/account_test.rml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Accouting tests on [[ datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") ]] - - - -
    - [[repeatIn(objects,'o')]] - - - - [[ o.name ]] - - - - - [[ o.desc or '' ]] - - - - - - - [[ repeatIn(execute_code(o.code_exec), 'test_result') ]] - [[ test_result ]] - - - - - - -
    - -
    -
    diff --git a/addons/account_test/report/account_test_report.py b/addons/account_test/report/account_test_report.py index 0cfbc040d82..bb21e3807a8 100644 --- a/addons/account_test/report/account_test_report.py +++ b/addons/account_test/report/account_test_report.py @@ -23,8 +23,10 @@ import datetime import time -from openerp.report import report_sxw +from openerp.osv import osv from openerp.tools.translate import _ +from openerp.report import report_sxw + # # Use period and Journal for selection or resources @@ -84,6 +86,11 @@ class report_assert_account(report_sxw.rml_parse): return result -report_sxw.report_sxw('report.account.test.assert.print', 'accounting.assert.test', 'addons/account_test/report/account_test.rml', parser=report_assert_account, header=False) + +class report_accounttest(osv.AbstractModel): + _name = 'report.account_test.report_accounttest' + _inherit = 'report.abstract_report' + _template = 'account_test.report_accounttest' + _wrapped_report_class = report_assert_account # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/views/report_accounttest.xml b/addons/account_test/views/report_accounttest.xml new file mode 100644 index 00000000000..02ce82218dc --- /dev/null +++ b/addons/account_test/views/report_accounttest.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py index 0659e4f4bae..dc8102d6647 100644 --- a/addons/account_voucher/__openerp__.py +++ b/addons/account_voucher/__openerp__.py @@ -49,7 +49,6 @@ This module manages: 'security/ir.model.access.csv', 'account_voucher_sequence.xml', 'account_voucher_workflow.xml', - 'account_voucher_report.xml', 'wizard/account_statement_from_invoice_view.xml', 'account_voucher_view.xml', 'voucher_payment_receipt_view.xml', @@ -66,7 +65,6 @@ This module manages: 'test/account_voucher.yml', 'test/sales_receipt.yml', 'test/sales_payment.yml', - 'test/account_voucher_report.yml', 'test/case1_usd_usd.yml', 'test/case1_usd_usd_payment_rate.yml', 'test/case2_usd_eur_debtor_in_eur.yml', diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index 5d0ed8297c2..771c6e15bd8 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -732,13 +732,17 @@ class account_voucher(osv.osv): total_credit = 0.0 total_debit = 0.0 - account_type = 'receivable' + account_type = None + if context.get('account_id'): + account_type = self.pool['account.account'].browse(cr, uid, context['account_id'], context=context).type if ttype == 'payment': - account_type = 'payable' + if not account_type: + account_type = 'payable' total_debit = price or 0.0 else: total_credit = price or 0.0 - account_type = 'receivable' + if not account_type: + account_type = 'receivable' if not context.get('move_line_ids', False): ids = move_line_pool.search(cr, uid, [('state','=','valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', '=', partner_id)], context=context) @@ -827,9 +831,9 @@ class account_voucher(osv.osv): else: default['value']['line_dr_ids'].append(rs) - if ttype == 'payment' and len(default['value']['line_cr_ids']) > 0: + if len(default['value']['line_cr_ids']) > 0: default['value']['pre_line'] = 1 - elif ttype == 'receipt' and len(default['value']['line_dr_ids']) > 0: + elif len(default['value']['line_dr_ids']) > 0: default['value']['pre_line'] = 1 default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price, ttype) return default @@ -1662,7 +1666,7 @@ class account_bank_statement_line(osv.osv): def _check_amount(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): if obj.voucher_id: - diff = abs(obj.amount) - obj.voucher_id.amount + diff = abs(obj.amount) - abs(obj.voucher_id.amount) if not self.pool.get('res.currency').is_zero(cr, uid, obj.statement_id.currency, diff): return False return True diff --git a/addons/account_voucher/account_voucher_report.xml b/addons/account_voucher/account_voucher_report.xml deleted file mode 100644 index 239492d1a27..00000000000 --- a/addons/account_voucher/account_voucher_report.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml index 288f8ce9332..3e4f1635914 100644 --- a/addons/account_voucher/account_voucher_view.xml +++ b/addons/account_voucher/account_voucher_view.xml @@ -213,10 +213,10 @@ - + - + onchange_amount(amount) @@ -230,7 +230,7 @@ - +
    @@ -241,7 +241,7 @@ - + diff --git a/addons/account_voucher/report/__init__.py b/addons/account_voucher/report/__init__.py index 862843352a8..53ac7e915be 100644 --- a/addons/account_voucher/report/__init__.py +++ b/addons/account_voucher/report/__init__.py @@ -19,8 +19,6 @@ # ############################################################################## -import account_voucher -import account_voucher_print import account_voucher_sales_receipt # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher.py b/addons/account_voucher/report/account_voucher.py deleted file mode 100644 index c23c7f4d384..00000000000 --- a/addons/account_voucher/report/account_voucher.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import time -from openerp.report import report_sxw -from openerp.tools import amount_to_text_en - -class report_voucher(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(report_voucher, self).__init__(cr, uid, name, context) - self.localcontext.update({ - 'time': time, - 'convert':self.convert, - 'get_title': self.get_title, - 'debit':self.debit, - 'credit':self.credit, - 'get_ref': self._get_ref - }) - - def convert(self, amount, cur): - amt_en = amount_to_text_en.amount_to_text(amount, 'en', cur) - return amt_en - - def get_title(self, type): - title = '' - if type: - title = type[0].swapcase() + type[1:] + " Voucher" - return title - - def debit(self, move_ids): - debit = 0.0 - for move in move_ids: - debit += move.debit - return debit - - def credit(self, move_ids): - credit = 0.0 - for move in move_ids: - credit += move.credit - return credit - - def _get_ref(self, voucher_id, move_ids): - voucher_line_obj = self.pool.get('account.voucher.line') - voucher_line = voucher_line_obj.search(self.cr, self.uid, [('partner_id', '=', move_ids.partner_id.id), ('voucher_id', '=', voucher_id)]) - if voucher_line: - voucher = voucher_line_obj.browse(self.cr, self.uid, voucher_line)[0] - return voucher.name - else: - return -report_sxw.report_sxw( - 'report.voucher.cash_receipt.drcr', - 'account.voucher', - 'addons/account_voucher/report/account_voucher.rml', - parser=report_voucher,header="external" -) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher.rml b/addons/account_voucher/report/account_voucher.rml deleted file mode 100644 index 6b3337aa64f..00000000000 --- a/addons/account_voucher/report/account_voucher.rml +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'voucher') ]] - - - - [[ get_title(voucher.type) ]] - - - - - - - - - - Journal: - - - [[ voucher.type ]] - - - Number: - - - [[ voucher.number ]] - - - - - - - Status: - - - PRO-FORMA [[ ((voucher.state == 'proforma') or removeParentNode('para')) and '' ]] - Draft[[ ((voucher.state == 'draft') or removeParentNode('para')) and '' ]] - Canceled [[ ((voucher.state == 'cancel') or removeParentNode('para')) and '' ]] - Posted [[ ((voucher.state == 'posted') or removeParentNode('para')) and '' ]] - - - Ref. : - - - [[ voucher.reference or '' ]] - - - Date: - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - - - - Particulars - - - Debit - - - Credit - - - - - - -
    - [[ repeatIn(voucher.move_ids,'move_ids') ]] - - - - [[ (move_ids.partner_id and move_ids.partner_id.name) or 'Account']] - - - [[ formatLang(move_ids.debit) ]] - - - [[ formatLang(move_ids.credit) ]] - - - - - [[ move_ids.account_id.name ]] - - - - - - - - - - - - - - - [[ move_ids.name ]] - [[ get_ref(voucher.id,move_ids) ]] - - - - - - - - - - - - - - - - -
    - - - - - - - Through : - - - - - - - - - - - - - - - [[ voucher.narration or '']] - - - - - - - - - - - - - - - On Account of : - - - - - - - - - - - - - - - [[ voucher.name ]] - - - - - - - - - - - - - - - Amount (in words) : - - - - - - - - - - - - - - - [[ convert(voucher.amount,voucher.currency_id.name) ]] - - - - - - - - - - - - - - - - - - - - - - - - - [[ debit(voucher.move_ids)]] - - - [[ credit(voucher.move_ids) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Receiver's Signature - - - - - - - - - - - - - Authorised Signatory - - - - - - -
    -
    diff --git a/addons/account_voucher/report/account_voucher_print.py b/addons/account_voucher/report/account_voucher_print.py deleted file mode 100644 index 1bc411947f6..00000000000 --- a/addons/account_voucher/report/account_voucher_print.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import time -from openerp.report import report_sxw -from openerp.tools import amount_to_text_en - -class report_voucher_print(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(report_voucher_print, self).__init__(cr, uid, name, context) - self.localcontext.update({ - 'time': time, - 'get_title': self.get_title, - 'get_lines':self.get_lines, - 'get_on_account':self.get_on_account, - 'convert':self.convert - }) - - def convert(self, amount, cur): - amt_en = amount_to_text_en.amount_to_text(amount, 'en', cur) - return amt_en - - def get_lines(self, voucher): - result = [] - if voucher.type in ('payment','receipt'): - type = voucher.line_ids and voucher.line_ids[0].type or False - for move in voucher.move_ids: - res = {} - amount = move.credit - if type == 'dr': - amount = move.debit - if amount > 0.0: - res['pname'] = move.partner_id.name - res['ref'] = 'Agst Ref'+" "+str(move.name) - res['aname'] = move.account_id.name - res['amount'] = amount - result.append(res) - else: - type = voucher.line_ids and voucher.line_ids[0].type or False - for move in voucher.move_ids: - res = {} - amount = move.credit - if type == 'dr': - amount = move.debit - if amount > 0.0: - res['pname'] = move.partner_id.name - res['ref'] = move.name - res['aname'] = move.account_id.name - res['amount'] = amount - result.append(res) - return result - - def get_title(self, type): - title = '' - if type: - title = type[0].swapcase() + type[1:] + " Voucher" - return title - - def get_on_account(self, voucher): - name = "" - if voucher.type == 'receipt': - name = "Received cash from "+str(voucher.partner_id.name) - elif voucher.type == 'payment': - name = "Payment from "+str(voucher.partner_id.name) - elif voucher.type == 'sale': - name = "Sale to "+str(voucher.partner_id.name) - elif voucher.type == 'purchase': - name = "Purchase from "+str(voucher.partner_id.name) - return name - -report_sxw.report_sxw( - 'report.voucher.print', - 'account.voucher', - 'addons/account_voucher/report/account_voucher_print.rml', - parser=report_voucher_print,header="external" -) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher_print.rml b/addons/account_voucher/report/account_voucher_print.rml deleted file mode 100644 index 9f0f2e1f07e..00000000000 --- a/addons/account_voucher/report/account_voucher_print.rml +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'voucher') ]] - - - - [[ get_title(voucher.type) ]] - - - - - - - - - - Number: - - - [[ voucher.number ]] - - - - - - - - - - - - - Date: - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - Status: - - - PRO-FORMA [[ ((voucher.state == 'proforma') or removeParentNode('para')) and '' ]] - Draft[[ ((voucher.state == 'draft') or removeParentNode('para')) and '' ]] - Canceled [[ ((voucher.state == 'cancel') or removeParentNode('para')) and '' ]] - Posted [[ ((voucher.state == 'posted') or removeParentNode('para')) and '' ]] - - - - - - - - - - - - - Currency: - - - [[ voucher.currency_id.symbol ]] - - - - - - - - - - Particulars - - - Amount - - - - - - -
    - [[ repeatIn(get_lines(voucher),'p') ]] - - - - Account : - - - - - - - - - - [[ p['pname'] ]] - - - [[ formatLang(p['amount'], currency_obj=voucher.currency_id) ]] - - - - - [[ p['ref'] ]] - - - - - - - - - - Account : [[ p['aname'] ]] - - - - - - - - - - - -
    - - - - - - - Through : - - - - - - - - - - [[ voucher.journal_id.name or '' ]] - - - - - - - - - - On Account of : - - - - - - - - - - [[ get_on_account(voucher) ]] - - - - - - - - - - Amount (in words) : - - - - - - - - - - [[ convert(voucher.amount,voucher.currency_id.name) ]] - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.amount, currency_obj=voucher.currency_id) ]] - - - -
    -
    diff --git a/addons/account_voucher/test/account_voucher_report.yml b/addons/account_voucher/test/account_voucher_report.yml deleted file mode 100644 index 96e96e4bdfd..00000000000 --- a/addons/account_voucher/test/account_voucher_report.yml +++ /dev/null @@ -1,27 +0,0 @@ -- - Demo for Account Voucher -- - !record {model: account.voucher, id: account_voucher_voucheraxelor0again, view: view_sale_receipt_form}: - type: sale - account_id: account.cash - company_id: base.main_company - journal_id: account.bank_journal - name: Voucher Axelor - narration: PC Assemble SC234 - amount: 1000.0 - line_ids: - - account_id: account.cash - amount: 1000.0 - name: Voucher Axelor - period_id: account.period_6 - -- - In order to test the PDF reports defined on a account_voucher, we will print account voucher Report -- - !python {model: account.voucher}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref("account_voucher_voucheraxelor0again")], 'voucher.cash_receipt.drcr', {}, {}) - if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'account_voucher-report.'+format), 'wb+').write(data) diff --git a/addons/base_gengo/__init__.py b/addons/base_gengo/__init__.py index 133fa90dc51..ff48d6cc91f 100644 --- a/addons/base_gengo/__init__.py +++ b/addons/base_gengo/__init__.py @@ -22,5 +22,6 @@ import res_company import ir_translation import wizard +import controller # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_gengo/controller/__init__.py b/addons/base_gengo/controller/__init__.py new file mode 100644 index 00000000000..4648ae64b0f --- /dev/null +++ b/addons/base_gengo/controller/__init__.py @@ -0,0 +1 @@ +import gengo_callback diff --git a/addons/base_gengo/controller/gengo_callback.py b/addons/base_gengo/controller/gengo_callback.py new file mode 100644 index 00000000000..381ac7b7fe9 --- /dev/null +++ b/addons/base_gengo/controller/gengo_callback.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +import openerp +from openerp.addons.web import http +from openerp.addons.web.http import request + +import json + +class website_gengo(http.Controller): + @http.route('/website/gengo_callback', type='http', auth='none') + def gengo_callback(self,**post): + cr, uid, context = request.cr, openerp.SUPERUSER_ID, request.context + translation_pool = request.registry['ir.translation'] + if post and post.get('job'): + job = json.loads(post['job']) + tid = job.get('custom_data', False) + if (job.get('status') == 'approved') and tid: + term = translation_pool.browse(cr, uid, int(tid), context=context) + if term.job_id <> job.get('job_id'): + raise 'Error' + vals = {'state': 'translated', 'value': job.get('body_tgt')} + translation_pool.write(cr, uid, [int(tid)], vals, context=context) diff --git a/addons/base_gengo/gengo_sync_schedular_data.xml b/addons/base_gengo/gengo_sync_schedular_data.xml index e55066e0e74..91a5c8266d8 100644 --- a/addons/base_gengo/gengo_sync_schedular_data.xml +++ b/addons/base_gengo/gengo_sync_schedular_data.xml @@ -5,8 +5,8 @@ Gengo Sync Translation (Response) - 20 - minutes + 6 + hours -1 @@ -17,8 +17,8 @@ Gengo Sync Translation (Request) - 20 - minutes + 6 + hours -1 diff --git a/addons/base_gengo/wizard/base_gengo_translations.py b/addons/base_gengo/wizard/base_gengo_translations.py index ecfb696fddc..f565b520d6c 100644 --- a/addons/base_gengo/wizard/base_gengo_translations.py +++ b/addons/base_gengo/wizard/base_gengo_translations.py @@ -33,10 +33,6 @@ try: from mygengo import MyGengo except ImportError: _logger.warning('Gengo library not found, Gengo features disabled. If you plan to use it, please install the mygengo library from http://pypi.python.org/pypi/mygengo') - class MyGengo(object): - def __init__(self, *args, **kwargs): - # no context for translations - so don't bother - raise ImportError('Gengo library not found, please install mygengo from http://pypi.python.org/pypi/mygengo') GENGO_DEFAULT_LIMIT = 20 @@ -71,7 +67,7 @@ class base_gengo_translations(osv.osv_memory): gengo = MyGengo( public_key=user.company_id.gengo_public_key.encode('ascii'), private_key=user.company_id.gengo_private_key.encode('ascii'), - sandbox = user.company_id.gengo_sandbox, + sandbox=user.company_id.gengo_sandbox, ) gengo.getAccountStats() return (True, gengo) @@ -83,7 +79,7 @@ class base_gengo_translations(osv.osv_memory): ''' Function called by the wizard. ''' - if context == None: + if context is None: context = {} flag, gengo = self.gengo_authentication(cr, uid, context=context) @@ -99,16 +95,16 @@ class base_gengo_translations(osv.osv_memory): ctx['gengo_language'] = wizard.lang_id.id if wizard.sync_limit > 200 or wizard.sync_limit < 1: raise osv.except_osv(_("Warning"), _('Sync limit should between 1 to 200 for Gengo translation services.')) - if wizard.sync_type in ['send','both']: + if wizard.sync_type in ['send', 'both']: self._sync_request(cr, uid, wizard.sync_limit, context=ctx) - if wizard.sync_type in ['receive','both']: - self._sync_response( cr, uid, wizard.sync_limit, context=ctx) + if wizard.sync_type in ['receive', 'both']: + self._sync_response(cr, uid, wizard.sync_limit, context=ctx) return {'type': 'ir.actions.act_window_close'} def _sync_response(self, cr, uid, limit=GENGO_DEFAULT_LIMIT, context=None): """ This method will be called by cron services to get translations from - Gengo. It will read translated terms and comments from Gengo and will + Gengo. It will read translated terms and comments from Gengo and will update respective ir.translation in openerp. """ translation_pool = self.pool.get('ir.translation') @@ -116,48 +112,49 @@ class base_gengo_translations(osv.osv_memory): if not flag: _logger.warning("%s", gengo) else: - translation_id = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('job_id', "!=",False)], limit=limit, context=context) - translation_terms = translation_pool.browse(cr, uid, translation_id, context=context) - gengo_job_id = [term.job_id for term in translation_terms] - if gengo_job_id: - gengo_ids = ','.join(gengo_job_id) - job_response = gengo.getTranslationJobBatch(id=gengo_ids) - if job_response['opstat'] == 'ok': - job_response_dict = dict([(job['job_id'],job) for job in job_response['response']['jobs']]) - for term in translation_terms: - up_term = up_comment = 0 - vals={} - if job_response_dict[term.job_id]['status'] == 'approved': - vals.update({'state': 'translated', - 'value': job_response_dict[term.job_id]['body_tgt']}) - up_term += 1 - job_comment = gengo.getTranslationJobComments(id=term.job_id) - if job_comment['opstat']=='ok': - gengo_comments="" - for comment in job_comment['response']['thread']: - gengo_comments += _('%s\n-- Commented on %s by %s.\n\n') % (comment['body'], time.ctime(comment['ctime']), comment['author']) - vals.update({'gengo_comment': gengo_comments}) - up_comment += 1 - if vals: - translation_pool.write(cr, uid, term.id, vals) - _logger.info("Successfully Updated `%d` terms and %d Comments." % (up_term, up_comment )) + offset = 0 + all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "!=", False)], context=context) + while True: + translation_ids = all_translation_ids[offset:offset + limit] + offset += limit + if not translation_ids: + break + translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context) + gengo_job_id = [term.job_id for term in translation_terms] + if gengo_job_id: + gengo_ids = ','.join(gengo_job_id) + try: + job_response = gengo.getTranslationJobBatch(id=gengo_ids) + except: + continue + if job_response['opstat'] == 'ok': + for job in job_response['response'].get('jobs', []): + self._update_terms_job(cr, uid, job, context=context) return True + def _update_terms_job(self, cr, uid, job, context=None): + translation_pool = self.pool.get('ir.translation') + tid = int(job['custom_data']) + vals = {} + if job.get('job_id', False): + vals['job_id'] = job['job_id'] + vals['state'] = 'inprogress' + if job.get('status', False) in ('queued','available','pending','reviewable'): + vals['state'] = 'inprogress' + if job.get('body_tgt', False) and job.get('status', False)=='approved': + vals['value'] = job['body_tgt'] + if job.get('status', False) in ('approved', 'canceled'): + vals['state'] = 'translated' + if vals: + translation_pool.write(cr, uid, [tid], vals, context=context) + def _update_terms(self, cr, uid, response, context=None): """ Update the terms after their translation were requested to Gengo """ - translation_pool = self.pool.get('ir.translation') - for jobs in response['jobs']: + for jobs in response.get('jobs', []): for t_id, res in jobs.items(): - vals = {} - t_id = int(t_id) - tier = translation_pool.read(cr, uid, [t_id], ['gengo_translation'], context=context)[0]['gengo_translation'] - if tier == "machine": - vals.update({'value': res['body_tgt'], 'state': 'translated'}) - else: - vals.update({'job_id': res['job_id'], 'state': 'inprogress'}) - translation_pool.write(cr, uid, [t_id], vals, context=context) + self._update_terms_job(cr, uid, res, context=context) return def pack_jobs_request(self, cr, uid, term_ids, context=None): @@ -174,20 +171,25 @@ class base_gengo_translations(osv.osv_memory): auto_approve = 1 if user.company_id.gengo_auto_approve else 0 for term in translation_pool.browse(cr, uid, term_ids, context=context): if re.search(r"\w", term.src or ""): - jobs[term.id] = {'type': 'text', - 'slug': 'single::English to ' + term.lang, - 'tier': tools.ustr(term.gengo_translation), - 'body_src': term.src, - 'lc_src': 'en', - 'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang), - 'auto_approve': auto_approve, - 'comment': user.company_id.gengo_comment and "%s %s"%(user.company_id.gengo_comment,term.gengo_comment) or term.gengo_comment, - 'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid,'web.base.url') + '/website/gengo_callback/' + str(term.id) + comment = user.company_id.gengo_comment or '' + if term.gengo_comment: + comment+='\n' + term.gengo_comment + jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = { + 'type': 'text', + 'slug': 'Single :: English to ' + term.lang, + 'tier': tools.ustr(term.gengo_translation), + 'custom_data': str(term.id), + 'body_src': term.src, + 'lc_src': 'en', + 'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang), + 'auto_approve': auto_approve, + 'comment': comment, + 'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid,'web.base.url') + '/website/gengo_callback' } - return {'jobs': jobs} + return {'jobs': jobs, 'as_group': 1} - def _send_translation_terms(self, cr, uid, term_ids, context=None): + def _send_translation_terms(self, cr, uid, term_ids, context=None): """ Send a request to Gengo with all the term_ids in a different job, get the response and update the terms in database accordingly. @@ -216,20 +218,23 @@ class base_gengo_translations(osv.osv_memory): context = {} language_pool = self.pool.get('res.lang') translation_pool = self.pool.get('ir.translation') + domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "=", False)] + if context.get('gengo_language', False): + lc = language_pool.browse(cr, uid, context['gengo_language'], context=context).code + domain.append( ('lang', '=', lc) ) + + all_term_ids = translation_pool.search(cr, uid, domain, context=context) try: - #by default, the request will be made for all terms that needs it, whatever the language - lang_ids = language_pool.search(cr, uid, [], context=context) - if context.get('gengo_language'): - #but if this specific key is given, then we restrict the request on terms of this language only - lang_ids = [context.get('gengo_language')] - langs = [lang.code for lang in language_pool.browse(cr, uid, lang_ids, context=context)] - #search for the n first terms to translate - term_ids = translation_pool.search(cr, uid, [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('lang', 'in', langs),('job_id',"=",False)], limit=limit, context=context) - if term_ids: - self._send_translation_terms(cr, uid, term_ids, context=context) - _logger.info("%s Translation terms have been posted to Gengo successfully", len(term_ids)) - else: - _logger.info('No Translation terms to process.') + offset = 0 + while True: + #search for the n first terms to translate + term_ids = all_term_ids[offset:offset + limit] + if term_ids: + offset += limit + self._send_translation_terms(cr, uid, term_ids, context=context) + _logger.info("%s Translation terms have been posted to Gengo successfully", len(term_ids)) + if not len(term_ids) == limit: + break except Exception, e: _logger.error("%s", e) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 1238bc9570f..78cb09001a9 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -285,7 +285,7 @@ openerp.base_import = function (instance) { callback(item_finder(default_value)); }, - + placeholder: _t('Don\'t import'), width: 'resolve', dropdownCssClass: 'oe_import_selector' }); diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml index 97bf3e66f7a..8d7155912e6 100644 --- a/addons/base_import/static/src/xml/import.xml +++ b/addons/base_import/static/src/xml/import.xml @@ -347,8 +347,7 @@ - + diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index e9ecf70b39b..9b3862508b0 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -126,6 +126,7 @@ class res_partner(osv.osv): continue vat_country, vat_number = self._split_vat(partner.vat) if not check_func(cr, uid, vat_country, vat_number, context=context): + _logger.info(_("Importing VAT Number [%s] is not valid !" % vat_number)) return False return True @@ -149,7 +150,9 @@ class res_partner(osv.osv): vat_no = "'CC##' (CC=Country Code, ##=VAT Number)" if default_vat_check(vat_country, vat_number): vat_no = _ref_vat[vat_country] if vat_country in _ref_vat else vat_no - return '\n' + _('This VAT number does not seem to be valid.\nNote: the expected format is %s') % vat_no + #Retrieve the current partner for wich the VAT is not valid + error_partner = self.browse(cr, uid, ids, context=context) + return '\n' + _('The VAT number [%s] for partner [%s] does not seem to be valid. \nNote: the expected format is %s') % (error_partner[0].vat, error_partner[0].name, vat_no) _constraints = [(check_vat, _construct_constraint_msg, ["vat"])] diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 3dc1fa75b8d..add0030d76c 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -714,7 +714,7 @@ class calendar_event(osv.Model): """ Return date and time (from to from) based on duration with timezone in string : eg. - 1) if user add duration for 2 hours, return : August-23-2013 at ( 04-30 To 06-30) (Europe/Brussels) + 1) if user add duration for 2 hours, return : August-23-2013 at (04-30 To 06-30) (Europe/Brussels) 2) if event all day ,return : AllDay, July-31-2013 """ if context is None: @@ -733,7 +733,7 @@ class calendar_event(osv.Model): time = _("AllDay , %s") % (event_date) elif meeting.duration < 24: duration = date + timedelta(hours=meeting.duration) - time = ("%s at ( %s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz) + time = ("%s at (%s To %s) (%s)") % (event_date, display_time, duration.strftime('%H-%M'), tz) else: time = ("%s at %s To\n %s at %s (%s)") % (event_date, display_time, date_deadline.strftime('%B-%d-%Y'), date_deadline.strftime('%H-%M'), tz) return time @@ -1298,9 +1298,14 @@ class calendar_event(osv.Model): invitation['attendee'].append({'name': attendee.cn, 'status': attendee.state}) return invitation - def get_interval(self, cr, uid, ids, date, interval, context=None): + def get_interval(self, cr, uid, ids, date, interval, tz=None, context=None): #Function used only in calendar_event_data.xml for email template date = datetime.strptime(date.split('.')[0], DEFAULT_SERVER_DATETIME_FORMAT) + + if tz: + timezone = pytz.timezone(tz or 'UTC') + date = date.replace(tzinfo=pytz.timezone('UTC')).astimezone(timezone) + if interval == 'day': res = str(date.day) elif interval == 'month': @@ -1471,7 +1476,7 @@ class calendar_event(osv.Model): self.create_attendees(cr, uid, [res], context=context) return res - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): if not context: context = {} @@ -1479,7 +1484,7 @@ class calendar_event(osv.Model): raise osv.except_osv(_('Warning!'), _('Group by date is not supported, use the calendar view instead.')) virtual_id = context.get('virtual_id', True) context.update({'virtual_id': False}) - res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) + res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby, lazy=lazy) for result in res: #remove the count, since the value is not consistent with the result of the search when expand the group for groupname in groupby: @@ -1582,6 +1587,8 @@ class mail_message(osv.Model): return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): + if context is None: + context = {} if doc_model == 'calendar.event': order = context.get('order', self._order) for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context): diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index 268c4b96bed..ef413ee3bb5 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -147,7 +147,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
    ${object.event_id.get_interval(object.event_id.date, 'month')}
    -
    ${object.event_id.get_interval(object.event_id.date, 'time')}
    +
    ${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
    @@ -212,7 +212,7 @@
    : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: @@ -227,9 +227,9 @@
    @@ -280,7 +280,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
    ${object.event_id.get_interval(object.event_id.date, 'month')}
    -
    ${object.event_id.get_interval(object.event_id.date, 'time')}
    +
    ${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
    @@ -345,7 +345,7 @@
    : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: @@ -360,9 +360,9 @@
    @@ -412,7 +412,7 @@ ${object.event_id.get_interval(object.event_id.date,'day')}
    ${object.event_id.get_interval(object.event_id.date, 'month')}
    -
    ${object.event_id.get_interval(object.event_id.date, 'time')}
    +
    ${not object.event_id.allday and object.event_id.get_interval(object.event_id.date, 'time', tz=object.partner_id.tz) or ''}
    @@ -477,7 +477,7 @@ - - - - - Invoice [[ ((o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')) or removeParentNode('para')) and '' ]] [[ o.number ]] - PRO-FORMA [[ ((o.type == 'out_invoice' and o.state == 'proforma2') or removeParentNode('para')) and '' ]] - Draft Invoice [[ ((o.type == 'out_invoice' and o.state == 'draft') or removeParentNode('para')) and '' ]] - Cancelled Invoice [[ ((o.type == 'out_invoice' and o.state == 'cancel') or removeParentNode('para')) and '' ]] [[ o.number ]] - Refund [[ (o.type=='out_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Refund [[ (o.type=='in_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Invoice [[ (o.type=='in_invoice' or removeParentNode('para')) and '' ]] [[ o.number ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - [[ repeatIn(o.invoice_line,'l') ]] - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - [[ repeatIn(o.tax_line,'t') ]] - -
    - - - - - - - - - - - [[ (o.comment and format(o.comment )) or removeParentNode('para') ]] - - - - [[ (o.payment_term and o.payment_term.note and format(o.payment_term and o.payment_term.note)) or removeParentNode('para') ]] - - - - - - - - - - - - - - diff --git a/addons/report_intrastat/test/report_intrastat_report.yml b/addons/report_intrastat/test/report_intrastat_report.yml index 687f605b901..5c70ba67ef2 100644 --- a/addons/report_intrastat/test/report_intrastat_report.yml +++ b/addons/report_intrastat/test/report_intrastat_report.yml @@ -16,6 +16,6 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('test_invoice_1')], 'account.invoice.intrastat', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('test_invoice_1')], 'report_intrastat.report_intrastatinvoice', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'report_intrastat-intrastat_report.'+format), 'wb+').write(data) diff --git a/addons/report_intrastat/views/report_intrastatinvoice.xml b/addons/report_intrastat/views/report_intrastatinvoice.xml new file mode 100644 index 00000000000..c534f808c95 --- /dev/null +++ b/addons/report_intrastat/views/report_intrastatinvoice.xml @@ -0,0 +1,149 @@ + + + + + + + + diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index bb5bac89e46..1684760debf 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -59,7 +59,7 @@ The Dashboard for the Sales Manager will include 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images': ['images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'], - 'depends': ['account_voucher'], + 'depends': ['account_voucher', 'report'], 'data': [ 'wizard/sale_make_invoice_advance.xml', 'wizard/sale_line_invoice.xml', diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 667f15a375d..48b09ec7493 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -500,7 +500,7 @@ class sale_order(osv.osv): lines.append(line.id) created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines) if created_lines: - invoices.setdefault(o.partner_id.id, []).append((o, created_lines)) + invoices.setdefault(o.partner_invoice_id.id or o.partner_id.id, []).append((o, created_lines)) if not invoices: for o in self.browse(cr, uid, ids, context=context): for i in o.invoice_ids: diff --git a/addons/sale/views/report_saleorder.xml b/addons/sale/views/report_saleorder.xml index c6f237e3ac3..c23e680e664 100644 --- a/addons/sale/views/report_saleorder.xml +++ b/addons/sale/views/report_saleorder.xml @@ -1,131 +1,135 @@ + + diff --git a/addons/sale/wizard/sale_line_invoice.py b/addons/sale/wizard/sale_line_invoice.py index cd199760e9e..fa0b46daa7f 100644 --- a/addons/sale/wizard/sale_line_invoice.py +++ b/addons/sale/wizard/sale_line_invoice.py @@ -101,7 +101,6 @@ class sale_order_line_make_invoice(osv.osv_memory): break if flag: workflow.trg_validate(uid, 'sale.order', order.id, 'manual_invoice', cr) - sales_order_obj.write(cr, uid, [order.id], {'state': 'progress'}) if not invoices: raise osv.except_osv(_('Warning!'), _('Invoice cannot be created for this Sales Order Line due to one of the following reasons:\n1.The state of this sales order line is either "draft" or "cancel"!\n2.The Sales Order Line is Invoiced!')) diff --git a/addons/sale_layout/__init__.py b/addons/sale_layout/__init__.py new file mode 100644 index 00000000000..bff786c0885 --- /dev/null +++ b/addons/sale_layout/__init__.py @@ -0,0 +1 @@ +import models diff --git a/addons/account/report/account_print_invoice.py b/addons/sale_layout/__openerp__.py similarity index 51% rename from addons/account/report/account_print_invoice.py rename to addons/sale_layout/__openerp__.py index 75680810254..b8fcefc6adc 100644 --- a/addons/account/report/account_print_invoice.py +++ b/addons/sale_layout/__openerp__.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). +# Copyright (C) 2014-Today OpenERP SA (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,19 +19,26 @@ # ############################################################################## -import time -from openerp.report import report_sxw - -class account_invoice(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(account_invoice, self).__init__(cr, uid, name, context=context) - self.localcontext.update({ - 'time': time, - }) -report_sxw.report_sxw( - 'report.account.invoice', - 'account.invoice', - 'addons/account/report/account_print_invoice.rml', - parser=account_invoice -) -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +{ + 'name': 'Sale Layout', + 'version': '1.0', + 'sequence': 14, + 'summary': 'Sale Layout, page-break, subtotals, separators, report', + 'description': """ +Manage your sales reports +========================= +With this module you can personnalize the sale order and invoice report with +separators, page-breaks or subtotals. + """, + 'author': 'OpenERP SA', + 'website': 'http://www.openerp.com', + 'depends': ['sale', 'report'], + 'category': 'Sale', + 'data': ['views/sale_layout_category_view.xml', + 'views/report_invoice_layouted.xml', + 'views/report_quotation_layouted.xml', + 'views/sale_layout_template.xml', + 'security/ir.model.access.csv'], + 'demo': ['data/sale_layout_category_data.xml'], + 'installable': True, +} diff --git a/addons/sale_layout/data/sale_layout_category_data.xml b/addons/sale_layout/data/sale_layout_category_data.xml new file mode 100644 index 00000000000..858654e427f --- /dev/null +++ b/addons/sale_layout/data/sale_layout_category_data.xml @@ -0,0 +1,20 @@ + + + + + Services + + + + 1 + + + + Material + + + + 10 + + + diff --git a/addons/sale_layout/models/__init__.py b/addons/sale_layout/models/__init__.py new file mode 100644 index 00000000000..9e9b002e402 --- /dev/null +++ b/addons/sale_layout/models/__init__.py @@ -0,0 +1 @@ +import sale_layout diff --git a/addons/sale_layout/models/sale_layout.py b/addons/sale_layout/models/sale_layout.py new file mode 100644 index 00000000000..ac9d4241607 --- /dev/null +++ b/addons/sale_layout/models/sale_layout.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import osv, fields +from itertools import groupby + + +def grouplines(self, ordered_lines, sortkey): + """Return lines from a specified invoice or sale order grouped by category""" + grouped_lines = [] + for key, valuesiter in groupby(ordered_lines, sortkey): + group = {} + group['category'] = key + group['lines'] = list(v for v in valuesiter) + + if 'subtotal' in key and key.subtotal is True: + group['subtotal'] = sum(line.price_subtotal for line in group['lines']) + grouped_lines.append(group) + + return grouped_lines + + +class SaleLayoutCategory(osv.Model): + _name = 'sale_layout.category' + _order = 'sequence' + _columns = { + 'name': fields.char('Name', required=True), + 'sequence': fields.integer('Sequence', required=True), + 'subtotal': fields.boolean('Add subtotal'), + 'separator': fields.boolean('Add separator'), + 'pagebreak': fields.boolean('Add pagebreak') + } + + _defaults = { + 'subtotal': True, + 'separator': True, + 'pagebreak': False, + 'sequence': 10 + } + + # We want to forbid edit of a category if it is already linked to a report. + def _check(self, cr, uid, ids): + for cat in self.browse(cr, uid, ids): + invoice_obj = self.pool.get('account.invoice.line') + sale_obj = self.pool.get('sale.order.line') + ids = invoice_obj.search(cr, uid, [('sale_layout_cat_id', '=', cat.id)]) + ids += sale_obj.search(cr, uid, [('sale_layout_cat_id', '=', cat.id)]) + + if len(ids) > 0: + return False + + return True + + _constraints = [( + _check, + 'This category could not be modified nor deleted because it is still used in an invoice or' + ' a sale report.', ['name'] + )] + + +class AccountInvoice(osv.Model): + _inherit = 'account.invoice' + + def sale_layout_lines(self, cr, uid, ids, invoice_id=None, context=None): + """ + Returns invoice lines from a specified invoice ordered by + sale_layout_category sequence. Used in sale_layout module. + + :Parameters: + -'invoice_id' (int): specify the concerned invoice. + """ + ordered_lines = self.browse(cr, uid, invoice_id, context=context).invoice_line + # We chose to group first by category model and, if not present, by invoice name + sortkey = lambda x: x.sale_layout_cat_id if x.sale_layout_cat_id else '' + + return grouplines(self, ordered_lines, sortkey) + + +class AccountInvoiceLine(osv.Model): + _inherit = 'account.invoice.line' + _columns = { + 'sale_layout_cat_id': fields.many2one('sale_layout.category', + 'Layout Category'), + 'categ_sequence': fields.related('sale_layout_cat_id', + 'sequence', type='integer', + string='Layout Sequence', store=True) + # Store is intentionally set in order to keep the "historic" order. + } + _order = 'invoice_id, categ_sequence, sequence, id' + + +class SaleOrder(osv.Model): + _inherit = 'sale.order' + + def sale_layout_lines(self, cr, uid, ids, order_id=None, context=None): + """ + Returns order lines from a specified sale ordered by + sale_layout_category sequence. Used in sale_layout module. + + :Parameters: + -'order_id' (int): specify the concerned sale order. + """ + ordered_lines = self.browse(cr, uid, order_id, context=context).order_line + sortkey = lambda x: x.sale_layout_cat_id if x.sale_layout_cat_id else '' + + return grouplines(self, ordered_lines, sortkey) + + +class SaleOrderLine(osv.Model): + _inherit = 'sale.order.line' + _columns = { + 'sale_layout_cat_id': fields.many2one('sale_layout.category', + 'Layout Category'), + 'categ_sequence': fields.related('sale_layout_cat_id', + 'sequence', type='integer', + string='Layout Sequence', store=True) + # Store is intentionally set in order to keep the "historic" order. + } + _order = 'order_id, categ_sequence, sequence, id' + + def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None): + """Save the layout when converting to an invoice line.""" + invoice_vals = super(SaleOrderLine, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context) + if line.sale_layout_cat_id: + invoice_vals['sale_layout_cat_id'] = line.sale_layout_cat_id.id + if line.categ_sequence: + invoice_vals['categ_sequence'] = line.categ_sequence + return invoice_vals diff --git a/addons/sale_layout/security/ir.model.access.csv b/addons/sale_layout/security/ir.model.access.csv new file mode 100644 index 00000000000..119fce977d1 --- /dev/null +++ b/addons/sale_layout/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +report_layout_category_1,report_layout_category_1,model_sale_layout_category,base.group_sale_manager,1,1,1,1 +report_layout_category_2,report_layout_category_2,model_sale_layout_category,account.group_account_manager,1,1,1,1 +report_layout_category_3,report_layout_category_3,model_sale_layout_category,base.group_sale_salesman,1,1,1,O +report_layout_category_4,report_layout_category_4,model_sale_layout_category,base.group_sale_salesman_all_leads,1,1,1,0 diff --git a/addons/sale_layout/views/report_invoice_layouted.xml b/addons/sale_layout/views/report_invoice_layouted.xml new file mode 100644 index 00000000000..4c0b1929484 --- /dev/null +++ b/addons/sale_layout/views/report_invoice_layouted.xml @@ -0,0 +1,65 @@ + + + + + + diff --git a/addons/sale_layout/views/report_quotation_layouted.xml b/addons/sale_layout/views/report_quotation_layouted.xml new file mode 100644 index 00000000000..02f56786392 --- /dev/null +++ b/addons/sale_layout/views/report_quotation_layouted.xml @@ -0,0 +1,70 @@ + + + + + + diff --git a/addons/sale_layout/views/sale_layout_category_view.xml b/addons/sale_layout/views/sale_layout_category_view.xml new file mode 100644 index 00000000000..08f892c127e --- /dev/null +++ b/addons/sale_layout/views/sale_layout_category_view.xml @@ -0,0 +1,120 @@ + + + + + + sale.order.form.inherit_1 + sale.order + + + + + + + + + + + + sale.order.line.form.inherit_2 + sale.order + + + + + + + + + + + + + account.invoice.form.inherit_1 + account.invoice + + + + + + + + + + + + account.invoice.line.form.inherit_2 + account.invoice.line + + + + + + + + + + + + + report.configuration.form.view + sale_layout.category + +
    + + + + + + + + +
    +
    + + + report.configuration.form.view + sale_layout.category + + + + + + + + + + + + + report.configuration.search.view + sale_layout.category + + + + + + + + + + + + + + Report Configuration + sale_layout.category + form + tree,form + + + +
    +
    diff --git a/addons/sale_layout/views/sale_layout_template.xml b/addons/sale_layout/views/sale_layout_template.xml new file mode 100644 index 00000000000..73406fc9fd6 --- /dev/null +++ b/addons/sale_layout/views/sale_layout_template.xml @@ -0,0 +1,43 @@ + + + + + + + + + + diff --git a/addons/share/res_users.py b/addons/share/res_users.py index 702522478dd..9c9ae0034e2 100644 --- a/addons/share/res_users.py +++ b/addons/share/res_users.py @@ -19,21 +19,7 @@ # ############################################################################## from openerp.osv import fields, osv - -class res_groups(osv.osv): - _name = "res.groups" - _inherit = 'res.groups' - _columns = { - 'share': fields.boolean('Share Group', readonly=True, - help="Group created to set access rights for sharing data with some users.") - } - - def get_application_groups(self, cr, uid, domain=None, context=None): - if domain is None: - domain = [] - domain.append(('share', '=', False)) - return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) - +from openerp import SUPERUSER_ID class res_users(osv.osv): _name = 'res.users' @@ -59,4 +45,28 @@ class res_users(osv.osv): }, help="External user with limited access, created only for the purpose of sharing data."), } + +class res_groups(osv.osv): + _name = "res.groups" + _inherit = 'res.groups' + _columns = { + 'share': fields.boolean('Share Group', readonly=True, + help="Group created to set access rights for sharing data with some users.") + } + + def init(self, cr): + # force re-generation of the user groups view without the shared groups + self.update_user_groups_view(cr, SUPERUSER_ID) + parent_class = super(res_groups, self) + if hasattr(parent_class, 'init'): + parent_class.init(cr) + + def get_application_groups(self, cr, uid, domain=None, context=None): + if domain is None: + domain = [] + domain.append(('share', '=', False)) + return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) + + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/i18n/pl.po b/addons/stock/i18n/pl.po index 66cb0cb868c..3f8e6b9bb9f 100644 --- a/addons/stock/i18n/pl.po +++ b/addons/stock/i18n/pl.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0dev\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-21 17:04+0000\n" -"PO-Revision-Date: 2014-04-04 19:47+0000\n" -"Last-Translator: Dariusz Żbikowski \n" +"PO-Revision-Date: 2014-04-07 13:08+0000\n" +"Last-Translator: Dariusz Żbikowski (Krokus) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-05 05:30+0000\n" +"X-Launchpad-Export-Date: 2014-04-08 06:18+0000\n" "X-Generator: Launchpad (build 16976)\n" #. module: stock @@ -2623,7 +2623,7 @@ msgstr "Ustaw na projekt" #: model:ir.actions.act_window,name:stock.action_stock_journal_form #: model:ir.ui.menu,name:stock.menu_action_stock_journal_form msgid "Stock Journals" -msgstr "Dzienniki mogazynowe" +msgstr "Dzienniki magazynowe" #. module: stock #: view:product.product:0 diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 1711bddcfce..19df0de92a2 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -247,37 +247,47 @@ class Website(openerp.addons.web.controllers.main.Home): return True @http.route('/website/attach', type='http', auth='user', methods=['POST'], website=True) - def attach(self, func, upload): + def attach(self, func, upload=None, url=None): + Attachments = request.registry['ir.attachment'] - url = message = None - try: - image_data = upload.read() - image = Image.open(cStringIO.StringIO(image_data)) - w, h = image.size - if w*h > 42e6: # Nokia Lumia 1020 photo resolution - raise ValueError( - u"Image size excessive, uploaded images must be smaller " - u"than 42 million pixel") - - Attachments = request.registry['ir.attachment'] + website_url = message = None + if not upload: + website_url = url + name = url.split("/").pop() attachment_id = Attachments.create(request.cr, request.uid, { - 'name': upload.filename, - 'datas': image_data.encode('base64'), - 'datas_fname': upload.filename, + 'name':name, + 'type': 'url', + 'url': url, 'res_model': 'ir.ui.view', }, request.context) + else: + try: + image_data = upload.read() + image = Image.open(cStringIO.StringIO(image_data)) + w, h = image.size + if w*h > 42e6: # Nokia Lumia 1020 photo resolution + raise ValueError( + u"Image size excessive, uploaded images must be smaller " + u"than 42 million pixel") - [attachment] = Attachments.read( - request.cr, request.uid, [attachment_id], ['website_url'], - context=request.context) - url = attachment['website_url'] - except Exception, e: - logger.exception("Failed to upload image to attachment") - message = unicode(e) + attachment_id = Attachments.create(request.cr, request.uid, { + 'name': upload.filename, + 'datas': image_data.encode('base64'), + 'datas_fname': upload.filename, + 'res_model': 'ir.ui.view', + }, request.context) + + [attachment] = Attachments.read( + request.cr, request.uid, [attachment_id], ['website_url'], + context=request.context) + website_url = attachment['website_url'] + except Exception, e: + logger.exception("Failed to upload image to attachment") + message = unicode(e) return """""" % (func, json.dumps(url), json.dumps(message)) + """ % (func, json.dumps(website_url), json.dumps(message)) @http.route(['/website/publish'], type='json', auth="public", website=True) def publish(self, id, object): @@ -288,8 +298,6 @@ class Website(openerp.addons.web.controllers.main.Home): values = {} if 'website_published' in _object._all_columns: values['website_published'] = not obj.website_published - if 'website_published_datetime' in _object._all_columns and values.get('website_published'): - values['website_published_datetime'] = fields.datetime.now() _object.write(request.cr, request.uid, [_id], values, context=request.context) @@ -341,9 +349,10 @@ class Website(openerp.addons.web.controllers.main.Home): id = int(id) ids = Model.search(request.cr, request.uid, - [('id', '=', id)], context=request.context) \ - or Model.search(request.cr, openerp.SUPERUSER_ID, - [('id', '=', id), ('website_published', '=', True)], context=request.context) + [('id', '=', id)], context=request.context) + if not ids and 'website_published' in Model._all_columns: + ids = Model.search(request.cr, openerp.SUPERUSER_ID, + [('id', '=', id), ('website_published', '=', True)], context=request.context) if not ids: return self.placeholder(response) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 272e3480fb5..17e34bd6895 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -66,7 +66,7 @@ class ir_http(orm.AbstractModel): def reroute(self, path): if not hasattr(request, 'rerouting'): - request.rerouting = [] + request.rerouting = [request.httprequest.path] if path in request.rerouting: raise Exception("Rerouting loop is forbidden") request.rerouting.append(path) diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index ef60aefbeff..8916968f7ca 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -157,7 +157,7 @@ class DateTime(orm.AbstractModel): value = datetime.datetime.strptime( value, DEFAULT_SERVER_DATETIME_FORMAT) if value: - value = column.context_timestamp( + value = fields.datetime.context_timestamp( cr, uid, timestamp=value, context=context) value = value.strftime(openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT) diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 67781cc02a0..c9fadade6ed 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -123,7 +123,7 @@ class view(osv.osv): return arch def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None): - if getattr(request, 'website_enabled', False): + if request and getattr(request, 'website_enabled', False): engine='website.qweb' if isinstance(id_or_xml_id, list): diff --git a/addons/website/models/website.py b/addons/website/models/website.py index a516f5cb96f..a0a6d1fb28b 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -638,7 +638,7 @@ class ir_attachment(osv.osv): # in-document URLs are html-escaped, a straight search will not # find them url = werkzeug.utils.escape(attachment.website_url) - ids = Views.search(cr, uid, [('arch', 'like', url)], context=context) + ids = Views.search(cr, uid, ["|", ('arch', 'like', '"%s"' % url), ('arch', 'like', "'%s'" % url)], context=context) if ids: removal_blocked_by[attachment.id] = Views.read( diff --git a/addons/website/static/src/css/editor.css b/addons/website/static/src/css/editor.css index da0fad43caf..eb4c5b2851c 100644 --- a/addons/website/static/src/css/editor.css +++ b/addons/website/static/src/css/editor.css @@ -94,6 +94,10 @@ display: none; } +.cke_editable .css_editable_mode_display { + display: block !important; +} + .oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child { background-image: url("/website/static/src/img/edit_here.png") !important; } @@ -180,7 +184,7 @@ ul.oe_menu_editor .disclose { cursor: text !important; } -.modal-dialog.select-image { +.modal-dialog.select-media { width: 80%; } @@ -212,7 +216,7 @@ ul.oe_menu_editor .disclose { .modal .font-icons-icons { font-size: 2em; - max-height: 6em; + max-height: 9em; overflow: auto; } .modal .font-icons-icons .font-icons-icon { @@ -271,6 +275,10 @@ ul.oe_menu_editor .disclose { -webkit-border-bottom-right-radius: 8px; border-bottom-right-radius: 8px; } +.existing-attachments .existing-attachment-cell.media_selected > i, .existing-attachments .existing-attachment-cell.media_selected > img { + border-width: 5px; + border-color: #00f8f8; +} .cke_widget_wrapper { position: static !important; @@ -296,17 +304,34 @@ ul.oe_menu_editor .disclose { background-color: #ffd9dd !important; } -.hover-edition-button { +.hover-edition { + display: inline-block; position: absolute; top: 0; left: 0; - z-index: 1000; + z-index: 1001; +} + +.preview-container { + text-align: center; + line-height: 100px; + height: 100px; +} +.preview-container > * { + max-height: 100px; + line-height: 100px; + margin: 0 auto; + display: inline-block; } .cke_editable .fa { cursor: pointer; } +.img-responsive { + text-align: center; +} + /* ---- MOBILE PREVIEW ---- {{{ */ .oe_mobile_preview.modal .modal-content { height: 660px; diff --git a/addons/website/static/src/css/editor.sass b/addons/website/static/src/css/editor.sass index 4571dcd257e..fb80fa47277 100644 --- a/addons/website/static/src/css/editor.sass +++ b/addons/website/static/src/css/editor.sass @@ -77,6 +77,9 @@ .cke_editable .css_editable_mode_hidden display: none +.cke_editable .css_editable_mode_display + display: block !important + .oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child background-image: url('/website/static/src/img/edit_here.png') !important @@ -150,7 +153,7 @@ ul.oe_menu_editor +user-select(auto) cursor: text !important -.modal-dialog.select-image +.modal-dialog.select-media width: 80% .modal .existing-attachments @@ -179,7 +182,7 @@ ul.oe_menu_editor .modal .font-icons-icons font-size: 2em - max-height: 6em + max-height: 9em overflow: auto .font-icons-icon @@ -232,6 +235,10 @@ $attachment-border-color: #848490 border-top: none border-left: none +border-bottom-right-radius(8px) + &.media_selected + > i, > img + border-width: 5px + border-color: rgb(0, 248, 248) // wrapper positioned relatively for drag&drop widget which is disabled below. // Breaks completely horribly crazy products listing page, so take it out. @@ -259,17 +266,30 @@ $attachment-border-color: #848490 outline: 1px solid red !important background-color: #ffd9dd !important -.hover-edition-button +.hover-edition + display: inline-block position: absolute top: 0 left: 0 - // This z-index is due to .navbar of bootstrap - z-index: 1000 + // This z-index is due to .navbar of bootstrap & jQuery-transfo + z-index: 1001 +.preview-container + text-align: center + line-height: 100px + height: 100px + > * + max-height: 100px + line-height: 100px + margin: 0 auto + display: inline-block // fontawesome .cke_editable .fa cursor: pointer +.img-responsive + text-align: center + // }}} /* ---- MOBILE PREVIEW ---- {{{ */ diff --git a/addons/website/static/src/css/snippets.css b/addons/website/static/src/css/snippets.css index 726855f311b..cbfca8be131 100644 --- a/addons/website/static/src/css/snippets.css +++ b/addons/website/static/src/css/snippets.css @@ -201,6 +201,7 @@ height: 0; position: absolute; background: transparent; + z-index: 1001; -webkit-border-radius: 3px; -moz-border-radius: 3px; -ms-border-radius: 3px; @@ -325,11 +326,13 @@ top: auto; left: 50%; bottom: -6px; + margin-left: -50px; } .oe_overlay .oe_handle.size .oe_handle_button { + position: relative; z-index: 3; text-align: center; - margin-left: -32px; + margin-left: -52px; margin-top: -10px; left: 0px; } @@ -341,15 +344,17 @@ box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7); } .oe_overlay .oe_handle.size .size { + position: absolute; width: 64px; cursor: row-resize; top: 9px; + margin-left: 52px; + padding: 0 5px; } .oe_overlay .oe_handle.size .auto_size { - width: 20px; - padding: 0 5px; - top: 1px; - margin-left: 36px; + position: absolute; + width: 100px; + top: 9px; cursor: pointer; } .oe_overlay .oe_handle.readonly { diff --git a/addons/website/static/src/css/snippets.sass b/addons/website/static/src/css/snippets.sass index 9b12e9df246..40467897e26 100644 --- a/addons/website/static/src/css/snippets.sass +++ b/addons/website/static/src/css/snippets.sass @@ -151,6 +151,7 @@ height: 0 position: absolute background: transparent + z-index: 1001 //@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.02) ,rgba(255,255,255,.02) 35px, rgba(0,0,0,.02) 35px, rgba(0,0,0,.02) 75px)) +border-radius(3px) @include transition(opacity 100ms linear) @@ -238,10 +239,12 @@ top: auto left: 50% bottom: -6px + margin-left: -50px .oe_handle_button + position: relative z-index: 3 text-align: center - margin-left: -32px + margin-left: -52px margin-top: -10px left: 0px &:hover @@ -249,14 +252,16 @@ color: #fff +box-shadow(0 0 5px 3px rgba(255,255,255,.7)) .size + position: absolute width: 64px cursor: row-resize top: 9px - .auto_size - width: 20px + margin-left: 52px padding: 0 5px - top: 1px - margin-left: 36px + .auto_size + position: absolute + width: 100px + top: 9px cursor: pointer &.readonly cursor: auto !important diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css index 354796a053e..9339b5e03b9 100644 --- a/addons/website/static/src/css/website.css +++ b/addons/website/static/src/css/website.css @@ -1,3 +1,4 @@ +@charset "utf-8"; /* THIS CSS FILE IS FOR WEBSITE THEMING CUSTOMIZATION ONLY * * css for editor buttons, openerp widget included in the website and other @@ -284,10 +285,6 @@ ul.nav-stacked > li > a { background-size: 100%; } -section, .carousel, .parallax, .row, .hr, .blockquote { - min-height: 30px; -} - .carousel, .parallax, .blockquote { overflow: hidden; } @@ -376,17 +373,33 @@ section, .carousel, .parallax, .row, .hr, .blockquote { position: absolute; margin-top: -8px; } -.carousel .carousel-control.left span { - left: 10px; +.carousel .carousel-control.left { + left: -10px; } -.carousel .carousel-control.right span { - right: 10px; +.carousel .carousel-control.left * { + position: absolute; + top: 50%; + z-index: 5; + right: 50%; +} +.carousel .carousel-control.right { + right: -10px; +} +.carousel .carousel-control.right * { + position: absolute; + top: 50%; + z-index: 5; + left: 50%; } .quotecarousel { padding-bottom: 16px; } +.hr { + padding: 4px 0; +} + /* Parallax Theme */ div.carousel .carousel-indicators li { border: 1px solid grey; @@ -527,3 +540,33 @@ span[data-oe-type="monetary"] { width: 400px; margin: 40px auto; } + +div.media_iframe_video { + height: 0; + margin: 0 auto; + text-align: center; + position: relative; + overflow: hidden; + padding-bottom: 66.5%; +} +div.media_iframe_video iframe { + width: 100%; + height: 100%; +} +div.media_iframe_video div { + position: absolute; + width: 100%; + height: 100%; + display: none; +} + +/* Mobile view */ +@media (max-width: 768px) { + img:not(.cke_iframe), .media_iframe_video, span.fa, i.fa { + -webkit-transform: none !important; + -moz-transform: none !important; + -ms-transform: none !important; + -o-transform: none !important; + transform: none !important; + } +} diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass index 77da53c2958..e8a7d870623 100644 --- a/addons/website/static/src/css/website.sass +++ b/addons/website/static/src/css/website.sass @@ -234,8 +234,6 @@ ul.nav-stacked > li > a .oe_img_bg background-size: 100% -section, .carousel, .parallax, .row, .hr, .blockquote - min-height: 30px .carousel, .parallax, .blockquote overflow: hidden @@ -308,14 +306,27 @@ section, .carousel, .parallax, .row, .hr, .blockquote top: 50% position: absolute margin-top: -8px - &.left span - left: 10px - &.right span - right: 10px + &.left + left: -10px + * + position: absolute + top: 50% + z-index: 5 + right: 50% + &.right + right: -10px + * + position: absolute + top: 50% + z-index: 5 + left: 50% .quotecarousel padding-bottom: 16px +.hr + padding: 4px 0 + /* Parallax Theme */ div.carousel @@ -434,3 +445,28 @@ span[data-oe-type="monetary"] overflow:hidden text-overflow:ellipsis +div.media_iframe_video + height: 0 + margin: 0 auto + text-align: center + position: relative + overflow: hidden + padding-bottom: 66.5% + iframe + width: 100% + height: 100% + div + position: absolute + width: 100% + height: 100% + display: none + +/* Mobile view */ + +@media (max-width: 768px) + img:not(.cke_iframe), .media_iframe_video, span.fa, i.fa + -webkit-transform: none !important + -moz-transform: none !important + -ms-transform: none !important + -o-transform: none !important + transform: none !important diff --git a/addons/website/static/src/js/jQuery.transfo.js b/addons/website/static/src/js/jQuery.transfo.js new file mode 100644 index 00000000000..725e5a02216 --- /dev/null +++ b/addons/website/static/src/js/jQuery.transfo.js @@ -0,0 +1,433 @@ +/* +Copyright (c) 2014 Christophe Matthieu, + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +(function($){ + 'use strict'; + var rad = Math.PI/180; + + // public methods + var methods = { + init : function(settings) { + return this.each(function() { + var $this = $(this), transfo = $this.data('transfo'); + if (!transfo) { + _init($this, settings); + } else { + _overwriteOptions($this, transfo, settings); + _targetCss($this, transfo); + } + }); + }, + + destroy : function() { + return this.each(function() { + var $this = $(this); + if ($this.data('transfo')) { + _destroy($this); + } + }); + }, + + reset : function() { + return this.each(function() { + var $this = $(this); + if ($this.data('transfo')) { + _reset($this); + } + }); + }, + + toggle : function() { + return this.each(function() { + var $this = $(this); + var transfo = $this.data('transfo'); + if (transfo) { + transfo.settings.hide = !transfo.settings.hide; + _showHide($this, transfo); + } + }); + }, + + hide : function() { + return this.each(function() { + var $this = $(this); + var transfo = $this.data('transfo'); + if (transfo) { + transfo.settings.hide = true; + _showHide($this, transfo); + } + }); + }, + + show : function() { + return this.each(function() { + var $this = $(this); + var transfo = $this.data('transfo'); + if (transfo) { + transfo.settings.hide = false; + _showHide($this, transfo); + } + }); + }, + + settings : function() { + if(this.length > 1) { + this.map(function () { + var $this = $(this); + return $this.data('transfo') && $this.data('transfo').settings; + }); + } + return this.data('transfo') && $this.data('transfo').settings; + }, + center : function() { + if(this.length > 1) { + this.map(function () { + var $this = $(this); + return $this.data('transfo') && $this.data('transfo').$center.offset(); + }); + } + return this.data('transfo') && this.data('transfo').$center.offset(); + } + }; + + $.fn.transfo = function( method ) { + if ( methods[method] ) { + return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.transfo' ); + } + return false; + }; + + function _init ($this, settings) { + var transfo = {}; + $this.data('transfo', transfo); + transfo.settings = settings; + + // generate all the controls markup + var css = "box-sizing: border-box; position: absolute; background-color: #fff; border: 1px solid #ccc; width: 8px; height: 8px; margin-left: -4px; margin-top: -4px;"; + transfo.$markup = $('' + + '
    ' + + '
    ' + + '' + + '' + + '' + + '' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    '); + transfo.$center = transfo.$markup.find(".transfo-scaler-mc"); + + // init setting and get css to set wrap + _setOptions($this, transfo); + _overwriteOptions ($this, transfo, settings); + + // append controls to container + $("body").append(transfo.$markup); + + // set transfo container and markup + setTimeout(function () { + _targetCss($this, transfo); + },0); + + _bind($this, transfo); + + _targetCss($this, transfo); + } + + function _overwriteOptions ($this, transfo, settings) { + transfo.settings = $.extend(transfo.settings, settings || {}); + } + + function _setOptions ($this, transfo) { + var style = $this.attr("style") || ""; + var transform = style.match(/transform\s*:([^;]+)/) ? style.match(/transform\s*:([^;]+)/)[1] : ""; + + transfo.settings = {}; + + transfo.settings.angle= transform.indexOf('rotate') != -1 ? parseFloat(transform.match(/rotate\(([^)]+)deg\)/)[1]) : 0; + transfo.settings.scalex= transform.indexOf('scaleX') != -1 ? parseFloat(transform.match(/scaleX\(([^)]+)\)/)[1]) : 1; + transfo.settings.scaley= transform.indexOf('scaleY') != -1 ? parseFloat(transform.match(/scaleY\(([^)]+)\)/)[1]) : 1; + + transfo.settings.style = style.replace(/[^;]*transform[^;]+/g, '').replace(/;+/g, ';'); + $this.attr("style", transfo.settings.style); + + transfo.settings.height = $this.innerHeight(); + transfo.settings.width = $this.innerWidth(); + + var translatex = transform.match(/translateX\(([0-9.-]+)(%|px)\)/); + var translatey = transform.match(/translateY\(([0-9.-]+)(%|px)\)/); + transfo.settings.translate = "%"; + + if (translatex && translatex[2] === "%") { + transfo.settings.translatexp = parseFloat(translatex[1]); + transfo.settings.translatex = transfo.settings.translatexp / 100 * transfo.settings.width; + } else { + transfo.settings.translatex = translatex ? parseFloat(translatex[1]) : 0; + } + if (translatey && translatey[2] === "%") { + transfo.settings.translateyp = parseFloat(translatey[1]); + transfo.settings.translatey = transfo.settings.translateyp / 100 * transfo.settings.height; + } else { + transfo.settings.translatey = translatey ? parseFloat(translatey[1]) : 0; + } + + transfo.settings.css = window.getComputedStyle($this[0], null); + transfo.settings.pos = $this.offset(); + + transfo.settings.rotationStep = 5; + transfo.settings.hide = false; + transfo.settings.callback = function () {}; + } + + function _bind ($this, transfo) { + function mousedown (event) { + _mouseDown($this, this, transfo, event); + $(document).on("mousemove", mousemove).on("mouseup", mouseup); + } + function mousemove (event) { + _mouseMove($this, this, transfo, event); + } + function mouseup (event) { + _mouseUp($this, this, transfo, event); + $(document).off("mousemove", mousemove).off("mouseup", mouseup); + } + + transfo.$markup.off().on("mousedown", mousedown); + transfo.$markup.find(">:not(.transfo-scaler-mc)").off().on("mousedown", mousedown); + } + + function _mouseDown($this, div, transfo, event) { + event.preventDefault(); + if (transfo.active || event.which !== 1) return; + + var type = "position", $e = $(div); + if ($e.hasClass("transfo-rotator")) type = "rotator"; + else if ($e.hasClass("transfo-scaler-tl")) type = "tl"; + else if ($e.hasClass("transfo-scaler-tr")) type = "tr"; + else if ($e.hasClass("transfo-scaler-br")) type = "br"; + else if ($e.hasClass("transfo-scaler-bl")) type = "bl"; + else if ($e.hasClass("transfo-scaler-tc")) type = "tc"; + else if ($e.hasClass("transfo-scaler-bc")) type = "bc"; + else if ($e.hasClass("transfo-scaler-ml")) type = "ml"; + else if ($e.hasClass("transfo-scaler-mr")) type = "mr"; + + transfo.active = { + "type": type, + "scalex": transfo.settings.scalex, + "scaley": transfo.settings.scaley, + "pageX": event.pageX, + "pageY": event.pageY, + "center": transfo.$center.offset(), + }; + } + function _mouseUp($this, div, transfo, event) { + transfo.active = null; + } + + function _mouseMove($this, div, transfo, event) { + event.preventDefault(); + if (!transfo.active) return; + var settings = transfo.settings; + var center = transfo.active.center; + var cdx = center.left - event.pageX; + var cdy = center.top - event.pageY; + + if (transfo.active.type == "rotator") { + var ang, dang = Math.atan((settings.width * settings.scalex) / (settings.height * settings.scaley)) / rad; + + if (cdy) ang = Math.atan(- cdx / cdy) / rad; + else ang = 0; + if (event.pageY >= center.top && event.pageX >= center.left) ang += 180; + else if (event.pageY >= center.top && event.pageX < center.left) ang += 180; + else if (event.pageY < center.top && event.pageX < center.left) ang += 360; + + ang -= dang; + if (settings.scaley < 0 && settings.scalex < 0) ang += 180; + + if (!event.ctrlKey) { + settings.angle = Math.round(ang / transfo.settings.rotationStep) * transfo.settings.rotationStep; + } else { + settings.angle = ang; + } + + // reset position : don't move center + _targetCss($this, transfo); + var new_center = transfo.$center.offset(); + var x = center.left - new_center.left; + var y = center.top - new_center.top; + var angle = ang * rad; + settings.translatex += x*Math.cos(angle) - y*Math.sin(-angle); + settings.translatey += - x*Math.sin(angle) + y*Math.cos(-angle); + } + else if (transfo.active.type == "position") { + var angle = settings.angle * rad; + var x = event.pageX - transfo.active.pageX; + var y = event.pageY - transfo.active.pageY; + transfo.active.pageX = event.pageX; + transfo.active.pageY = event.pageY; + var dx = x*Math.cos(angle) - y*Math.sin(-angle); + var dy = - x*Math.sin(angle) + y*Math.cos(-angle); + + settings.translatex += dx; + settings.translatey += dy; + } + else if (transfo.active.type.length === 2) { + var angle = settings.angle * rad; + var dx = cdx*Math.cos(angle) - cdy*Math.sin(-angle); + var dy = - cdx*Math.sin(angle) + cdy*Math.cos(-angle); + if (transfo.active.type.indexOf("t") != -1) { + settings.scaley = dy / (settings.height/2); + } + if (transfo.active.type.indexOf("b") != -1) { + settings.scaley = - dy / (settings.height/2); + } + if (transfo.active.type.indexOf("l") != -1) { + settings.scalex = dx / (settings.width/2); + } + if (transfo.active.type.indexOf("r") != -1) { + settings.scalex = - dx / (settings.width/2); + } + if (settings.scaley > 0 && settings.scaley < 0.05) settings.scaley = 0.05; + if (settings.scalex > 0 && settings.scalex < 0.05) settings.scalex = 0.05; + if (settings.scaley < 0 && settings.scaley > -0.05) settings.scaley = -0.05; + if (settings.scalex < 0 && settings.scalex > -0.05) settings.scalex = -0.05; + + if (event.shiftKey && + (transfo.active.type === "tl" || transfo.active.type === "bl" || + transfo.active.type === "tr" || transfo.active.type === "br")) { + settings.scaley = settings.scalex; + } + } + + settings.angle = Math.round(settings.angle); + settings.translatex = Math.round(settings.translatex); + settings.translatey = Math.round(settings.translatey); + settings.scalex = Math.round(settings.scalex*100)/100; + settings.scaley = Math.round(settings.scaley*100)/100; + + _targetCss($this, transfo); + return false; + } + + function _setCss($this, css, settings) { + var transform = ""; + var trans = false; + if (settings.angle !== 0) { + trans = true; + transform += " rotate("+settings.angle+"deg) "; + } + if (settings.translatex) { + trans = true; + transform += " translateX("+(settings.translate === "%" ? settings.translatexp+"%" : settings.translatex+"px")+") "; + } + if (settings.translatey) { + trans = true; + transform += " translateY("+(settings.translate === "%" ? settings.translateyp+"%" : settings.translatey+"px")+") "; + } + if (settings.scalex != 1) { + trans = true; + transform += " scaleX("+settings.scalex+") "; + } + if (settings.scaley != 1){ + trans = true; + transform += " scaleY("+settings.scaley+") "; + } + + if (trans) { + css += ";" + /* Safari */ + css += "-webkit-transform:" + transform + ";" + /* Firefox */ + + "-moz-transform:" + transform + ";" + /* IE */ + + "-ms-transform:" + transform + ";" + /* Opera */ + + "-o-transform:" + transform + ";" + /* Other */ + + "transform:" + transform + ";"; + } + + css = css.replace(/(\s*;)+/g, ';').replace(/^\s*;|;\s*$/g, ''); + + $this.attr("style", css); + } + + function _targetCss ($this, transfo) { + var settings = transfo.settings; + var width = parseFloat(settings.css.width); + var height = parseFloat(settings.css.height); + settings.translatexp = Math.round(settings.translatex/width*1000)/10; + settings.translateyp = Math.round(settings.translatey/height*1000)/10; + + _setCss($this, settings.style, settings); + + _setCss(transfo.$markup, + "position: absolute;" + + "top:" + settings.pos.top + "px;" + + "left:" + settings.pos.left + "px;" + + "width:" + width + "px;" + + "height:" + height + "px;" + + "cursor: move;", + settings); + transfo.$markup.find(">").css("transform", "scaleX("+(1/settings.scalex)+") scaleY("+(1/settings.scaley)+")"); + + _showHide($this, transfo); + + transfo.settings.callback.call($this[0], $this); + } + + function _showHide ($this, transfo) { + transfo.$markup.css("z-index", transfo.settings.hide ? -1 : 1000); + if (transfo.settings.hide) { + transfo.$markup.find(">").hide(); + transfo.$markup.find(".transfo-scaler-mc").show(); + } else { + transfo.$markup.find(">").show(); + } + } + + function _destroy ($this) { + $this.data('transfo').$markup.remove(); + $this.removeData('transfo'); + } + + function _reset ($this) { + var transfo = $this.data('transfo'); + _destroy($this); + $this.transfo(transfo.settings); + } + +})(jQuery); diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c965c5ef834..365b8cf46ea 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -64,7 +64,7 @@ return new website.editor.RTELinkDialog(editor).appendTo(document.body); } function image_dialog(editor, image) { - return new website.editor.RTEImageDialog(editor, image).appendTo(document.body); + return new website.editor.MediaDialog(editor, image).appendTo(document.body); } // only enable editors manually @@ -80,14 +80,19 @@ website.init_editor = function () { CKEDITOR.plugins.add('customdialogs', { -// requires: 'link,image', + // requires: 'link,image', init: function (editor) { editor.on('doubleclick', function (evt) { var element = evt.data.element; - if (element.is('img') && is_editable_node(element)) { + if ((element.is('img') || element.$.className.indexOf(' fa-') != -1) && is_editable_node(element)) { image_dialog(editor, element); return; } + var parent = new CKEDITOR.dom.element(element.$.parentNode); + if (parent.$.className.indexOf('media_iframe_video') != -1 && is_editable_node(parent)) { + image_dialog(editor, parent); + return; + } element = get_selected_link(editor) || evt.data.element; if (!(element.is('a') && is_editable_node(element))) { @@ -109,7 +114,7 @@ context: 'a', }); //noinspection JSValidateTypes - editor.addCommand('image', { + editor.addCommand('cimage', { exec: function (editor) { image_dialog(editor); return true; @@ -126,7 +131,7 @@ }); editor.ui.addButton('Image', { label: 'Image', - command: 'image', + command: 'cimage', toolbar: 'insert,10', }); @@ -400,7 +405,7 @@ init: function () { this.on('edit', function () { - new website.editor.FontIconsDialog(editor, this.element.$) + new website.editor.MediaDialog(editor, this.element) .appendTo(document.body); }); }, @@ -629,22 +634,48 @@ }, /** - * Creates a "hover" button for image and link edition + * Creates a "hover" button for link edition * - * @param {String} label the button's label * @param {Function} editfn edition function, called when clicking the button - * @param {String} [classes] additional classes to set on the button * @returns {jQuery} */ - make_hover_button: function (label, editfn, classes) { - return $(openerp.qweb.render('website.editor.hoverbutton', { - label: label, - classes: classes, - })).hide().appendTo(document.body).click(function (e) { + make_hover_button_link: function (editfn) { + return $(openerp.qweb.render('website.editor.hoverbutton.link', {})) + .hide() + .click(function (e) { + e.preventDefault(); + e.stopPropagation(); + editfn.call(this, e); + }) + .appendTo(document.body); + }, + + /** + * Creates a "hover" button for image + * + * @param {Function} editfn edition function, called when clicking the button + * @param {Function} stylefn edition style function, called when clicking the button + * @returns {jQuery} + */ + make_hover_button_image: function (editfn, stylefn) { + var $div = $(openerp.qweb.render('website.editor.hoverbutton.media', {})) + .hide() + .appendTo(document.body); + + $div.find('[data-toggle="dropdown"]').dropdown(); + $div.find(".hover-edition-button").click(function (e) { e.preventDefault(); e.stopPropagation(); editfn.call(this, e); }); + if (stylefn) { + $div.find(".hover-style-button").click(function (e) { + e.preventDefault(); + e.stopPropagation(); + stylefn.call(this, e); + }); + } + return $div; }, /** * For UI clarity, during RTE edition when the user hovers links and @@ -653,23 +684,18 @@ */ setup_hover_buttons: function () { var editor = this.rte.editor; - var $link_button = this.make_hover_button(_t("Change"), function () { + var $link_button = this.make_hover_button_link(function () { var sel = new CKEDITOR.dom.element(previous); editor.getSelection().selectElement(sel); if(sel.hasClass('fa')) { - new website.editor.FontIconsDialog(editor, previous) + new website.editor.MediaDialog(editor, previous) .appendTo(document.body); } else if (previous.tagName.toUpperCase() === 'A') { link_dialog(editor); } $link_button.hide(); previous = null; - }, 'btn-xs'); - var $image_button = this.make_hover_button(_t("Change"), function () { - image_dialog(editor, new CKEDITOR.dom.element(previous)); - $image_button.hide(); - previous = null; - }, 'btn-sm'); + }); function is_icons_widget(element) { var w = editor.widgets.getByElement(element); @@ -681,7 +707,7 @@ // -ish, because when moving to the button itself ``previous`` is // still set to the element having triggered showing the button. var previous; - $(editor.element.$).on('mouseover', 'a, img, .fa', function () { + $(editor.element.$).on('mouseover', 'a', function () { // Back from edit button -> ignore if (previous && previous === this) { return; } @@ -700,34 +726,19 @@ previous = this; var $selected = $(this); var position = $selected.offset(); - if ($selected.is('img')) { - $link_button.hide(); - // center button on image - $image_button.show().offset({ - top: $selected.outerHeight() / 2 - + position.top - - $image_button.outerHeight() / 2, - left: $selected.outerWidth() / 2 - + position.left - - $image_button.outerWidth() / 2, - }); - } else { - $image_button.hide(); - // put button below link, horizontally centered - $link_button.show().offset({ - top: $selected.outerHeight() - + position.top, - left: $selected.outerWidth() / 2 - + position.left - - $link_button.outerWidth() / 2 - }) - } + $link_button.show().offset({ + top: $selected.outerHeight() + + position.top, + left: $selected.outerWidth() / 2 + + position.left + - $link_button.outerWidth() / 2 + }) }).on('mouseleave', 'a, img, .fa', function (e) { var current = document.elementFromPoint(e.clientX, e.clientY); - if (current === $link_button[0] || current === $image_button[0]) { + if (current === $link_button[0] || $(current).parent()[0] === $link_button[0]) { return; } - $image_button.add($link_button).hide(); + $link_button.hide(); previous = null; }); } @@ -1041,6 +1052,7 @@ }, save: function () { this.close(); + this.trigger("saved"); }, cancel: function () { }, @@ -1290,6 +1302,128 @@ }, }); + website.editor.Media = openerp.Widget.extend({ + init: function (parent, editor, media) { + this._super(); + this.parent = parent; + this.editor = editor; + this.media = media; + }, + start: function () { + this.$preview = this.$('.preview-container').detach(); + return this._super(); + }, + search: function (needle) { + }, + save: function () { + }, + clear: function () { + }, + cancel: function () { + }, + close: function () { + }, + }); + website.editor.MediaDialog = website.editor.Dialog.extend({ + template: 'website.editor.dialog.media', + events : _.extend({}, website.editor.Dialog.prototype.events, { + 'input input#icon-search': 'search', + }), + + init: function (editor, media) { + this._super(editor); + this.editor = editor; + this.page = 0; + this.media = media; + }, + start: function () { + var self = this; + + this.imageDialog = new website.editor.RTEImageDialog(this, this.editor, this.media); + this.imageDialog.appendTo(this.$("#editor-media-image")); + this.iconDialog = new website.editor.FontIconsDialog(this, this.editor, this.media); + this.iconDialog.appendTo(this.$("#editor-media-icon")); + this.videoDialog = new website.editor.VideoDialog(this, this.editor, this.media); + this.videoDialog.appendTo(this.$("#editor-media-video")); + + this.active = this.imageDialog; + + $('a[data-toggle="tab"]').on('shown.bs.tab', function (event) { + if ($(event.target).is('[href="#editor-media-image"]')) { + self.active = self.imageDialog; + self.$('li.search, li.previous, li.next').removeClass("hidden"); + } else if ($(event.target).is('[href="#editor-media-icon"]')) { + self.active = self.iconDialog; + self.$('li.search, li.previous, li.next').removeClass("hidden"); + self.$('.nav-tabs li.previous, .nav-tabs li.next').addClass("hidden"); + } else if ($(event.target).is('[href="#editor-media-video"]')) { + self.active = self.videoDialog; + self.$('.nav-tabs li.search').addClass("hidden"); + } + }); + + if (this.media) { + if (this.media.$.nodeName === "IMG") { + this.$('[href="#editor-media-image"]').tab('show'); + } else if (this.media.$.className.match(/(^|\s)media_iframe_video($|\s)/)) { + this.$('[href="#editor-media-video"]').tab('show'); + } else if (this.media.$.className.match(/(^|\s)fa($|\s)/)) { + this.$('[href="#editor-media-icon"]').tab('show'); + } + + if ($(this.media.$).parent().data("oe-field") === "image") { + this.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden'); + } + } + + return this._super(); + }, + save: function () { + var self = this; + if (self.media) { + this.media.$.innerHTML = ""; + if (this.active !== this.imageDialog) { + this.imageDialog.clear(); + } + if (this.active !== this.iconDialog) { + this.iconDialog.clear(); + } + if (this.active !== this.videoDialog) { + this.videoDialog.clear(); + } + } else { + var selection = this.editor.getSelection(); + var range = selection.getRanges(true)[0]; + this.media = new CKEDITOR.dom.element("img"); + range.insertNode(this.media); + range.selectNodeContents(this.media); + this.active.media = this.media; + } + + var $el = $(self.active.media.$); + + this.active.save(); + + this.media.$.className = this.media.$.className.replace(/\s+/g, ' '); + + setTimeout(function () { + $el.trigger("saved", self.active.media.$); + $(document.body).trigger("media-saved", [$el[0], self.active.media.$]); + },0); + + this._super(); + }, + searchTimer: null, + search: function () { + var self = this; + var needle = this.$("input#icon-search").val(); + clearTimeout(this.searchTimer); + this.searchTimer = setTimeout(function () { + self.active.search(needle || ""); + },250); + } + }); + /** * ImageDialog widget. Lets users change an image, including uploading a * new image in OpenERP or selecting the image style (if supported by @@ -1307,73 +1441,118 @@ * selected by the users (or possibly the ones * originally passed in) */ - website.editor.ImageDialog = website.editor.Dialog.extend({ + var IMAGES_PER_ROW = 6; + var IMAGES_ROWS = 2; + website.editor.ImageDialog = website.editor.Media.extend({ template: 'website.editor.dialog.image', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'change .url-source': function (e) { this.changed($(e.target)); }, + 'change .url-source': function (e) { + this.changed($(e.target)); + }, 'click button.filepicker': function () { this.$('input[type=file]').click(); }, 'change input[type=file]': 'file_selection', - 'change input.url': 'preview_image', - 'click a[href=#existing]': 'browse_existing', - 'change select.image-style': 'preview_image', + 'submit form': 'form_submit', + 'change input.url': "change_input", + 'keyup input.url': "change_input", + //'change select.image-style': 'preview_image', + 'click .existing-attachments img': 'select_existing', + 'click .existing-attachment-remove': 'try_remove', }), + init: function (parent, editor, media) { + this.page = 0; + this._super(parent, editor, media); + }, start: function () { - this.$('button.wait').text("Uploading…"); - var $options = this.$('.image-style').children(); - this.image_styles = $options.map(function () { return this.value; }).get(); + var self = this; + var res = this._super(); - var o = { url: null, style: null, }; + var o = { url: null }; // avoid typos, prevent addition of new properties to the object Object.preventExtensions(o); this.trigger('start', o); - if (o.url) { - if (o.style) { - this.$('.image-style').val(o.style); + this.parent.$(".pager > li").click(function (e) { + e.preventDefault(); + var $target = $(e.currentTarget); + if ($target.hasClass('disabled')) { + return; } - this.set_image(o.url); - } + self.page += $target.hasClass('previous') ? -1 : 1; + self.display_attachments(); + }); - return this._super(); + this.set_image(o.url); + + return res; }, save: function () { + if (!this.link) { + this.link = this.$(".existing-attachments img:first").attr('src'); + } this.trigger('save', { - url: this.$('input.url').val(), - style: this.$('.image-style').val(), + url: this.link }); + this.media.renameNode("img"); + this.media.$.attributes.src = this.link; return this._super(); }, + clear: function () { + this.media.$.className = this.media.$.className.replace(/(^|\s)(img(\s|$)|img-[^\s]*)/g, ' '); + }, cancel: function () { this.trigger('cancel'); }, - /** - * Sets the provided image url as the dialog's value-to-save and - * refreshes the preview element to use it. - */ - set_image: function (url, error) { - this.$('input.url').val( - error ? '' : url); - this.$('input.url').val(url); - this.preview_image(); + change_input: function (e) { + var $input = $(e.target); + var $button = $input.parent().find("button"); + if ($input.val() === "") { + $button.addClass("btn-default").removeClass("btn-primary"); + } else { + $button.removeClass("btn-default").addClass("btn-primary"); + } }, - file_selection: function () { - this.$el.addClass('nosave'); - this.$('form').removeClass('has-error').find('.help-block').empty(); - this.$('button.filepicker').removeClass('btn-danger btn-success'); - + search: function (needle) { var self = this; + this.fetch_existing(needle).then(function () { + self.selected_existing(self.$('input.url').val()); + }); + }, + + set_image: function (url, error) { + var self = this; + if (url) this.link = url; + this.$('input.url').val(''); + this.fetch_existing().then(function () { + self.selected_existing(url); + }); + }, + + form_submit: function (event) { + var self = this; + var $form = this.$('form[action="/website/attach"]'); + if (!$form.find('input[name="upload"]').val().length) { + var url = $form.find('input[name="url"]').val(); + if (this.selected_existing(url).size()) { + event.preventDefault(); + return false; + } + } var callback = _.uniqueId('func_'); this.$('input[name=func]').val(callback); - window[callback] = function (url, error) { delete window[callback]; self.file_selected(url, error); }; + }, + file_selection: function () { + this.$el.addClass('nosave'); + this.$('form').removeClass('has-error').find('.help-block').empty(); + this.$('button.filepicker').removeClass('btn-danger btn-success'); this.$('form').submit(); }, file_selected: function(url, error) { @@ -1387,125 +1566,27 @@ $button.addClass('btn-danger'); } this.set_image(url, error); + // auto save and close popup + this.parent.save(); }, - preview_image: function () { - var loaded = function () { - this.$el.removeClass('nosave'); - }.bind(this); - var image = this.$('input.url').val(); - if (!image) { loaded(); return; } - var $img = this.$('img.image-preview') - .attr('src', image) - .removeClass(this.image_styles.join(' ')) - .addClass(this.$('select.image-style').val()); - - if ($img.prop('complete')) { - loaded(); - } else { - $img.load(loaded) + fetch_existing: function (needle) { + var domain = [['res_model', '=', 'ir.ui.view'], '|', + ['mimetype', '=', false], ['mimetype', '=like', 'image/%']]; + if (needle && needle.length) { + domain.push('|', ['datas_fname', 'ilike', needle], ['name', 'ilike', needle]); } - }, - browse_existing: function (e) { - e.preventDefault(); - this.$('form').removeClass('has-error').find('.help-block').empty(); - this.$('button.filepicker').removeClass('btn-danger btn-success'); - new website.editor.ExistingImageDialog(this).appendTo(document.body); - }, - }); - website.editor.RTEImageDialog = website.editor.ImageDialog.extend({ - init: function (editor, image) { - this._super(editor); - - this.element = image; - - this.on('start', this, this.proxy('started')); - this.on('save', this, this.proxy('saved')); - }, - started: function (holder) { - if (!this.element) { - var selection = this.editor.getSelection(); - this.element = selection && selection.getSelectedElement(); - } - - var el = this.element; - if (!el || !el.is('img')) { - return; - } - _(this.image_styles).each(function (style) { - if (el.hasClass(style)) { - holder.style = style; - } - }); - holder.url = el.getAttribute('src'); - }, - saved: function (data) { - var element, editor = this.editor; - if (!(element = this.element)) { - element = editor.document.createElement('img'); - element.addClass('img'); - element.addClass('img-responsive'); - // focus event handler interactions between bootstrap (modal) - // and ckeditor (RTE) lead to blowing the stack in Safari and - // Chrome (but not FF) when this is done synchronously => - // defer insertion so modal has been hidden & destroyed before - // it happens - setTimeout(function () { - editor.insertElement(element); - }, 0); - } - - var style = data.style; - element.setAttribute('src', data.url); - element.removeAttribute('data-cke-saved-src'); - $(element.$).removeClass(this.image_styles.join(' ')); - if (style) { element.addClass(style); } - }, - }); - - var IMAGES_PER_ROW = 6; - var IMAGES_ROWS = 4; - website.editor.ExistingImageDialog = website.editor.Dialog.extend({ - template: 'website.editor.dialog.image.existing', - events: _.extend({}, website.editor.Dialog.prototype.events, { - 'click .existing-attachments img': 'select_existing', - 'click .pager > li': function (e) { - e.preventDefault(); - var $target = $(e.currentTarget); - if ($target.hasClass('disabled')) { - return; - } - this.page += $target.hasClass('previous') ? -1 : 1; - this.display_attachments(); - }, - 'click .existing-attachment-remove': 'try_remove', - }), - init: function (parent) { - this.image = null; - this.page = 0; - this.parent = parent; - this._super(parent.editor); - }, - - start: function () { - return $.when( - this._super(), - this.fetch_existing().then(this.proxy('fetched_existing'))); - }, - - fetch_existing: function () { return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'ir.attachment', method: 'search_read', args: [], kwargs: { fields: ['name', 'website_url'], - domain: [['res_model', '=', 'ir.ui.view'], '|', - ['mimetype', '=', false], ['mimetype', '=like', 'image/%']], + domain: domain, order: 'id desc', context: website.get_context(), } - }); + }).then(this.proxy('fetched_existing')); }, fetched_existing: function (records) { this.records = records; @@ -1528,24 +1609,33 @@ this.$('.existing-attachments').replaceWith( openerp.qweb.render( 'website.editor.dialog.image.existing.content', {rows: rows})); - this.$('.pager') + this.parent.$('.pager') .find('li.previous').toggleClass('disabled', (from === 0)).end() .find('li.next').toggleClass('disabled', (from + per_screen >= records.length)); - }, select_existing: function (e) { var link = $(e.currentTarget).attr('src'); - if (link) { - this.parent.set_image(link); - } - this.close() + this.link = link; + this.selected_existing(link); + }, + selected_existing: function (link) { + this.$('.existing-attachment-cell.media_selected').removeClass("media_selected"); + var $select = this.$('.existing-attachment-cell img').filter(function () { + return $(this).attr("src") == link; + }).first(); + $select.parent().addClass("media_selected"); + return $select; }, try_remove: function (e) { var $help_block = this.$('.help-block').empty(); var self = this; - var id = parseInt($(e.target).data('id'), 10); + var $a = $(e.target); + var id = parseInt($a.data('id'), 10); var attachment = _.findWhere(this.records, {id: id}); + var $both = $a.parent().children(); + + $both.css({borderWidth: "5px", borderColor: "#f00"}); return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'ir.attachment', @@ -1561,6 +1651,7 @@ self.display_attachments(); return; } + $both.css({borderWidth: "", borderColor: ""}); $help_block.replaceWith(openerp.qweb.render( 'website.editor.dialog.image.existing.error', { views: prevented[id] @@ -1570,6 +1661,48 @@ }, }); + website.editor.RTEImageDialog = website.editor.ImageDialog.extend({ + init: function (parent, editor, media) { + this._super(parent, editor, media); + + this.on('start', this, this.proxy('started')); + this.on('save', this, this.proxy('saved')); + }, + started: function (holder) { + if (!this.media) { + var selection = this.editor.getSelection(); + this.media = selection && selection.getSelectedElement(); + } + + var el = this.media; + if (!el || !el.is('img')) { + return; + } + holder.url = el.getAttribute('src'); + }, + saved: function (data) { + var element, editor = this.editor; + if (!(element = this.media)) { + element = editor.document.createElement('img'); + element.addClass('img'); + element.addClass('img-responsive'); + // focus event handler interactions between bootstrap (modal) + // and ckeditor (RTE) lead to blowing the stack in Safari and + // Chrome (but not FF) when this is done synchronously => + // defer insertion so modal has been hidden & destroyed before + // it happens + setTimeout(function () { + editor.insertElement(element); + }, 0); + } + + var style = data.style; + element.setAttribute('src', data.url); + element.removeAttribute('data-cke-saved-src'); + if (style) { element.addClass(style); } + }, + }); + function get_selected_link(editor) { var sel = editor.getSelection(), el = sel.getSelectedElement(); @@ -1581,7 +1714,7 @@ range.shrink(CKEDITOR.SHRINK_TEXT); var commonAncestor = range.getCommonAncestor(); var viewRoot = editor.elementPath(commonAncestor).contains(function (element) { - return element.data('oe-model') === 'ir.ui.view' + return element.data('oe-model') === 'ir.ui.view'; }); if (!viewRoot) { return null; } // if viewRoot is the first link, don't edit it. @@ -1589,7 +1722,7 @@ .contains('a', true); } - website.editor.FontIconsDialog = website.editor.Dialog.extend({ + website.editor.FontIconsDialog = website.editor.Media.extend({ template: 'website.editor.dialog.font-icons', events : _.extend({}, website.editor.Dialog.prototype.events, { change: 'update_preview', @@ -1607,20 +1740,6 @@ this.$('#fa-size').val(e.target.getAttribute('data-size')); this.update_preview(); }, - 'input input#icon-search': function () { - var needle = this.$('#icon-search').val(); - var icons = this.icons; - if (needle) { - icons = _(icons).filter(function (icon) { - return icon.id.substring(3).indexOf(needle) !== -1; - }); - } - - this.$('div.font-icons-icons').html( - openerp.qweb.render( - 'website.editor.dialog.font-icons.icons', - {icons: icons})); - }, }), // List of FontAwesome icons in 4.0.3, extracted from the cheatsheet. @@ -1630,10 +1749,6 @@ // where we still need to implement ``initSelection``) // TODO: add id/name to the text in order to allow FAYT selection of icons? icons: [{"text": "\uf000", "id": "fa-glass"}, {"text": "\uf001", "id": "fa-music"}, {"text": "\uf002", "id": "fa-search"}, {"text": "\uf003", "id": "fa-envelope-o"}, {"text": "\uf004", "id": "fa-heart"}, {"text": "\uf005", "id": "fa-star"}, {"text": "\uf006", "id": "fa-star-o"}, {"text": "\uf007", "id": "fa-user"}, {"text": "\uf008", "id": "fa-film"}, {"text": "\uf009", "id": "fa-th-large"}, {"text": "\uf00a", "id": "fa-th"}, {"text": "\uf00b", "id": "fa-th-list"}, {"text": "\uf00c", "id": "fa-check"}, {"text": "\uf00d", "id": "fa-times"}, {"text": "\uf00e", "id": "fa-search-plus"}, {"text": "\uf010", "id": "fa-search-minus"}, {"text": "\uf011", "id": "fa-power-off"}, {"text": "\uf012", "id": "fa-signal"}, {"text": "\uf013", "id": "fa-cog"}, {"text": "\uf014", "id": "fa-trash-o"}, {"text": "\uf015", "id": "fa-home"}, {"text": "\uf016", "id": "fa-file-o"}, {"text": "\uf017", "id": "fa-clock-o"}, {"text": "\uf018", "id": "fa-road"}, {"text": "\uf019", "id": "fa-download"}, {"text": "\uf01a", "id": "fa-arrow-circle-o-down"}, {"text": "\uf01b", "id": "fa-arrow-circle-o-up"}, {"text": "\uf01c", "id": "fa-inbox"}, {"text": "\uf01d", "id": "fa-play-circle-o"}, {"text": "\uf01e", "id": "fa-repeat"}, {"text": "\uf021", "id": "fa-refresh"}, {"text": "\uf022", "id": "fa-list-alt"}, {"text": "\uf023", "id": "fa-lock"}, {"text": "\uf024", "id": "fa-flag"}, {"text": "\uf025", "id": "fa-headphones"}, {"text": "\uf026", "id": "fa-volume-off"}, {"text": "\uf027", "id": "fa-volume-down"}, {"text": "\uf028", "id": "fa-volume-up"}, {"text": "\uf029", "id": "fa-qrcode"}, {"text": "\uf02a", "id": "fa-barcode"}, {"text": "\uf02b", "id": "fa-tag"}, {"text": "\uf02c", "id": "fa-tags"}, {"text": "\uf02d", "id": "fa-book"}, {"text": "\uf02e", "id": "fa-bookmark"}, {"text": "\uf02f", "id": "fa-print"}, {"text": "\uf030", "id": "fa-camera"}, {"text": "\uf031", "id": "fa-font"}, {"text": "\uf032", "id": "fa-bold"}, {"text": "\uf033", "id": "fa-italic"}, {"text": "\uf034", "id": "fa-text-height"}, {"text": "\uf035", "id": "fa-text-width"}, {"text": "\uf036", "id": "fa-align-left"}, {"text": "\uf037", "id": "fa-align-center"}, {"text": "\uf038", "id": "fa-align-right"}, {"text": "\uf039", "id": "fa-align-justify"}, {"text": "\uf03a", "id": "fa-list"}, {"text": "\uf03b", "id": "fa-outdent"}, {"text": "\uf03c", "id": "fa-indent"}, {"text": "\uf03d", "id": "fa-video-camera"}, {"text": "\uf03e", "id": "fa-picture-o"}, {"text": "\uf040", "id": "fa-pencil"}, {"text": "\uf041", "id": "fa-map-marker"}, {"text": "\uf042", "id": "fa-adjust"}, {"text": "\uf043", "id": "fa-tint"}, {"text": "\uf044", "id": "fa-pencil-square-o"}, {"text": "\uf045", "id": "fa-share-square-o"}, {"text": "\uf046", "id": "fa-check-square-o"}, {"text": "\uf047", "id": "fa-arrows"}, {"text": "\uf048", "id": "fa-step-backward"}, {"text": "\uf049", "id": "fa-fast-backward"}, {"text": "\uf04a", "id": "fa-backward"}, {"text": "\uf04b", "id": "fa-play"}, {"text": "\uf04c", "id": "fa-pause"}, {"text": "\uf04d", "id": "fa-stop"}, {"text": "\uf04e", "id": "fa-forward"}, {"text": "\uf050", "id": "fa-fast-forward"}, {"text": "\uf051", "id": "fa-step-forward"}, {"text": "\uf052", "id": "fa-eject"}, {"text": "\uf053", "id": "fa-chevron-left"}, {"text": "\uf054", "id": "fa-chevron-right"}, {"text": "\uf055", "id": "fa-plus-circle"}, {"text": "\uf056", "id": "fa-minus-circle"}, {"text": "\uf057", "id": "fa-times-circle"}, {"text": "\uf058", "id": "fa-check-circle"}, {"text": "\uf059", "id": "fa-question-circle"}, {"text": "\uf05a", "id": "fa-info-circle"}, {"text": "\uf05b", "id": "fa-crosshairs"}, {"text": "\uf05c", "id": "fa-times-circle-o"}, {"text": "\uf05d", "id": "fa-check-circle-o"}, {"text": "\uf05e", "id": "fa-ban"}, {"text": "\uf060", "id": "fa-arrow-left"}, {"text": "\uf061", "id": "fa-arrow-right"}, {"text": "\uf062", "id": "fa-arrow-up"}, {"text": "\uf063", "id": "fa-arrow-down"}, {"text": "\uf064", "id": "fa-share"}, {"text": "\uf065", "id": "fa-expand"}, {"text": "\uf066", "id": "fa-compress"}, {"text": "\uf067", "id": "fa-plus"}, {"text": "\uf068", "id": "fa-minus"}, {"text": "\uf069", "id": "fa-asterisk"}, {"text": "\uf06a", "id": "fa-exclamation-circle"}, {"text": "\uf06b", "id": "fa-gift"}, {"text": "\uf06c", "id": "fa-leaf"}, {"text": "\uf06d", "id": "fa-fire"}, {"text": "\uf06e", "id": "fa-eye"}, {"text": "\uf070", "id": "fa-eye-slash"}, {"text": "\uf071", "id": "fa-exclamation-triangle"}, {"text": "\uf072", "id": "fa-plane"}, {"text": "\uf073", "id": "fa-calendar"}, {"text": "\uf074", "id": "fa-random"}, {"text": "\uf075", "id": "fa-comment"}, {"text": "\uf076", "id": "fa-magnet"}, {"text": "\uf077", "id": "fa-chevron-up"}, {"text": "\uf078", "id": "fa-chevron-down"}, {"text": "\uf079", "id": "fa-retweet"}, {"text": "\uf07a", "id": "fa-shopping-cart"}, {"text": "\uf07b", "id": "fa-folder"}, {"text": "\uf07c", "id": "fa-folder-open"}, {"text": "\uf07d", "id": "fa-arrows-v"}, {"text": "\uf07e", "id": "fa-arrows-h"}, {"text": "\uf080", "id": "fa-bar-chart-o"}, {"text": "\uf081", "id": "fa-twitter-square"}, {"text": "\uf082", "id": "fa-facebook-square"}, {"text": "\uf083", "id": "fa-camera-retro"}, {"text": "\uf084", "id": "fa-key"}, {"text": "\uf085", "id": "fa-cogs"}, {"text": "\uf086", "id": "fa-comments"}, {"text": "\uf087", "id": "fa-thumbs-o-up"}, {"text": "\uf088", "id": "fa-thumbs-o-down"}, {"text": "\uf089", "id": "fa-star-half"}, {"text": "\uf08a", "id": "fa-heart-o"}, {"text": "\uf08b", "id": "fa-sign-out"}, {"text": "\uf08c", "id": "fa-linkedin-square"}, {"text": "\uf08d", "id": "fa-thumb-tack"}, {"text": "\uf08e", "id": "fa-external-link"}, {"text": "\uf090", "id": "fa-sign-in"}, {"text": "\uf091", "id": "fa-trophy"}, {"text": "\uf092", "id": "fa-github-square"}, {"text": "\uf093", "id": "fa-upload"}, {"text": "\uf094", "id": "fa-lemon-o"}, {"text": "\uf095", "id": "fa-phone"}, {"text": "\uf096", "id": "fa-square-o"}, {"text": "\uf097", "id": "fa-bookmark-o"}, {"text": "\uf098", "id": "fa-phone-square"}, {"text": "\uf099", "id": "fa-twitter"}, {"text": "\uf09a", "id": "fa-facebook"}, {"text": "\uf09b", "id": "fa-github"}, {"text": "\uf09c", "id": "fa-unlock"}, {"text": "\uf09d", "id": "fa-credit-card"}, {"text": "\uf09e", "id": "fa-rss"}, {"text": "\uf0a0", "id": "fa-hdd-o"}, {"text": "\uf0a1", "id": "fa-bullhorn"}, {"text": "\uf0f3", "id": "fa-bell"}, {"text": "\uf0a3", "id": "fa-certificate"}, {"text": "\uf0a4", "id": "fa-hand-o-right"}, {"text": "\uf0a5", "id": "fa-hand-o-left"}, {"text": "\uf0a6", "id": "fa-hand-o-up"}, {"text": "\uf0a7", "id": "fa-hand-o-down"}, {"text": "\uf0a8", "id": "fa-arrow-circle-left"}, {"text": "\uf0a9", "id": "fa-arrow-circle-right"}, {"text": "\uf0aa", "id": "fa-arrow-circle-up"}, {"text": "\uf0ab", "id": "fa-arrow-circle-down"}, {"text": "\uf0ac", "id": "fa-globe"}, {"text": "\uf0ad", "id": "fa-wrench"}, {"text": "\uf0ae", "id": "fa-tasks"}, {"text": "\uf0b0", "id": "fa-filter"}, {"text": "\uf0b1", "id": "fa-briefcase"}, {"text": "\uf0b2", "id": "fa-arrows-alt"}, {"text": "\uf0c0", "id": "fa-users"}, {"text": "\uf0c1", "id": "fa-link"}, {"text": "\uf0c2", "id": "fa-cloud"}, {"text": "\uf0c3", "id": "fa-flask"}, {"text": "\uf0c4", "id": "fa-scissors"}, {"text": "\uf0c5", "id": "fa-files-o"}, {"text": "\uf0c6", "id": "fa-paperclip"}, {"text": "\uf0c7", "id": "fa-floppy-o"}, {"text": "\uf0c8", "id": "fa-square"}, {"text": "\uf0c9", "id": "fa-bars"}, {"text": "\uf0ca", "id": "fa-list-ul"}, {"text": "\uf0cb", "id": "fa-list-ol"}, {"text": "\uf0cc", "id": "fa-strikethrough"}, {"text": "\uf0cd", "id": "fa-underline"}, {"text": "\uf0ce", "id": "fa-table"}, {"text": "\uf0d0", "id": "fa-magic"}, {"text": "\uf0d1", "id": "fa-truck"}, {"text": "\uf0d2", "id": "fa-pinterest"}, {"text": "\uf0d3", "id": "fa-pinterest-square"}, {"text": "\uf0d4", "id": "fa-google-plus-square"}, {"text": "\uf0d5", "id": "fa-google-plus"}, {"text": "\uf0d6", "id": "fa-money"}, {"text": "\uf0d7", "id": "fa-caret-down"}, {"text": "\uf0d8", "id": "fa-caret-up"}, {"text": "\uf0d9", "id": "fa-caret-left"}, {"text": "\uf0da", "id": "fa-caret-right"}, {"text": "\uf0db", "id": "fa-columns"}, {"text": "\uf0dc", "id": "fa-sort"}, {"text": "\uf0dd", "id": "fa-sort-asc"}, {"text": "\uf0de", "id": "fa-sort-desc"}, {"text": "\uf0e0", "id": "fa-envelope"}, {"text": "\uf0e1", "id": "fa-linkedin"}, {"text": "\uf0e2", "id": "fa-undo"}, {"text": "\uf0e3", "id": "fa-gavel"}, {"text": "\uf0e4", "id": "fa-tachometer"}, {"text": "\uf0e5", "id": "fa-comment-o"}, {"text": "\uf0e6", "id": "fa-comments-o"}, {"text": "\uf0e7", "id": "fa-bolt"}, {"text": "\uf0e8", "id": "fa-sitemap"}, {"text": "\uf0e9", "id": "fa-umbrella"}, {"text": "\uf0ea", "id": "fa-clipboard"}, {"text": "\uf0eb", "id": "fa-lightbulb-o"}, {"text": "\uf0ec", "id": "fa-exchange"}, {"text": "\uf0ed", "id": "fa-cloud-download"}, {"text": "\uf0ee", "id": "fa-cloud-upload"}, {"text": "\uf0f0", "id": "fa-user-md"}, {"text": "\uf0f1", "id": "fa-stethoscope"}, {"text": "\uf0f2", "id": "fa-suitcase"}, {"text": "\uf0a2", "id": "fa-bell-o"}, {"text": "\uf0f4", "id": "fa-coffee"}, {"text": "\uf0f5", "id": "fa-cutlery"}, {"text": "\uf0f6", "id": "fa-file-text-o"}, {"text": "\uf0f7", "id": "fa-building-o"}, {"text": "\uf0f8", "id": "fa-hospital-o"}, {"text": "\uf0f9", "id": "fa-ambulance"}, {"text": "\uf0fa", "id": "fa-medkit"}, {"text": "\uf0fb", "id": "fa-fighter-jet"}, {"text": "\uf0fc", "id": "fa-beer"}, {"text": "\uf0fd", "id": "fa-h-square"}, {"text": "\uf0fe", "id": "fa-plus-square"}, {"text": "\uf100", "id": "fa-angle-double-left"}, {"text": "\uf101", "id": "fa-angle-double-right"}, {"text": "\uf102", "id": "fa-angle-double-up"}, {"text": "\uf103", "id": "fa-angle-double-down"}, {"text": "\uf104", "id": "fa-angle-left"}, {"text": "\uf105", "id": "fa-angle-right"}, {"text": "\uf106", "id": "fa-angle-up"}, {"text": "\uf107", "id": "fa-angle-down"}, {"text": "\uf108", "id": "fa-desktop"}, {"text": "\uf109", "id": "fa-laptop"}, {"text": "\uf10a", "id": "fa-tablet"}, {"text": "\uf10b", "id": "fa-mobile"}, {"text": "\uf10c", "id": "fa-circle-o"}, {"text": "\uf10d", "id": "fa-quote-left"}, {"text": "\uf10e", "id": "fa-quote-right"}, {"text": "\uf110", "id": "fa-spinner"}, {"text": "\uf111", "id": "fa-circle"}, {"text": "\uf112", "id": "fa-reply"}, {"text": "\uf113", "id": "fa-github-alt"}, {"text": "\uf114", "id": "fa-folder-o"}, {"text": "\uf115", "id": "fa-folder-open-o"}, {"text": "\uf118", "id": "fa-smile-o"}, {"text": "\uf119", "id": "fa-frown-o"}, {"text": "\uf11a", "id": "fa-meh-o"}, {"text": "\uf11b", "id": "fa-gamepad"}, {"text": "\uf11c", "id": "fa-keyboard-o"}, {"text": "\uf11d", "id": "fa-flag-o"}, {"text": "\uf11e", "id": "fa-flag-checkered"}, {"text": "\uf120", "id": "fa-terminal"}, {"text": "\uf121", "id": "fa-code"}, {"text": "\uf122", "id": "fa-reply-all"}, {"text": "\uf122", "id": "fa-mail-reply-all"}, {"text": "\uf123", "id": "fa-star-half-o"}, {"text": "\uf124", "id": "fa-location-arrow"}, {"text": "\uf125", "id": "fa-crop"}, {"text": "\uf126", "id": "fa-code-fork"}, {"text": "\uf127", "id": "fa-chain-broken"}, {"text": "\uf128", "id": "fa-question"}, {"text": "\uf129", "id": "fa-info"}, {"text": "\uf12a", "id": "fa-exclamation"}, {"text": "\uf12b", "id": "fa-superscript"}, {"text": "\uf12c", "id": "fa-subscript"}, {"text": "\uf12d", "id": "fa-eraser"}, {"text": "\uf12e", "id": "fa-puzzle-piece"}, {"text": "\uf130", "id": "fa-microphone"}, {"text": "\uf131", "id": "fa-microphone-slash"}, {"text": "\uf132", "id": "fa-shield"}, {"text": "\uf133", "id": "fa-calendar-o"}, {"text": "\uf134", "id": "fa-fire-extinguisher"}, {"text": "\uf135", "id": "fa-rocket"}, {"text": "\uf136", "id": "fa-maxcdn"}, {"text": "\uf137", "id": "fa-chevron-circle-left"}, {"text": "\uf138", "id": "fa-chevron-circle-right"}, {"text": "\uf139", "id": "fa-chevron-circle-up"}, {"text": "\uf13a", "id": "fa-chevron-circle-down"}, {"text": "\uf13b", "id": "fa-html5"}, {"text": "\uf13c", "id": "fa-css3"}, {"text": "\uf13d", "id": "fa-anchor"}, {"text": "\uf13e", "id": "fa-unlock-alt"}, {"text": "\uf140", "id": "fa-bullseye"}, {"text": "\uf141", "id": "fa-ellipsis-h"}, {"text": "\uf142", "id": "fa-ellipsis-v"}, {"text": "\uf143", "id": "fa-rss-square"}, {"text": "\uf144", "id": "fa-play-circle"}, {"text": "\uf145", "id": "fa-ticket"}, {"text": "\uf146", "id": "fa-minus-square"}, {"text": "\uf147", "id": "fa-minus-square-o"}, {"text": "\uf148", "id": "fa-level-up"}, {"text": "\uf149", "id": "fa-level-down"}, {"text": "\uf14a", "id": "fa-check-square"}, {"text": "\uf14b", "id": "fa-pencil-square"}, {"text": "\uf14c", "id": "fa-external-link-square"}, {"text": "\uf14d", "id": "fa-share-square"}, {"text": "\uf14e", "id": "fa-compass"}, {"text": "\uf150", "id": "fa-caret-square-o-down"}, {"text": "\uf151", "id": "fa-caret-square-o-up"}, {"text": "\uf152", "id": "fa-caret-square-o-right"}, {"text": "\uf153", "id": "fa-eur"}, {"text": "\uf154", "id": "fa-gbp"}, {"text": "\uf155", "id": "fa-usd"}, {"text": "\uf156", "id": "fa-inr"}, {"text": "\uf157", "id": "fa-jpy"}, {"text": "\uf158", "id": "fa-rub"}, {"text": "\uf159", "id": "fa-krw"}, {"text": "\uf15a", "id": "fa-btc"}, {"text": "\uf15b", "id": "fa-file"}, {"text": "\uf15c", "id": "fa-file-text"}, {"text": "\uf15d", "id": "fa-sort-alpha-asc"}, {"text": "\uf15e", "id": "fa-sort-alpha-desc"}, {"text": "\uf160", "id": "fa-sort-amount-asc"}, {"text": "\uf161", "id": "fa-sort-amount-desc"}, {"text": "\uf162", "id": "fa-sort-numeric-asc"}, {"text": "\uf163", "id": "fa-sort-numeric-desc"}, {"text": "\uf164", "id": "fa-thumbs-up"}, {"text": "\uf165", "id": "fa-thumbs-down"}, {"text": "\uf166", "id": "fa-youtube-square"}, {"text": "\uf167", "id": "fa-youtube"}, {"text": "\uf168", "id": "fa-xing"}, {"text": "\uf169", "id": "fa-xing-square"}, {"text": "\uf16a", "id": "fa-youtube-play"}, {"text": "\uf16b", "id": "fa-dropbox"}, {"text": "\uf16c", "id": "fa-stack-overflow"}, {"text": "\uf16d", "id": "fa-instagram"}, {"text": "\uf16e", "id": "fa-flickr"}, {"text": "\uf170", "id": "fa-adn"}, {"text": "\uf171", "id": "fa-bitbucket"}, {"text": "\uf172", "id": "fa-bitbucket-square"}, {"text": "\uf173", "id": "fa-tumblr"}, {"text": "\uf174", "id": "fa-tumblr-square"}, {"text": "\uf175", "id": "fa-long-arrow-down"}, {"text": "\uf176", "id": "fa-long-arrow-up"}, {"text": "\uf177", "id": "fa-long-arrow-left"}, {"text": "\uf178", "id": "fa-long-arrow-right"}, {"text": "\uf179", "id": "fa-apple"}, {"text": "\uf17a", "id": "fa-windows"}, {"text": "\uf17b", "id": "fa-android"}, {"text": "\uf17c", "id": "fa-linux"}, {"text": "\uf17d", "id": "fa-dribbble"}, {"text": "\uf17e", "id": "fa-skype"}, {"text": "\uf180", "id": "fa-foursquare"}, {"text": "\uf181", "id": "fa-trello"}, {"text": "\uf182", "id": "fa-female"}, {"text": "\uf183", "id": "fa-male"}, {"text": "\uf184", "id": "fa-gittip"}, {"text": "\uf185", "id": "fa-sun-o"}, {"text": "\uf186", "id": "fa-moon-o"}, {"text": "\uf187", "id": "fa-archive"}, {"text": "\uf188", "id": "fa-bug"}, {"text": "\uf189", "id": "fa-vk"}, {"text": "\uf18a", "id": "fa-weibo"}, {"text": "\uf18b", "id": "fa-renren"}, {"text": "\uf18c", "id": "fa-pagelines"}, {"text": "\uf18d", "id": "fa-stack-exchange"}, {"text": "\uf18e", "id": "fa-arrow-circle-o-right"}, {"text": "\uf190", "id": "fa-arrow-circle-o-left"}, {"text": "\uf191", "id": "fa-caret-square-o-left"}, {"text": "\uf192", "id": "fa-dot-circle-o"}, {"text": "\uf193", "id": "fa-wheelchair"}, {"text": "\uf194", "id": "fa-vimeo-square"}, {"text": "\uf195", "id": "fa-try"}, {"text": "\uf196", "id": "fa-plus-square-o"}], - init: function (editor, element) { - this._super(editor); - this.element = element; - }, /** * Initializes select2: in Chrome and Safari, - - + -
    - Browse existing images -

    Image URL

    - + + - -
    - -
    - - -
    - +
    + + + + + +
    +
    + +
    +
    + + + diff --git a/addons/website/static/src/xml/website.snippets.xml b/addons/website/static/src/xml/website.snippets.xml index c5cf94d4791..b1853f366b0 100644 --- a/addons/website/static/src/xml/website.snippets.xml +++ b/addons/website/static/src/xml/website.snippets.xml @@ -39,8 +39,8 @@
    +
    Auto Resize
    Resize
    -
    x
    diff --git a/addons/website/tests/test_requests.py b/addons/website/tests/test_requests.py index 2a22ae04445..127aea274d5 100644 --- a/addons/website/tests/test_requests.py +++ b/addons/website/tests/test_requests.py @@ -6,6 +6,7 @@ import werkzeug.urls import lxml.html +import openerp from openerp import tools import cases @@ -43,15 +44,23 @@ class CrawlSuite(unittest2.TestSuite): def __init__(self, user=None, password=None): super(CrawlSuite, self).__init__() - self.opener = urllib2.OpenerDirector() - self.opener.add_handler(urllib2.UnknownHandler()) - self.opener.add_handler(urllib2.HTTPHandler()) - self.opener.add_handler(urllib2.HTTPSHandler()) - self.opener.add_handler(urllib2.HTTPCookieProcessor()) - self.opener.add_handler(RedirectHandler()) + registry = openerp.registry(tools.config['db_name']) + try: + # switch registry to test mode, so that requests can be made + registry.enter_test_mode() - self._authenticate(user, password) - self.user = user + self.opener = urllib2.OpenerDirector() + self.opener.add_handler(urllib2.UnknownHandler()) + self.opener.add_handler(urllib2.HTTPHandler()) + self.opener.add_handler(urllib2.HTTPSHandler()) + self.opener.add_handler(urllib2.HTTPCookieProcessor()) + self.opener.add_handler(RedirectHandler()) + + self._authenticate(user, password) + self.user = user + + finally: + registry.leave_test_mode() def _request(self, path): return self.opener.open(urlparse.urlunsplit([ @@ -79,37 +88,45 @@ class CrawlSuite(unittest2.TestSuite): assert auth.getcode() < 400, "Auth failure %d" % auth.getcode() def _wrapped_run(self, result, debug=False): - paths = [URL('/'), URL('/sitemap')] - seen = set(paths) + registry = openerp.registry(tools.config['db_name']) + try: + # switch registry to test mode, so that requests can be made + registry.enter_test_mode() - while paths: - url = paths.pop(0) - r = self._request(url.url) - url.to_case(self.user, r).run(result) + paths = [URL('/'), URL('/sitemap')] + seen = set(paths) - if r.info().gettype() != 'text/html': - continue + while paths: + url = paths.pop(0) + r = self._request(url.url) + url.to_case(self.user, r).run(result) - doc = lxml.html.fromstring(r.read()) - for link in doc.xpath('//a[@href]'): - href = link.get('href') - - # avoid repeats, even for links we won't crawl no need to - # bother splitting them if we've already ignored them - # previously - if href in seen: continue - seen.add(href) - - parts = urlparse.urlsplit(href) - - if parts.netloc or \ - not parts.path.startswith('/') or \ - parts.path == '/web' or\ - parts.path.startswith('/web/') or \ - (parts.scheme and parts.scheme not in ('http', 'https')): + if r.info().gettype() != 'text/html': continue - paths.append(URL(href, url.url)) + doc = lxml.html.fromstring(r.read()) + for link in doc.xpath('//a[@href]'): + href = link.get('href') + + # avoid repeats, even for links we won't crawl no need to + # bother splitting them if we've already ignored them + # previously + if href in seen: continue + seen.add(href) + + parts = urlparse.urlsplit(href) + + if parts.netloc or \ + not parts.path.startswith('/') or \ + parts.path == '/web' or\ + parts.path.startswith('/web/') or \ + (parts.scheme and parts.scheme not in ('http', 'https')): + continue + + paths.append(URL(href, url.url)) + + finally: + registry.leave_test_mode() class URL(object): def __init__(self, url, source=None): diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 3e27ffb227f..8ade1725e4e 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -39,8 +39,8 @@ - - + + @@ -522,7 +522,7 @@

    - + Contact Us Now @@ -942,6 +942,11 @@ data-selector-children=".content">
    +
    +
    +
    +
    +
  • Change...
  • +
    + + + diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 0cfba4d14ed..a9a9173099a 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -284,6 +284,8 @@ + + diff --git a/addons/website_blog/__openerp__.py b/addons/website_blog/__openerp__.py index 97c163945af..831c180d51f 100644 --- a/addons/website_blog/__openerp__.py +++ b/addons/website_blog/__openerp__.py @@ -30,7 +30,7 @@ OpenERP Blog """, 'author': 'OpenERP SA', - 'depends': ['knowledge', 'website_mail'], + 'depends': ['knowledge', 'website_mail', 'website_partner'], 'data': [ 'data/website_blog_data.xml', 'views/website_blog_views.xml', diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py index 5cb678b5475..e2eac59678e 100644 --- a/addons/website_blog/controllers/main.py +++ b/addons/website_blog/controllers/main.py @@ -1,23 +1,4 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2013-Today OpenERP SA (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## import datetime import werkzeug @@ -29,6 +10,7 @@ from openerp.addons.website.models.website import slug from openerp.osv.orm import browse_record from openerp.tools.translate import _ from openerp import SUPERUSER_ID +from openerp.tools import html2plaintext class QueryURL(object): @@ -62,12 +44,13 @@ class QueryURL(object): class WebsiteBlog(http.Controller): - _blog_post_per_page = 6 - _post_comment_per_page = 6 + _blog_post_per_page = 20 + _post_comment_per_page = 10 def nav_list(self): blog_post_obj = request.registry['blog.post'] - groups = blog_post_obj.read_group(request.cr, request.uid, [], ['name', 'create_date'], + groups = blog_post_obj.read_group( + request.cr, request.uid, [], ['name', 'create_date'], groupby="create_date", orderby="create_date asc", context=request.context) for group in groups: begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date() @@ -108,35 +91,27 @@ class WebsiteBlog(http.Controller): def blog(self, blog=None, tag=None, page=1, **opt): """ Prepare all values to display the blog. - :param blog: blog currently browsed. - :param tag: tag that is currently used to filter blog posts - :param integer page: current page of the pager. Can be the blog or - post pager. - :param date: date currently used to filter blog posts (dateBegin_dateEnd) - :return dict values: values for the templates, containing - - 'blog_posts': list of browse records that are the posts to display - in a given blog, if not blog_post_id - - 'blog': browse of the current blog, if blog_id - - 'blogs': list of browse records of blogs - - 'pager': the pager to display posts pager in a blog - - 'tag': current tag, if tag_id + - 'blog': current blog + - 'blogs': all blogs for navigation + - 'pager': pager of posts + - 'tag': current tag + - 'tags': all tags, for navigation - 'nav_list': a dict [year][month] for archives navigation + - 'date': date_begin optional parameter, used in archives navigation + - 'blog_url': help object to create URLs """ date_begin, date_end = opt.get('date_begin'), opt.get('date_end') cr, uid, context = request.cr, request.uid, request.context blog_post_obj = request.registry['blog.post'] - blog_posts = None - blog_obj = request.registry['blog.blog'] blog_ids = blog_obj.search(cr, uid, [], order="create_date asc", context=context) blogs = blog_obj.browse(cr, uid, blog_ids, context=context) domain = [] - if blog: domain += [('blog_id', '=', blog.id)] if tag: @@ -176,35 +151,29 @@ class WebsiteBlog(http.Controller): 'post_url': post_url, 'date': date_begin, } - return request.website.render("website_blog.blog_post_short", values) + response = request.website.render("website_blog.blog_post_short", values) + return response @http.route([ - '/blogpost/', + '/blog//post/', ], type='http', auth="public", website=True, multilang=True) - def blog_post(self, blog_post, tag_id=None, page=1, enable_editor=None, **post): + def blog_post(self, blog, blog_post, tag_id=None, page=1, enable_editor=None, **post): """ Prepare all values to display the blog. - :param blog_post: blog post currently browsed. If not set, the user is - browsing the blog and a post pager is calculated. - If set the user is reading the blog post and a - comments pager is calculated. - :param blog: blog currently browsed. - :param tag: tag that is currently used to filter blog posts - :param integer page: current page of the pager. Can be the blog or - post pager. - :param date: date currently used to filter blog posts (dateBegin_dateEnd) - - - 'enable_editor': editor control - :return dict values: values for the templates, containing - - 'blog_post': browse of the current post, if blog_post_id - - 'blog': browse of the current blog, if blog_id + - 'blog_post': browse of the current post + - 'blog': browse of the current blog - 'blogs': list of browse records of blogs - - 'pager': the pager to display comments pager in a blog post - - 'tag': current tag, if tag_id + - 'tag': current tag, if tag_id in parameters + - 'tags': all tags, for tag-based navigation + - 'pager': a pager on the comments - 'nav_list': a dict [year][month] for archives navigation + - 'next_post': next blog post, to direct the user towards the next interesting post """ + cr, uid, context = request.cr, request.uid, request.context + tag_obj = request.registry['blog.tag'] + blog_post_obj = request.registry['blog.post'] date_begin, date_end = post.get('date_begin'), post.get('date_end') pager_url = "/blogpost/%s" % blog_post.id @@ -226,62 +195,125 @@ class WebsiteBlog(http.Controller): post_url = QueryURL('', ['blogpost'], blogpost=blog_post, tag_id=tag_id, date_begin=date_begin, date_end=date_end) blog_url = QueryURL('', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag, date_begin=date_begin, date_end=date_end) - cr, uid, context = request.cr, request.uid, request.context - blog_obj = request.registry['blog.blog'] - blog_ids = blog_obj.search(cr, uid, [], context=context) - blogs = blog_obj.browse(cr, uid, blog_ids, context=context) + if not blog_post.blog_id.id == blog.id: + return request.redirect("/blog/%s/post/%s" % (slug(blog_post.blog_id), slug(blog_post))) - tag_obj = request.registry['blog.tag'] - tag_ids = tag_obj.search(cr, uid, [], context=context) - tags = tag_obj.browse(cr, uid, tag_ids, context=context) + tags = tag_obj.browse(cr, uid, tag_obj.search(cr, uid, [], context=context), context=context) + + # Find next Post + visited_blogs = request.httprequest.cookies.get('visited_blogs') or '' + visited_ids = filter(None, visited_blogs.split(',')) + visited_ids = map(lambda x: int(x), visited_ids) + if blog_post.id not in visited_ids: + visited_ids.append(blog_post.id) + next_post_id = blog_post_obj.search(cr, uid, [ + ('id', 'not in', visited_ids), + ], order='ranking desc', limit=1, context=context) + if not next_post_id: + next_post_id = blog_post_obj.search(cr, uid, [('id', '!=', blog.id)], order='ranking desc', limit=1, context=context) + next_post = next_post_id and blog_post_obj.browse(cr, uid, next_post_id[0], context=context) or False values = { - 'blog': blog_post.blog_id, - 'blogs': blogs, 'tags': tags, 'tag': tag, + 'blog': blog, 'blog_post': blog_post, 'main_object': blog_post, - 'pager': pager, 'nav_list': self.nav_list(), 'enable_editor': enable_editor, + 'next_post': next_post, 'date': date_begin, 'post_url': post_url, 'blog_url': blog_url, + 'pager': pager, } - return request.website.render("website_blog.blog_post_complete", values) + response = request.website.render("website_blog.blog_post_complete", values) + response.set_cookie('visited_blogs', ','.join(map(str, visited_ids))) + + request.session[request.session_id] = request.session.get(request.session_id, []) + if not (blog_post.id in request.session[request.session_id]): + request.session[request.session_id].append(blog_post.id) + # Increase counter + blog_post_obj.write(cr, SUPERUSER_ID, [blog_post.id], { + 'visits': blog_post.visits+1, + },context=context) + return response + + def _blog_post_message(self, user, blog_post_id=0, **post): + cr, uid, context = request.cr, request.uid, request.context + blog_post = request.registry['blog.post'] + partner_obj = request.registry['res.partner'] + thread_obj = request.registry['mail.thread'] + website = request.registry['website'] + + public_id = website.get_public_user(cr, uid, context) + if uid != public_id: + partner_ids = [user.partner_id.id] + else: + partner_ids = blog_post._find_partner_from_emails( + cr, SUPERUSER_ID, 0, [post.get('email')], context=context) + if not partner_ids or not partner_ids[0]: + partner_ids = [partner_obj.create(cr, SUPERUSER_ID, {'name': post.get('name'), 'email': post.get('email')}, context=context)] + + message_id = blog_post.message_post( + cr, SUPERUSER_ID, int(blog_post_id), + body=post.get('comment'), + type='comment', + subtype='mt_comment', + author_id=partner_ids[0], + path=post.get('path', False), + context=dict(context, mail_create_nosubcribe=True)) + return message_id @http.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'], website=True) def blog_post_comment(self, blog_post_id=0, **post): cr, uid, context = request.cr, request.uid, request.context if post.get('comment'): - user = request.registry['res.users'].browse(cr, SUPERUSER_ID, uid, context=context) - group_ids = user.groups_id - group_id = request.registry["ir.model.data"].get_object_reference(cr, uid, 'website_mail', 'group_comment')[1] - if group_id in [group.id for group in group_ids]: - blog_post = request.registry['blog.post'] - blog_post.check_access_rights(cr, uid, 'read') - blog_post.message_post( - cr, SUPERUSER_ID, int(blog_post_id), - body=post.get('comment'), - type='comment', - subtype='mt_comment', - author_id=user.partner_id.id, - context=dict(context, mail_create_nosubcribe=True)) + user = request.registry['res.users'].browse(cr, uid, uid, context=context) + blog_post = request.registry['blog.post'] + blog_post.check_access_rights(cr, uid, 'read') + self._blog_post_message(user, blog_post_id, **post) return werkzeug.utils.redirect(request.httprequest.referrer + "#comments") + def _get_discussion_detail(self, ids, publish=False, **post): + cr, uid, context = request.cr, request.uid, request.context + values = [] + mail_obj = request.registry.get('mail.message') + for message in mail_obj.browse(cr, SUPERUSER_ID, ids, context=context): + values.append({ + "id": message.id, + "author_name": message.author_id.name, + "author_image": message.author_id.image and \ + ("data:image/png;base64,%s" % message.author_id.image) or \ + '/website_blog/static/src/img/anonymous.png', + "date": message.date, + 'body': html2plaintext(message.body), + 'website_published' : message.website_published, + 'publish' : publish, + }) + return values + + @http.route(['/blogpost/post_discussion'], type='json', auth="public", website=True) + def post_discussion(self, blog_post_id=0, **post): + cr, uid, context = request.cr, request.uid, request.context + publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher') + user = request.registry['res.users'].browse(cr, uid, uid, context=context) + id = self._blog_post_message(user, blog_post_id, **post) + return self._get_discussion_detail([id], publish, **post) + @http.route('/blogpost/new', type='http', auth="public", website=True, multilang=True) def blog_post_create(self, blog_id, **post): cr, uid, context = request.cr, request.uid, request.context create_context = dict(context, mail_create_nosubscribe=True) - new_blog_post_id = request.registry['blog.post'].create( - request.cr, request.uid, { - 'blog_id': blog_id, - 'name': _("Blog Post Title"), - 'content': '', - 'website_published': False, - }, context=create_context) - return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id) + new_blog_post_id = request.registry['blog.post'].create(cr, uid, { + 'blog_id': blog_id, + 'name': _("Blog Post Title"), + 'subtitle': _("Subtitle"), + 'content': '', + 'website_published': False, + }, context=create_context) + new_blog_post = request.registry['blog.post'].browse(cr, uid, new_blog_post_id, context=context) + return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post))) @http.route('/blogpost/duplicate', type='http', auth="public", website=True) def blog_post_copy(self, blog_post_id, **post): @@ -293,5 +325,31 @@ class WebsiteBlog(http.Controller): """ cr, uid, context = request.cr, request.uid, request.context create_context = dict(context, mail_create_nosubscribe=True) - new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context) - return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id) + nid = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context) + new_blog_post = request.registry['blog.post'].browse(cr, uid, nid, context=context) + post = request.registry['blog.post'].browse(cr, uid, nid, context) + return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(post.blog_id), slug(new_blog_post))) + + @http.route('/blogpost/get_discussion/', type='json', auth="public", website=True) + def discussion(self, post_id=0, path=None, count=False, **post): + cr, uid, context = request.cr, request.uid, request.context + mail_obj = request.registry.get('mail.message') + domain = [('res_id', '=', int(post_id)), ('model', '=', 'blog.post'), ('path', '=', path)] + #check current user belongs to website publisher group + publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher') + if not publish: + domain.append(('website_published', '=', True)) + ids = mail_obj.search(cr, SUPERUSER_ID, domain, count=count) + if count: + return ids + return self._get_discussion_detail(ids, publish, **post) + + @http.route('/blogpost/change_background', type='json', auth="public", website=True) + def change_bg(self, post_id=0, image=None, **post): + if not post_id: + return False + return request.registry['blog.post'].write(request.cr, request.uid, [int(post_id)], {'background_image': image}, request.context) + + @http.route('/blog/get_user/', type='json', auth="public", website=True) + def get_user(self, **post): + return [False if request.session.uid else True] diff --git a/addons/website_blog/data/website_blog_data.xml b/addons/website_blog/data/website_blog_data.xml index a5a3aa3d8c9..efc25264633 100644 --- a/addons/website_blog/data/website_blog_data.xml +++ b/addons/website_blog/data/website_blog_data.xml @@ -2,7 +2,8 @@ - News + Our News + Sharing our evolution with passion Presentation of new OpenERP features diff --git a/addons/website_blog/data/website_blog_demo.xml b/addons/website_blog/data/website_blog_demo.xml index 913c2ddc9b1..d6827220414 100644 --- a/addons/website_blog/data/website_blog_demo.xml +++ b/addons/website_blog/data/website_blog_demo.xml @@ -8,329 +8,199 @@ functional - technical - - website - - pos - - OpenERP v8 New Features + The Future of Emails + Ideas behing the OpenERP communication tools. - OpenERP, Point of Sale, Hardware, Interface, Payment Terminal, Store - Open source Point of Sale with no installation required that runs online and offline. + OpenERP, email + The Future of Emails + /website_blog/static/src/img/post1.jpg -
    -
    -
    - -
    -
    -

    - OpenERP's Point of Sale introduces a super clean - interface with no installation required that runs - online and offline on modern hardwares. -

    - It's full integration with the company inventory - and accounting, gives you real time statistics - without the hassle of integrating several applications. -

    -
    -
    -
    +
    + +

    + Emails are broken. +

    + Emails make me waste my time. But I need them. + Given the importance that emails have in our lives, + it's incredible it's still one of the only software + areas that did not evolve in the past 20 years! +

    + Reading my inbox is the most unproductive task I do + on a daily basis. I have to spend one full hour a + day to process my emails. All the junk flows in the + same inbox; spams, information that doesn't matter, + quoted answers of quoted answers, etc. At the end + of the hour, only 10 emails actually requested an + answer from me. With a good tool, I could have done + my job in 10 minutes! +

    -
    -
    -
    -
    -

    - Linked with Project Management -

    -

    Infinitely flexible. Incredibly easy to use.

    -
    -
    -

    - OpenERP's collaborative and realtime project - management helps your team get work done. Keep - track of everything, from the big picture to the - minute details, from the customer contract to the - billing. -

    - Organize projects around your own processes. Work - on tasks and issues using the kanban view, schedule - tasks using the gantt chart and control deadlines - in the calendar view. Every project may have it's - own stages allowing teams to optimize their job. -

    -
    -
    -
    +
    +

    + At OpenERP, we build tools to bring productivity to + enterprises. As emails and information flows are one of + the biggest wastes of time in companies, we have to fix + this. +

    + To disrupt emails, you need more than just another user + interface. We need to rethink the whole communication flow. +

    +

    The Communication Mechanism of OpenERP

    +

    + Here are the ideas behing the OpenERP communication tools: +

    +
      +
    • + Get Things Done: your inbox is a + todo list. You should be able to process (not only + read) the inbox and easily mark messages for future + actions. Every inbox should be empty after having + been processed; no more overload of information. + +
    • + Keep control of what you want to receive or don't want + to receive. People should never receive spam. You + should follow/unfollow any kind of information in one + click. +
    • + Productivity is key: our smart user + interface does not require you to click on every mail + to read a thread. Reading a full thread, replying, + attaching documents is super fast. + +
    • + A mix of push & pull: Today, people + are victims of what others decide to push to them. + OpenERP differentiates: +
        +
      • + Messages "for information": + you can pull them when you need some specific + information; they are not required to be read + every day.You receive only what you decided + to follow.This accounts for 90% of your daily + emails.Use the "Inbox" menu for these. +
      • + Messages "for action": they + require your immediate attention and you need + to process them all. This accounts for 10% + of your daily emails. Use the "To: me" menu + for these. +
      • +
      +
    • + Focus on the Content: Everything is + stripped to emphasize on the real message. No more + welcome introductions, greetings, signatures and legal + notes.We standardize the layout of each message. + (signatures are on the profile of a contact, not in + every message) +
    • + Folders and mailing lists are great tools but too + complex in traditional email clients. In OpenERP, a + group of contacts that share a discussion can be + created with one click. Every group should have it's + own email address. +
    • +
    -
    -
    -
    -
    -

    Work with the hardware you already have...

    -
    -
    - -
    -
    -

    - No installation required -

    -

    - OpenERP's Point of Sale introduces a super clean - interface with no installation required that runs - online and offline on modern hardware. Laptops, - tablets, industrial POS, it runs on everything. -

    -

    - Get more information » -

    -
    -
    -
    -
    - ]]> - New Hardware Integration + Integrating your CMS and E-Commerce + Building your company's website and selling your products online easy. - - - -
    -
    -
    - -
    -
    -

    - New Features Launched -

    -

    - OpenERP's Point of Sale introduces a super clean - interface with no installation required that runs - online and offline on modern hardware. Laptops, - tablets, industrial POS, it runs on everything. -

    -
    -
    -
    -
    -
    -
    -
    -
    -

    Our Offers

    -
    - -
    -
    - -
    -

    Beginner

    -

    - Starter package -

    -
    -
    -

    $450.00

    -
    per month
    -
    - - -
      -
    • Battery: 8 hours
    • -
    • Screen: 2.5 inch
    • -
    • Weight: 1.1 ounces
    • -
    • No support
    • -
    - -
    -
    -
    -
    - -
    -

    Professional

    -

    - Enterprise package -

    -
    -
    -

    $590.00

    -
    per month
    -
    - - -
      -
    • Battery: 12 hours
    • -
    • Screen: 2.8 inch
    • -
    • Weight: 1.2 ounces
    • -
    • Limited support
    • -
    - -
    -
    -
    -
    - -
    -

    Expert

    -

    - The top of the top -

    -
    -
    -

    $890.00

    -
    per month
    -
    - - -
      -
    • Battery: 20 hours
    • -
    • Screen: 2.8 inch
    • -
    • Weight: 1.2 ounces
    • -
    • Unlimited support
    • -
    - -
    - -
    -
    -
    -
    - - -]]> -
    -
    - - - Touchscreen Point of Sale for 6.1 - - - Point of Sale, Hardware, Interface, Payment Terminal, Store - Point of Sale with no installation required that runs online and offline. - -The brand new OpenERP touchscreen point of sale is available with 6.1 which allows you -to manage your shop sales very easily. It's fully web based so that you don't -have to install or deploy any software and all the sales shops can be easily -consolidated. It works in connected and disconnected modes so that you can -continue to sell even if you lose your internet connection.

    - -

    Here's a summary of its main features and benefits:

    -
      -
    • 100% WEB based
    • -
    • available for any touchscreen device (ipod, ipad, any tablet)mobile (with portable devices)
    • -
    • no installation required
    • -
    • no synchronization needed, completely integrated
    • -
    • continue working even when your connection is down or if you close your browser, data won't be lost
    • -
    • fully web based with a clean interface smart interface
    • -
    -

    You have different options to select your products. You can do it through the -barcode reader, just browse through the categories you have put in place (ie. -drinks, snacks, meals, etc.), or text search in case neither of the other -options work for you. For example, if you need to use the POS for your restaurant, -your employees can record multiple tickets at the same time without having to wait -to process one transaction at a time. In addition, you can facilitate payments, -the application allows multiple payment methods.

    -

    The POS application is so simple and accessible to use that your shop or -restaurant will never need any other tool to manage orders. Due to its smart -and user-friendly interface you don't need any training to learn how to use it. -Think of it as an out-of-the-box solution to boost your business' productivity. -

    -]]> -
    -
    - - - Announcing a New Partnership - - - OpenERP, Partnership, News, Accounting - Our company partners with OpenERP to develop accounting best practices. - -
    -
    -
    - -
    -
    -

    - We are proud to announce a new partnership with - the company OpenERP. Their open source application suite - will allow us to reach new markets, specifically in - the accounting area. -

    - The full integration with the company inventory - and accounting, will give our customers real time statistics - without the hassle of integrating several applications. -

    -
    -
    + + /website_blog/static/src/img/post2.jpg + + +
    + +
    +
    +

    + New Features Launched +

    +

    + To add to an already comprehensive set of OpenERP + features, a website content management system (CMS + or WMS) has been developed and a beta release is + available from today, 31st January 2014. +

    -
    -
    -
    -
    -

    - OpenERP Project Management -

    -

    Infinitely flexible. Incredibly easy to use.

    -
    -
    -

    - OpenERP's collaborative and realtime project - management helps your team get work done. Keep - track of everything, from the big picture to the - minute details, from the customer contract to the - billing. -

    - Organize projects around your own processes. Work - on tasks and issues using the kanban view, schedule - tasks using the gantt chart and control deadlines - in the calendar view. Every project may have it's - own stages allowing teams to optimize their job. -

    -
    -
    -
    +
    +

    + OpenERP claims to be 'the Open Source software that makes + building your company's website and selling your products + online easy'. So how true is this statement? +

    + "OpenERP's latest launch will allow a business to go from + zero to trading online quicker than ever before,” Stuart + Mackintosh, MD of Open Source specialist and OpenERP + integration partner, OpusVL, explains. “The investment + required to have a fully automated business system is + dramatically reduced, enabling the small and medium + enterprise to compete at a level of functionality and + performance previously reserved for the big IT investors." +

    +
    +

    + "Finally, the leading edge is being brought to the masses. + It will now be the turn of the big players to catch up to + the superior technologies of the SME." +

    +
    +

    + "This is another clever and highly disruptive move by + OpenERP,which will force other technology providers to + take another look at the value they are providing to ensure + that their 'solutions' can still compete." +

    + "OpenERP now competes on many fronts, with no real + competition out there to knock them off the top spot. + With the launch of their integrated CMS and Ecommerce + systems,it only elevates their position as one of the leading + lights in the open source revolution. It will be at least 5 + years before another ERP or CMS provider will be able to + compete at this level due to the technology currently + employed by most industry providers." +

    +

    Adding to industry leading technology

    +

    + Like many modern website editors, with OpenERP you can edit + content in-line, enabling you to see exactly what you are + changing and ensure your changes suit the context. +

    + However, unlike other web content management systems, it + fully integrates into the back-end database. This means + that when you edit a product description, image or price, + it updates the product database in real time, providing a + true self-service window into the business. +

    + This provides a single source of data for your company and + removes the need to create offline synchronisation between + website and product database. +

    + As it comes, there is a default website based on Bootstrap + 3, the latest industry standard for rapid development of + multi-device websites backed by Twitter, so can be directly + integrated with many web tools and works across all devices + by default. +

    ]]> - - diff --git a/addons/website_blog/doc/blog_blog.rst b/addons/website_blog/doc/blog_blog.rst new file mode 100644 index 00000000000..8c5f80ab8e4 --- /dev/null +++ b/addons/website_blog/doc/blog_blog.rst @@ -0,0 +1,20 @@ +_blog_blog: + +blog.blog +========= +In ``blog.blog``, added field ``subtitle`` which Indicates the subtitle of blogs. + - ``subtitle``: fields.char('Blog Subtitle') + +mail.message +============ +In ``mail.message``, added field ``discussion`` which Indicates the unique identification +of paragraph on blog post. + - ``discussion``: fields.char('Discussion Unique Name') + +blog.post +========= +Fields +++++++ + - ``sub_title`` : contains the subtitle of every blog post. + - ``visits`` : Indicates the number of visits on evry blog post. + - ``ranking`` : Indicates the ranking on every blog post. diff --git a/addons/website_blog/doc/changelog.rst b/addons/website_blog/doc/changelog.rst index 8b6131b5806..42f2fd7e170 100644 --- a/addons/website_blog/doc/changelog.rst +++ b/addons/website_blog/doc/changelog.rst @@ -7,3 +7,29 @@ Changelog ---------------- - created ``website_blog`` menu, build on defunct document_page module. + - added new feature ``Inline Discussion`` , that will allow a user to comment + on every paragraph on blog post + - added new feature ``Select to Tweet``, that will alllow a user tweet a selected + text from blog to post , directly on twitter. + + + +WebsiteBlog(controller) +======================= +Methods ++++++++ + - ``blog`` : remove routing related to date. + - ``blog_post`` : updated with , suggestion of next post to the user based on + cookie and number of views. + - ``discussion`` : added method , contains a detail of discussion on every paragraph, + if count is true it only return len of ids else return full detail. + def discussion(self, post_id=0, discussion=None, count=False, **post) + - ``post_discussion`` : added methodt, that allow to post discussion on any paragraph. + def post_discussion(self, blog_post_id=0, **post) + - ``change_bg`` : added method allow a user to change background image on blog + post from front-end. + def change_bg(self, post_id=0, image=None, **post) + - ``get_user`` : added method , that will return True if user is public else False. + def get_user(self, **post): + return [False if request.session.uid else True] + diff --git a/addons/website_blog/doc/controller.rst b/addons/website_blog/doc/controller.rst new file mode 100644 index 00000000000..727368aab8c --- /dev/null +++ b/addons/website_blog/doc/controller.rst @@ -0,0 +1,21 @@ +.. _controller: + +WebsiteBlog(controller) +======================= +Methods ++++++++ + - ``blog`` : remove routing related to date. + - ``blog_post`` : updated with , suggestion of next post to the user based on + cookie and number of views. + - ``discussion`` : added method , contains a detail of discussion on every paragraph, + if count is true it only return len of ids else return full detail. + def discussion(self, post_id=0, discussion=None, count=False, **post) + - ``post_discussion`` : added methodt, that allow to post discussion on any paragraph. + def post_discussion(self, blog_post_id=0, **post) + - ``change_bg`` : added method allow a user to change background image on blog + post from front-end. + def change_bg(self, post_id=0, image=None, **post) + - ``get_user`` : added method , that will return True if user is public else False. + def get_user(self, **post): + return [False if request.session.uid else True] + diff --git a/addons/website_blog/models/__init__.py b/addons/website_blog/models/__init__.py index fb5368a71c5..083e1ef6660 100644 --- a/addons/website_blog/models/__init__.py +++ b/addons/website_blog/models/__init__.py @@ -1 +1,2 @@ +import mail_message import website_blog diff --git a/addons/website_blog/models/mail_message.py b/addons/website_blog/models/mail_message.py new file mode 100644 index 00000000000..e1b60f6ad20 --- /dev/null +++ b/addons/website_blog/models/mail_message.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import osv, fields + + +class MailMessage(osv.Model): + _inherit = 'mail.message' + + _columns = { + 'path': fields.char( + 'Discussion Path', select=1, + help='Used to display messages in a paragraph-based chatter using a unique path;'), + } diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py index e132e4c5e15..031856fff10 100644 --- a/addons/website_blog/models/website_blog.py +++ b/addons/website_blog/models/website_blog.py @@ -1,32 +1,15 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-Today OpenERP SA (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## +from datetime import datetime +import difflib +import lxml +import random from openerp import tools from openerp import SUPERUSER_ID from openerp.osv import osv, fields from openerp.tools.translate import _ -import difflib - class Blog(osv.Model): _name = 'blog.blog' @@ -35,12 +18,9 @@ class Blog(osv.Model): _order = 'name' _columns = { - 'name': fields.char('Name', required=True), + 'name': fields.char('Blog Name', required=True), + 'subtitle': fields.char('Blog Subtitle'), 'description': fields.text('Description'), - 'blog_post_ids': fields.one2many( - 'blog.post', 'blog_id', - 'Blogs', - ), } @@ -52,9 +32,6 @@ class BlogTag(osv.Model): _columns = { 'name': fields.char('Name', required=True), - 'blog_post_ids': fields.many2many( - 'blog.post', string='Posts', - ), } @@ -62,37 +39,20 @@ class BlogPost(osv.Model): _name = "blog.post" _description = "Blog Post" _inherit = ['mail.thread', 'website.seo.metadata'] - _order = 'write_date DESC' - # maximum number of characters to display in summary - _shorten_max_char = 250 + _order = 'id DESC' - def get_shortened_content(self, cr, uid, ids, name, arg, context=None): + def _compute_ranking(self, cr, uid, ids, name, arg, context=None): res = {} - for page in self.browse(cr, uid, ids, context=context): - try: - body_short = tools.html_email_clean( - page.content, - remove=True, - shorten=True, - max_length=self._shorten_max_char, - expand_options={ - 'oe_expand_container_tag': 'div', - 'oe_expand_container_class': 'oe_mail_expand text-center', - 'oe_expand_container_content': '', - 'oe_expand_a_href': '/blogpost/%d' % page.id, - 'oe_expand_a_class': 'oe_mail_expand btn btn-info', - 'oe_expand_separator_node': 'br', - }, - protect_sections=True, - ) - except Exception: - body_short = False - res[page.id] = body_short + for blog_post in self.browse(cr, uid, ids, context=context): + age = datetime.now() - datetime.strptime(blog_post.create_date, tools.DEFAULT_SERVER_DATETIME_FORMAT) + res[blog_post.id] = blog_post.visits * (0.5+random.random()) / max(3, age.days) return res _columns = { 'name': fields.char('Title', required=True, translate=True), - 'content_image': fields.binary('Background Image'), + 'subtitle': fields.char('Sub Title', translate=True), + 'author_id': fields.many2one('res.partner', 'Author'), + 'background_image': fields.binary('Background Image'), 'blog_id': fields.many2one( 'blog.blog', 'Blog', required=True, ondelete='cascade', @@ -101,32 +61,22 @@ class BlogPost(osv.Model): 'blog.tag', string='Tags', ), 'content': fields.html('Content', translate=True), - 'shortened_content': fields.function( - get_shortened_content, - type='html', - string='Shortened Content', - help="Shortened content of the page that serves as a summary" - ), # website control 'website_published': fields.boolean( 'Publish', help="Publish on the website" ), - 'website_published_datetime': fields.datetime( - 'Publish Date' - ), - # TDE TODO FIXME: when website_mail/mail_thread.py inheritance work -> this field won't be necessary 'website_message_ids': fields.one2many( 'mail.message', 'res_id', domain=lambda self: [ - '&', ('model', '=', self._name), ('type', '=', 'comment') + '&', '&', ('model', '=', self._name), ('type', '=', 'comment'), ('path', '=', False) ], string='Website Messages', help="Website communication history", ), - # technical stuff: history, menu (to keep ?) 'history_ids': fields.one2many( 'blog.post.history', 'post_id', - 'History', help='Last post modifications' + 'History', help='Last post modifications', + deprecated='This field will be removed for OpenERP v9.' ), # creation / update stuff 'create_date': fields.datetime( @@ -145,11 +95,71 @@ class BlogPost(osv.Model): 'res.users', 'Last Contributor', select=True, readonly=True, ), + 'visits': fields.integer('No of Views'), + 'ranking': fields.function(_compute_ranking, string='Ranking', type='float'), } + _defaults = { - 'website_published': False + 'name': _('Blog Post Title'), + 'subtitle': _('Subtitle'), + 'author_id': lambda self, cr, uid, ctx=None: self.pool['res.users'].browse(cr, uid, uid, context=ctx).partner_id.id, } + def html_tag_nodes(self, html, attribute=None, tags=None, context=None): + """ Processing of html content to tag paragraphs and set them an unique + ID. + :return result: (html, mappin), where html is the updated html with ID + and mapping is a list of (old_ID, new_ID), where old_ID + is None is the paragraph is a new one. """ + mapping = [] + if not html: + return html, mapping + if tags is None: + tags = ['p'] + if attribute is None: + attribute = 'data-unique-id' + counter = 0 + + # form a tree + root = lxml.html.fragment_fromstring(html, create_parent='div') + if not len(root) and root.text is None and root.tail is None: + return html, mapping + + # check all nodes, replace : + # - img src -> check URL + # - a href -> check URL + for node in root.iter(): + if not node.tag in tags: + continue + ancestor_tags = [parent.tag for parent in node.iterancestors()] + if ancestor_tags: + ancestor_tags.pop() + ancestor_tags.append('counter_%s' % counter) + new_attribute = '/'.join(reversed(ancestor_tags)) + old_attribute = node.get(attribute) + node.set(attribute, new_attribute) + mapping.append((old_attribute, counter)) + counter += 1 + + html = lxml.html.tostring(root, pretty_print=False, method='html') + # this is ugly, but lxml/etree tostring want to put everything in a 'div' that breaks the editor -> remove that + if html.startswith('
    ') and html.endswith('
    '): + html = html[5:-6] + return html, mapping + + def _postproces_content(self, cr, uid, id, content=None, context=None): + if content is None: + content = self.browse(cr, uid, id, context=context).content + if content is False: + return content + content, mapping = self.html_tag_nodes(content, attribute='data-chatter-id', tags=['p'], context=context) + for old_attribute, new_attribute in mapping: + if not old_attribute: + continue + msg_ids = self.pool['mail.message'].search(cr, SUPERUSER_ID, [('path', '=', old_attribute)], context=context) + self.pool['mail.message'].write(cr, SUPERUSER_ID, msg_ids, {'path': new_attribute}, context=context) + return content + def create_history(self, cr, uid, ids, vals, context=None): for i in ids: history = self.pool.get('blog.post.history') @@ -163,12 +173,16 @@ class BlogPost(osv.Model): def create(self, cr, uid, vals, context=None): if context is None: context = {} + if 'content' in vals: + vals['content'] = self._postproces_content(cr, uid, None, vals['content'], context=context) create_context = dict(context, mail_create_nolog=True) post_id = super(BlogPost, self).create(cr, uid, vals, context=create_context) self.create_history(cr, uid, [post_id], vals, context) return post_id def write(self, cr, uid, ids, vals, context=None): + if 'content' in vals: + vals['content'] = self._postproces_content(cr, uid, None, vals['content'], context=context) result = super(BlogPost, self).write(cr, uid, ids, vals, context) self.create_history(cr, uid, ids, vals, context) return result @@ -183,10 +197,6 @@ class BlogPost(osv.Model): }) return super(BlogPost, self).copy(cr, uid, id, default=default, context=context) - def img(self, cr, uid, ids, field='image_small', context=None): - post = self.browse(cr, SUPERUSER_ID, ids[0], context=context) - return "/website/image?model=%s&field=%s&id=%s" % ('res.users', field, post.create_uid.id) - class BlogPostHistory(osv.Model): _name = "blog.post.history" @@ -215,5 +225,3 @@ class BlogPostHistory(osv.Model): raise osv.except_osv(_('Warning!'), _('There are no changes in revisions.')) diff = difflib.HtmlDiff() return diff.make_table(line1, line2, "Revision-%s" % (v1), "Revision-%s" % (v2), context=True) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/website_blog/static/description/index.html b/addons/website_blog/static/description/index.html index 1f198c11678..171fe942843 100644 --- a/addons/website_blog/static/description/index.html +++ b/addons/website_blog/static/description/index.html @@ -6,10 +6,7 @@
    - - - - +
    diff --git a/addons/website_blog/static/lib/contentshare.js b/addons/website_blog/static/lib/contentshare.js new file mode 100644 index 00000000000..9bfda158703 --- /dev/null +++ b/addons/website_blog/static/lib/contentshare.js @@ -0,0 +1,63 @@ +(function(){ + $.fn.share = function(options) { + var option = $.extend($.fn.share.defaults,options); + $.extend($.fn.share,{ + init : function(shareable) { + var self = this; + $.fn.share.defaults.shareable = shareable; + $.fn.share.defaults.shareable.on('mouseup',function(){ + self.popOver(); + }); + $.fn.share.defaults.shareable.on('mousedown',function(){ + self.destroy(); + }); + }, + getContent : function() { + var current_url = window.location.href + var selected_text = this.getSelection('string').substring(0,option.maxLength-(current_url.length+option.author_name.length+7)); + var text = encodeURIComponent('\"'+selected_text+'\" '+'--@'+option.author_name+' '+current_url) + return ''; + }, + getSelection : function(share) { + if(window.getSelection){ + return (share=='string')?String(window.getSelection().getRangeAt(0)).replace(/\s{2,}/g, ' '):window.getSelection().getRangeAt(0); + } + else if(document.selection){ + return (share=='string')?document.selection.createRange().text.replace(/\s{2,}/g, ' '):document.selection.createRange(); + } + }, + popOver : function() { + this.destroy(); + if(this.getSelection('string').length < option.minLength) + return; + var data = this.getContent(); + var range = this.getSelection(); + var newNode = document.createElement("mark"); + range.surroundContents(newNode); + $('mark').addClass(option.className); + $('.'+option.className).popover({trigger:'manual', placement: option.placement, html: true + , content:function(){ + return data; + } + }); + $('.'+option.className).popover('show'); + }, + destroy : function(){ + $('.'+option.className).popover('hide'); + $('mark').contents().unwrap(); + $('mark').remove(); + } + }); + $.fn.share.init(this); + }; + + $.fn.share.defaults = { + shareLink : "http://twitter.com/intent/tweet?text=", + minLength : 5, + maxLength : 140, + target : "blank", + className : "share", + placement : "top", + }; + +}()); diff --git a/addons/website_blog/static/src/css/website_blog.css b/addons/website_blog/static/src/css/website_blog.css index f7355ce783d..9097e3af31f 100644 --- a/addons/website_blog/static/src/css/website_blog.css +++ b/addons/website_blog/static/src/css/website_blog.css @@ -9,6 +9,12 @@ display: block; } +.read_width { + max-width: 700px; + margin-left: auto; + margin-right: auto; +} + .blog_content a.oe_mail_expand:after { content: " →"; } @@ -20,3 +26,127 @@ p.post-meta { position: relative; top: -5px; } + +div#blog_angle_down a:hover { + text-decoration: none; +} + +.cover { + -webkit-background-size: cover; + -moz-background-size: cover; + -o-background-size: cover; + background-size: cover; + background-position: center; + background-repeat: no-repeat; + background-color: black; + color: white; + position: relative; +} +.cover .blog_title { + position: absolute; + text-align: center; + top: 20%; + left: 0; + right: 0; +} +.cover .blog_title h1 { + font-weight: bold; +} + +.cover_footer { + min-height: 350px; + height: 65vh; + cursor: pointer; +} + +/*Inline Discussion */ +.discussion { + padding: 5px 10px 10px; + position: absolute; + top: 0; + left: 0; + line-height: 16px; + font-size: 13px; + font-weight: bold; + font-family: sans-serif; + text-align: center; + z-index: 7; +} +.discussion > a { + opacity: 0; + display: block; + overflow: hidden; + width: 20px; + height: 17px; + color: white; + text-decoration: none; + cursor: pointer; + background: #bbbbbb; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + -ms-border-radius: 2px; + -o-border-radius: 2px; + border-radius: 2px; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; + -o-transition: all 0.5s; + transition: all 0.5s; +} +.discussion > a.has-comments { + opacity: 0.6; +} + +.discussion-contain:hover .discussion > a { + opacity: 1; +} + +.discussion > a:after { + border-right: 7px solid transparent; + border-top: 7px solid #bbbbbb; + right: 19px; + top: 22px; + height: 0; + width: 0; + display: block; + content: " "; + position: absolute; + -webkit-transition: all 0.5s; + -moz-transition: all 0.5s; + -o-transition: all 0.5s; + transition: all 0.5s; +} +.discussion:hover > a, .discussion.hovered > a { + opacity: 1; + background: #57ad68; +} +.discussion:hover > a:after, .discussion.hovered > a:after { + border-top-color: #57ad68; +} + +#discussions_wrapper { + position: absolute; + top: 0; + left: 0; +} + +#discussions_overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 8; + display: none; +} + +.discussion .popover-content { + max-height: 250px; + width: 250px; + overflow: auto; + font-weight: normal; +} + +mark + .popover { + cursor: pointer; +} diff --git a/addons/website_blog/static/src/css/website_blog.sass b/addons/website_blog/static/src/css/website_blog.sass index 4691dde83c2..6342c6b99a2 100644 --- a/addons/website_blog/static/src/css/website_blog.sass +++ b/addons/website_blog/static/src/css/website_blog.sass @@ -1,5 +1,4 @@ @charset "utf-8" - @import "compass/css3" .css_website_mail @@ -10,6 +9,11 @@ &:first-of-type display: block +.read_width + max-width: 700px + margin-left: auto + margin-right: auto + .blog_content a.oe_mail_expand:after content: " →" @@ -20,3 +24,113 @@ p.post-meta position: relative top: -5px +div#blog_angle_down + a:hover + text-decoration: none + +.cover + -webkit-background-size: cover + -moz-background-size: cover + -o-background-size: cover + background-size: cover + background-position: center + background-repeat: no-repeat + background-color: #000 + color: #fff + position: relative + .blog_title + position: absolute + text-align: center + top: 20% + left: 0 + right: 0 + h1 + font-weight: bold + +.cover_footer + min-height : 350px + height: 65vh + cursor: pointer + +/*Inline Discussion + +.discussion + padding: 5px 10px 10px + position: absolute + top: 0 + left: 0 + line-height: 16px + font-size: 13px + font-weight: bold + font-family: sans-serif + text-align: center + z-index: 7 + > a + opacity: 0 + display: block + overflow: hidden + width: 20px + height: 17px + color: white + text-decoration: none + cursor: pointer + background: #bbbbbb + -webkit-border-radius: 2px + -moz-border-radius: 2px + -ms-border-radius: 2px + -o-border-radius: 2px + border-radius: 2px + -webkit-transition: all 0.5s + -moz-transition: all 0.5s + -o-transition: all 0.5s + transition: all 0.5s + &.has-comments + opacity: .6 + +.discussion-contain:hover .discussion > a + opacity: 1 + +.discussion + > a:after + border-right: 7px solid transparent + border-top: 7px solid #bbbbbb + right: 19px + top: 22px + height: 0 + width: 0 + display: block + content: " " + position: absolute + -webkit-transition: all 0.5s + -moz-transition: all 0.5s + -o-transition: all 0.5s + transition: all 0.5s + &:hover > a, &.hovered > a + opacity: 1 + background: #57AD68 + &:hover > a:after, &.hovered > a:after + border-top-color: #57AD68 + +#discussions_wrapper + position: absolute + top: 0 + left: 0 + +#discussions_overlay + position: fixed + top: 0 + left: 0 + right: 0 + bottom: 0 + background: rgba(0, 0, 0, 0.5) + z-index: 8 + display: none + +.discussion .popover-content + max-height: 250px + width: 250px + overflow: auto + font-weight: normal + +mark + .popover + cursor: pointer diff --git a/addons/website_blog/static/src/img/CMS_WMS_screens.jpg b/addons/website_blog/static/src/img/CMS_WMS_screens.jpg new file mode 100644 index 00000000000..08fc4aafc41 Binary files /dev/null and b/addons/website_blog/static/src/img/CMS_WMS_screens.jpg differ diff --git a/addons/website_blog/static/src/img/anonymous.png b/addons/website_blog/static/src/img/anonymous.png new file mode 100644 index 00000000000..6461bf735f1 Binary files /dev/null and b/addons/website_blog/static/src/img/anonymous.png differ diff --git a/addons/website_blog/static/src/img/mail-sc-00.png b/addons/website_blog/static/src/img/mail-sc-00.png new file mode 100644 index 00000000000..dbb14b4da36 Binary files /dev/null and b/addons/website_blog/static/src/img/mail-sc-00.png differ diff --git a/addons/website_blog/static/src/img/mail-sc-03.png b/addons/website_blog/static/src/img/mail-sc-03.png new file mode 100644 index 00000000000..3011ef129b5 Binary files /dev/null and b/addons/website_blog/static/src/img/mail-sc-03.png differ diff --git a/addons/website_blog/static/src/img/post1.jpg b/addons/website_blog/static/src/img/post1.jpg new file mode 100644 index 00000000000..f3e3aa852a6 Binary files /dev/null and b/addons/website_blog/static/src/img/post1.jpg differ diff --git a/addons/website_blog/static/src/img/post2.jpg b/addons/website_blog/static/src/img/post2.jpg new file mode 100644 index 00000000000..8f6002a40db Binary files /dev/null and b/addons/website_blog/static/src/img/post2.jpg differ diff --git a/addons/website_blog/static/src/js/website_blog.editor.js b/addons/website_blog/static/src/js/website_blog.editor.js index 1c5deef56f7..103b2bee1e7 100644 --- a/addons/website_blog/static/src/js/website_blog.editor.js +++ b/addons/website_blog/static/src/js/website_blog.editor.js @@ -27,7 +27,38 @@ }).then(function (cat_id) { document.location = '/blogpost/new?blog_id=' + cat_id; }); - } + }, }), + edit: function () { + $('.popover').remove(); + this._super(); + var vHeight = $(window).height(); + $('body').on('click','#change_cover',_.bind(this.change_bg,{},vHeight)); + $('body').on('click', '#clear_cover',_.bind(this.clean_bg,{},vHeight)); + }, + save : function() { + var res = this._super(); + if ($('.cover').length) { + openerp.jsonRpc("/blogpost/change_background", 'call', { + 'post_id' : $('#blog_post_name').attr('data-oe-id'), + 'image' : $('.cover').css('background-image').replace(/url\(|\)|"|'/g,''), + }); + } + return res; + }, + clean_bg : function(vHeight) { + $('.js_fullheight').css({"background-image":'none', 'min-height': vHeight}); + }, + change_bg : function(vHeight) { + var self = this; + var editor = new website.editor.ImageDialog(); + editor.on('start', self, function (o) { + o.url = $('.js_fullheight').length ? $('.js_fullheight').css('background-image').replace(/url\(|\)|"|'/g,'') : ''; + }); + editor.on('save', self, function (o) { + $('.js_fullheight').css({"background-image": o.url && o.url !== "" ? 'url(' + o.url + ')' : "", 'min-height': vHeight}) + }); + editor.appendTo('body'); + }, }); })(); diff --git a/addons/website_blog/static/src/js/website_blog.inline.discussion.js b/addons/website_blog/static/src/js/website_blog.inline.discussion.js new file mode 100644 index 00000000000..56851c3939c --- /dev/null +++ b/addons/website_blog/static/src/js/website_blog.inline.discussion.js @@ -0,0 +1,199 @@ +// Inspired from https://github.com/tsi/inlineDisqussions +(function () { + + 'use strict'; + + var website = openerp.website, + qweb = openerp.qweb; + website.add_template_file('/website_blog/static/src/xml/website_blog.inline.discussion.xml'); + website.blog_discussion = openerp.Class.extend({ + init: function(options) { + var self = this ; + self.discus_identifier; + var defaults = { + position: 'right', + post_id: $('#blog_post_name').attr('data-blog-id'), + content : false, + public_user: false, + }; + self.settings = $.extend({}, defaults, options); + self.do_render(self); + }, + do_render: function(data) { + var self = this; + if ($('#discussions_wrapper').length === 0 && self.settings.content.length > 0) { + $('
    ').insertAfter($('#blog_content')); + } + // Attach a discussion to each paragraph. + $(self.settings.content).each(function(i) { + self.discussion_handler(i, $(this)); + }); + // Hide the discussion. + $('html').click(function(event) { + if($(event.target).parents('#discussions_wrapper, .main-discussion-link-wrp').length === 0) { + self.hide_discussion(); + } + if(!$(event.target).hasClass('discussion-link') && !$(event.target).parents('.popover').length){ + if($('.move_discuss').length){ + $('[enable_chatter_discuss=True]').removeClass('move_discuss'); + $('[enable_chatter_discuss=True]').animate({ + 'marginLeft': "+=40%" + }); + $('#discussions_wrapper').animate({ + 'marginLeft': "+=250px" + }); + } + } + }); + }, + prepare_data : function(identifier, comment_count) { + var self = this; + return openerp.jsonRpc("/blogpost/get_discussion/", 'call', { + 'post_id': self.settings.post_id, + 'path': identifier, + 'count': comment_count, //if true only get length of total comment, display on discussion thread. + }) + }, + discussion_handler : function(i, node) { + var self = this; + var identifier = node.attr('data-chatter-id'); + if (identifier) { + self.prepare_data(identifier, true).then( function (data) { + self.prepare_discuss_link(data, identifier, node); + }); + } + }, + prepare_discuss_link : function(data, identifier, node) { + var self = this; + var cls = data > 0 ? 'discussion-link has-comments' : 'discussion-link'; + var a = $('') + .attr('data-discus-identifier', identifier) + .attr('data-discus-position', self.settings.position) + .text(data > 0 ? data : '+') + .attr('data-contentwrapper', '.mycontent') + .wrap('
    ') + .parent() + .appendTo('#discussions_wrapper'); + a.css({ + 'top': node.offset().top, + 'left': self.settings.position == 'right' ? node.outerWidth() + node.offset().left: node.offset().left - a.outerWidth() + }); + // node.attr('data-discus-identifier', identifier) + node.mouseover(function() { + a.addClass("hovered"); + }).mouseout(function() { + a.removeClass("hovered"); + }); + + a.delegate('a.discussion-link', "click", function(e) { + e.preventDefault(); + if(!$('.move_discuss').length){ + $('[enable_chatter_discuss=True]').addClass('move_discuss'); + $('[enable_chatter_discuss=True]').animate({ + 'marginLeft': "-=40%" + }); + $('#discussions_wrapper').animate({ + 'marginLeft': "-=250px" + }); + } + if ($(this).is('.active')) { + e.stopPropagation(); + self.hide_discussion(); + } + else { + self.get_discussion($(this), function(source) {}); + } + }); + }, + get_discussion : function(source, callback) { + var self = this; + var identifier = source.attr('data-discus-identifier'); + self.hide_discussion(); + self.discus_identifier = identifier; + var elt = $('a[data-discus-identifier="'+identifier+'"]'); + elt.append(qweb.render("website.blog_discussion.popover", {'identifier': identifier , 'options': self.settings})); + var comment = ''; + self.prepare_data(identifier,false).then(function(data){ + _.each(data, function(res){ + comment += qweb.render("website.blog_discussion.comment", {'res': res}); + }); + $('.discussion_history').html('
      '+comment+'
    '); + self.create_popover(elt, identifier); + // Add 'active' class. + $('a.discussion-link, a.main-discussion-link').removeClass('active').filter(source).addClass('active'); + elt.popover('hide').filter(source).popover('show'); + callback(source); + }); + }, + create_popover : function(elt, identifier) { + var self = this; + elt.popover({ + placement:'right', + trigger:'manual', + html:true, content:function(){ + return $($(this).data('contentwrapper')).html(); + } + }).parent().delegate(self).on('click','button#comment_post',function(e) { + e.stopImmediatePropagation(); + self.post_discussion(identifier); + }); + }, + validate : function(public_user){ + var comment = $(".popover textarea#inline_comment").val(); + if (public_user){ + var author_name = $('.popover input#author_name').val(); + var author_email = $('.popover input#author_email').val(); + if(!comment || !author_name || !author_email){ + if (!author_name) + $('div#author_name').addClass('has-error'); + else + $('div#author_name').removeClass('has-error'); + if (!author_email) + $('div#author_email').addClass('has-error'); + else + $('div#author_email').removeClass('has-error'); + if(!comment) + $('div#inline_comment').addClass('has-error'); + else + $('div#inline_comment').removeClass('has-error'); + return false + } + } + else if(!comment) { + $('div#inline_comment').addClass('has-error'); + return false + } + $("div#inline_comment").removeClass('has-error'); + $('div#author_name').removeClass('has-error'); + $('div#author_email').removeClass('has-error'); + $(".popover textarea#inline_comment").val(''); + $('.popover input#author_name').val(''); + $('.popover input#author_email').val(''); + return [comment, author_name, author_email] + }, + post_discussion : function(identifier) { + var self = this; + var val = self.validate(self.settings.public_user) + if(!val) return + openerp.jsonRpc("/blogpost/post_discussion", 'call', { + 'blog_post_id': self.settings.post_id, + 'path': self.discus_identifier, + 'comment': val[0], + 'name' : val[1], + 'email': val[2], + }).then(function(res){ + $(".popover ul.media-list").prepend(qweb.render("website.blog_discussion.comment", {'res': res[0]})) + var ele = $('a[data-discus-identifier="'+ self.discus_identifier +'"]'); + ele.text(_.isNaN(parseInt(ele.text())) ? 1 : parseInt(ele.text())+1) + ele.addClass('has-comments'); + }); + }, + hide_discussion : function() { + var self = this; + $('a[data-discus-identifier="'+ self.discus_identifier+'"]').popover('destroy'); + $('a.discussion-link').removeClass('active'); + } + + }); + +})(); diff --git a/addons/website_blog/static/src/js/website_blog.js b/addons/website_blog/static/src/js/website_blog.js new file mode 100644 index 00000000000..3217bf1a04d --- /dev/null +++ b/addons/website_blog/static/src/js/website_blog.js @@ -0,0 +1,40 @@ +$(document).ready(function() { + + function page_transist(event) { + event.preventDefault(); + newLocation = $('.js_next')[0].href; + var top = $('.cover_footer').offset().top; + $('.cover_footer').animate({ + height: $(window).height()+'px' + }, 300); + $('html, body').animate({ + scrollTop: top + }, 300, 'swing', function() { + window.location.href = newLocation; + }); + } + function animate(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + var target = $(this.hash); + $('html, body').stop().animate({ + 'scrollTop': target.offset().top - 32 + }, 500, 'swing', function () { + window.location.hash = 'blog_content'; + }); + } + + var content = $("div[enable_chatter_discuss='True']").find('p[data-chatter-id]'); + if (content) { + openerp.jsonRpc("/blog/get_user/", 'call', {}).then(function(data){ + $('#discussions_wrapper').empty(); + new openerp.website.blog_discussion({'content' : content, 'public_user':data[0]}); + }); + } + + $('.js_fullheight').css('min-height', $(window).height()); + $(".js_tweet").share({'author_name':$('#blog_author').text()}); + $('.cover_footer').on('click',page_transist); + $('a[href^="#blog_content"]').on('click', animate); + +}); diff --git a/addons/website_blog/static/src/xml/website_blog.inline.discussion.xml b/addons/website_blog/static/src/xml/website_blog.inline.discussion.xml new file mode 100644 index 00000000000..8c1cda26265 --- /dev/null +++ b/addons/website_blog/static/src/xml/website_blog.inline.discussion.xml @@ -0,0 +1,38 @@ + + + +
  • +
    + +
    +
    + + +
    +
    +
    + + by + + +
    +
  • +
    + +
    : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 4da0a509ed1..9dfe22202ec 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -241,10 +241,10 @@ class crm_lead(format_address, osv.osv): 'opt_out': fields.boolean('Opt-Out', oldname='optout', help="If opt-out is checked, this contact has refused to receive emails for mass mailing and marketing campaign. " "Filter 'Available for Mass Mailing' allows users to filter the leads when performing mass mailing."), - 'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"), + 'type': fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', select=True, help="Type is used to separate Leads and Opportunities"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'date_closed': fields.datetime('Closed', readonly=True), - 'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', + 'stage_id': fields.many2one('crm.case.stage', 'Stage', track_visibility='onchange', select=True, domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"), 'user_id': fields.many2one('res.users', 'Salesperson', select=True, track_visibility='onchange'), 'referred': fields.char('Referred By', size=64), diff --git a/addons/crm_partner_assign/static/src/js/next.js b/addons/crm_partner_assign/static/src/js/next.js deleted file mode 100644 index b3a4fff2732..00000000000 --- a/addons/crm_partner_assign/static/src/js/next.js +++ /dev/null @@ -1,19 +0,0 @@ -openerp.crm_partner_assign = function (instance) { - instance.crm_partner_assign = instance.crm_partner_assign || {}; - instance.crm_partner_assign.next_or_list = function(parent) { - var view = parent.inner_widget.active_view; - var controller = parent.inner_widget.views[view].controller; - if (view === "form"){ - if (controller.dataset.size()) { - controller.execute_pager_action('next'); - } else { - controller.do_action('history_back'); - } - } - controller.do_action({ type: 'ir.actions.act_window_close' }); - if (view === "list"){ - controller.records.remove(controller.records.get(parent.dialog_widget.action.context.active_id)); - } - }; - instance.web.client_actions.add("next_or_list", "instance.crm_partner_assign.next_or_list"); -} \ No newline at end of file diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested.py b/addons/crm_partner_assign/wizard/crm_channel_interested.py index a407ca7b910..a23de29d766 100644 --- a/addons/crm_partner_assign/wizard/crm_channel_interested.py +++ b/addons/crm_partner_assign/wizard/crm_channel_interested.py @@ -63,15 +63,12 @@ class crm_lead_forward_to_partner(osv.TransientModel): if wizard.comment: message += '

    %s

    ' % wizard.comment for active_id in context.get('active_ids', []): - lead_obj.message_post(cr, uid, active_id, body=message, context=context) + lead_obj.message_post(cr, uid, active_id, body=message, subtype="mail.mt_comment", context=context) if values: lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids', []), values) if wizard.interested: for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context): lead_obj.convert_opportunity(cr, SUPERUSER_ID, [lead.id], lead.partner_id and lead.partner_id.id or None, context=None) return { - 'type': 'ir.actions.client', - 'tag': 'next_or_list', - 'params': { - }, + 'type': 'ir.actions.act_window_close', } diff --git a/addons/delivery/sale.py b/addons/delivery/sale.py index dbebd01ef1e..c5d032ca8a8 100644 --- a/addons/delivery/sale.py +++ b/addons/delivery/sale.py @@ -58,20 +58,18 @@ class sale_order(osv.Model): result.update(carrier_id=order.carrier_id.id) return result - def _delivery_unset(self, cr, uid, order, context=None): - line_ids = [line.id for line in order.order_line if line.is_delivery] - self.pool['sale.order.line'].unlink(cr, uid, line_ids, context=context) - order.refresh() - return True + def _delivery_unset(self, cr, uid, ids, context=None): + sale_obj = self.pool['sale.order.line'] + line_ids = sale_obj.search(cr, uid, [('order_id', 'in', ids), ('is_delivery', '=', True)],context=context) + sale_obj.unlink(cr, uid, line_ids, context=context) def delivery_set(self, cr, uid, ids, context=None): line_obj = self.pool.get('sale.order.line') grid_obj = self.pool.get('delivery.grid') carrier_obj = self.pool.get('delivery.carrier') acc_fp_obj = self.pool.get('account.fiscal.position') - + self._delivery_unset(cr, uid, ids, context=context) for order in self.browse(cr, uid, ids, context=context): - self._delivery_unset(cr, uid, order, context=context) grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id) if not grid_id: raise osv.except_osv(_('No Grid Available!'), _('No grid matching for this carrier!')) diff --git a/addons/document/document.py b/addons/document/document.py index eb51ad5ac57..9008f32cd20 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -2005,7 +2005,7 @@ class nodefd_content(StringIO, node_descriptor): par = self._get_parent() uid = par.context.uid - cr = openerp.registry(par.context.dbname).db.cursor() + cr = openerp.registry(par.context.dbname).cursor() try: if self.mode in ('w', 'w+', 'r+'): data = self.getvalue() @@ -2058,7 +2058,7 @@ class nodefd_static(StringIO, node_descriptor): par = self._get_parent() # uid = par.context.uid - cr = openerp.registry(par.context.dbname).db.cursor() + cr = openerp.registry(par.context.dbname).cursor() try: if self.mode in ('w', 'w+', 'r+'): data = self.getvalue() diff --git a/addons/edi/edi_service.py b/addons/edi/edi_service.py index dd95196ef4f..0d3edd451d1 100644 --- a/addons/edi/edi_service.py +++ b/addons/edi/edi_service.py @@ -34,18 +34,14 @@ def _edi_dispatch(db_name, method_name, *method_args): try: registry = openerp.modules.registry.RegistryManager.get(db_name) assert registry, 'Unknown database %s' % db_name - edi = registry['edi.edi'] - cr = registry.db.cursor() - res = None - res = getattr(edi, method_name)(cr, *method_args) - cr.commit() + with registry.cursor() as cr: + edi = registry['edi.edi'] + return getattr(edi, method_name)(cr, *method_args) + except Exception, e: _logger.exception('Failed to execute EDI method %s with args %r.', method_name, method_args) raise - finally: - cr.close() - return res def exp_import_edi_document(db_name, uid, passwd, edi_document, context=None): return _edi_dispatch(db_name, 'import_edi', uid, edi_document, None) diff --git a/addons/event/event.py b/addons/event/event.py index 92b237687d7..7ee99402158 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -158,16 +158,16 @@ class event_event(osv.osv): 'seats_min': fields.integer('Minimum Reserved Seats', oldname='register_min', help="You can for each event define a minimum registration level. If you do not enough registrations you are not able to confirm your event. (put 0 to ignore this rule )", readonly=True, states={'draft': [('readonly', False)]}), 'seats_reserved': fields.function(_get_seats, oldname='register_current', string='Reserved Seats', type='integer', multi='seats_reserved', store={'event.registration': (_get_events_from_registrations, ['state'], 10), - 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max'], 20)}), + 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max', 'registration_ids'], 20)}), 'seats_available': fields.function(_get_seats, oldname='register_avail', string='Available Seats', type='integer', multi='seats_reserved', store={'event.registration': (_get_events_from_registrations, ['state'], 10), - 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max'], 20)}), + 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max', 'registration_ids'], 20)}), 'seats_unconfirmed': fields.function(_get_seats, oldname='register_prospect', string='Unconfirmed Seat Reservations', type='integer', multi='seats_reserved', store={'event.registration': (_get_events_from_registrations, ['state'], 10), - 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max'], 20)}), + 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max', 'registration_ids'], 20)}), 'seats_used': fields.function(_get_seats, oldname='register_attended', string='Number of Participations', type='integer', multi='seats_reserved', store={'event.registration': (_get_events_from_registrations, ['state'], 10), - 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max'], 20)}), + 'event.event': (lambda self, cr, uid, ids, c = {}: ids, ['seats_max', 'registration_ids'], 20)}), 'registration_ids': fields.one2many('event.registration', 'event_id', 'Registrations', readonly=False, states={'done': [('readonly', True)]}), 'date_begin': fields.datetime('Start Date', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'date_end': fields.datetime('End Date', required=True, readonly=True, states={'draft': [('readonly', False)]}), @@ -201,7 +201,6 @@ class event_event(osv.osv): } def _check_seats_limit(self, cr, uid, ids, context=None): - print "event _check_seats_limit" for event in self.browse(cr, uid, ids, context=context): if event.seats_max and event.seats_available < 0: return False diff --git a/addons/event/res_partner_view.xml b/addons/event/res_partner_view.xml index 7e97f80e30d..19eb2517131 100644 --- a/addons/event/res_partner_view.xml +++ b/addons/event/res_partner_view.xml @@ -10,6 +10,7 @@ + diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 8e79c43c8a6..925b05de5ab 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -279,7 +279,7 @@ class gamification_goal(osv.Model): if goal.definition_id.computation_mode == 'sum': field_name = goal.definition_id.field_id.name - res = obj.read_group(cr, uid, domain, [field_name], [''], context=context) + res = obj.read_group(cr, uid, domain, [field_name], [field_name], context=context) new_value = res and res[0][field_name] or 0.0 else: # computation mode = count diff --git a/addons/google_drive/__openerp__.py b/addons/google_drive/__openerp__.py index 8f135c5f9d1..e486c2c2d34 100644 --- a/addons/google_drive/__openerp__.py +++ b/addons/google_drive/__openerp__.py @@ -28,7 +28,6 @@ 'installable': True, 'auto_install': False, 'js': [ - 'static/lib/gapi/client.js', 'static/src/js/gdrive.js', ], 'data': [ diff --git a/addons/google_drive/static/lib/gapi/client.js b/addons/google_drive/static/lib/gapi/client.js deleted file mode 100644 index 7f40ec55ef9..00000000000 --- a/addons/google_drive/static/lib/gapi/client.js +++ /dev/null @@ -1,7 +0,0 @@ -var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){var f=null,g=encodeURIComponent,k=window,m=decodeURIComponent,n="push",r="test",t="shift",u="replace",y="length",B="split",C="join";var D=k,E=document,aa=D.location,ba=function(){},ca=/\[native code\]/,G=function(a,b,c){return a[b]=a[b]||c},da=function(a){for(var b=0;bda.call(b,e)&&c[n](e)}return c},sa=function(a){"loading"!=E.readyState?Z(a):E.write("<"+X+' src="'+encodeURI(a)+'">")},Z=function(a){var b=E.createElement(X);b.setAttribute("src",a);b.async="true";(a=E.getElementsByTagName(X)[0])?a.parentNode.insertBefore(b,a):(E.head||E.body||E.documentElement).appendChild(b)},ta=function(a,b){var c=b&&b._c;if(c)for(var d=0;dOrganize your vacancies and applications
    -
    - - - - -
    +

    diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py index b6c302aa9e9..938fa064d52 100644 --- a/addons/hw_escpos/controllers/main.py +++ b/addons/hw_escpos/controllers/main.py @@ -54,11 +54,10 @@ class EscposDriver(Thread): return connected def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.daemon = True - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def get_escpos_printer(self): try: diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py index 64daf20fccb..a0f225ab42f 100644 --- a/addons/hw_scanner/controllers/main.py +++ b/addons/hw_scanner/controllers/main.py @@ -88,10 +88,10 @@ class Scanner(Thread): } def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def set_status(self, status, message = None): if status == self.status['status']: diff --git a/addons/idea/models/idea.py b/addons/idea/models/idea.py index 61934cfc3b2..37fbbe82e1c 100644 --- a/addons/idea/models/idea.py +++ b/addons/idea/models/idea.py @@ -91,7 +91,7 @@ class IdeaIdea(osv.Model): # Technical stuff #------------------------------------------------------ - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): """ Override read_group to always display all states. """ if groupby and groupby[0] == "state": # Default result structure @@ -103,7 +103,7 @@ class IdeaIdea(osv.Model): 'state_count': 0, } for state_value, state_name in states] # Get standard results - read_group_res = super(IdeaIdea, self).read_group(cr, uid, domain, fields, groupby, offset, limit, context, orderby) + read_group_res = super(IdeaIdea, self).read_group(cr, uid, domain, fields, groupby, offset, limit, context, orderby, lazy) # Update standard results with default results result = [] for state_value, state_name in states: @@ -114,7 +114,7 @@ class IdeaIdea(osv.Model): result.append(res[0]) return result else: - return super(IdeaIdea, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) + return super(IdeaIdea, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby, lazy=lazy) #------------------------------------------------------ # Workflow / Actions diff --git a/addons/l10n_be/account_tax_template.xml b/addons/l10n_be/account_tax_template.xml index 7dfd37b2f40..6958673ae8b 100644 --- a/addons/l10n_be/account_tax_template.xml +++ b/addons/l10n_be/account_tax_template.xml @@ -2052,6 +2052,8 @@ VAT-IN-V82-CAR-EXC-C1 Frais de voiture - VAT 50% Non Deductible + + 0.105 percent diff --git a/addons/l10n_fr/fr_fiscal_templates.xml b/addons/l10n_fr/fr_fiscal_templates.xml index bf49d15e08c..cca96422c22 100644 --- a/addons/l10n_fr/fr_fiscal_templates.xml +++ b/addons/l10n_fr/fr_fiscal_templates.xml @@ -40,11 +40,6 @@ - - - - - @@ -57,22 +52,12 @@ - - - - - - - - - - @@ -91,17 +76,6 @@ - - - - - - - - - - - @@ -124,17 +98,6 @@ - - - - - - - - - - - @@ -146,17 +109,6 @@ - - - - - - - - - - - @@ -177,11 +129,6 @@ - - - - - @@ -194,22 +141,12 @@ - - - - - - - - - - @@ -224,11 +161,6 @@ - - - - - @@ -241,23 +173,12 @@ - - - - - - - - - - - diff --git a/addons/l10n_fr/fr_tax.xml b/addons/l10n_fr/fr_tax.xml index 8633cca7141..22e1e12f03c 100644 --- a/addons/l10n_fr/fr_tax.xml +++ b/addons/l10n_fr/fr_tax.xml @@ -29,28 +29,6 @@ sale - - - - TVA collectée (vente) 19,6% - 19.6 - - percent - - - - - - - - - - - - - - sale - @@ -96,51 +74,7 @@ sale - - - TVA collectée (vente) 7,0% - 7.0 - - percent - - - - - - - - - - - - - - sale - - - - TVA collectée (vente) 5,0% - 5.0 - - percent - - - - - - - - - - - - - - sale - - - TVA collectée (vente) 5,5% 5.5 @@ -208,28 +142,6 @@ purchase - - - TVA déductible (achat) 19,6% - ACH-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% @@ -274,51 +186,7 @@ purchase - - - TVA déductible (achat) 7,0% - ACH-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% - ACH-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% ACH-5.5 @@ -387,29 +255,6 @@ purchase - - - TVA déductible (achat) 19,6% TTC - ACH-19.6-TTC - - - percent - - - - - - - - - - - - - - purchase - - TVA déductible (achat) 8,5% TTC @@ -456,53 +301,7 @@ purchase - - - TVA déductible (achat) 7,0% TTC - ACH-7.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - - TVA déductible (achat) 5,0% TTC - ACH-5.0-TTC - - - percent - - - - - - - - - - - - - - purchase - - - TVA déductible (achat) 5,5% TTC ACH-5.5-TTC @@ -573,28 +372,6 @@ purchase - - - TVA déd./immobilisation (achat) 19,6% - IMMO-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA déd./immobilisation (achat) 8,5% @@ -639,51 +416,7 @@ purchase - - - TVA déd./immobilisation (achat) 7,0% - IMMO-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA déd./immobilisation (achat) 5,0% - IMMO-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA déd./immobilisation (achat) 5,5% IMMO-5.5 @@ -751,28 +484,6 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_due-19.6 - - percent - - - - - - - - - - - - - - purchase - - TVA due s/ acq. intracommunautaire (achat) 8,5% @@ -817,51 +528,7 @@ purchase - - - TVA due s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_due-7.0 - - percent - - - - - - - - - - - - - - purchase - - - - TVA due s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_due-5.0 - - percent - - - - - - - - - - - - - - purchase - - - TVA due s/ acq. intracommunautaire (achat) 5,5% ACH_UE_due-5.5 @@ -925,24 +592,6 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 19,6% - ACH_UE_ded.-19.6 - - percent - - - - - - - - - - purchase - - TVA déd. s/ acq. intracommunautaire (achat) 8,5% @@ -979,43 +628,7 @@ purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 7,0% - ACH_UE_ded.-7.0 - - percent - - - - - - - - - - purchase - - - - TVA déd. s/ acq. intracommunautaire (achat) 5,0% - ACH_UE_ded.-5.0 - - percent - - - - - - - - - - purchase - - - TVA déd. s/ acq. intracommunautaire (achat) 5,5% ACH_UE_ded.-5.5 diff --git a/addons/l10n_lu/__init__.py b/addons/l10n_lu/__init__.py index 0e933f136e0..9a6ca02408e 100644 --- a/addons/l10n_lu/__init__.py +++ b/addons/l10n_lu/__init__.py @@ -19,6 +19,4 @@ # ############################################################################## -import wizard - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/__openerp__.py b/addons/l10n_lu/__openerp__.py index 46d2312bb02..96c4ea64dea 100644 --- a/addons/l10n_lu/__openerp__.py +++ b/addons/l10n_lu/__openerp__.py @@ -22,7 +22,6 @@ # ############################################################################## - { 'name': 'Luxembourg - Accounting', 'version': '1.0', @@ -51,12 +50,12 @@ This is the base module to manage the accounting chart for Luxembourg. 'account.fiscal.position.tax.template-2011.csv', # configuration wizard, views, reports... 'l10n_lu_wizard.xml', - 'wizard/print_vat_view.xml' ], - 'test': ['test/l10n_lu_report.yml'], + 'test': [], 'demo': [], 'installable': True, 'auto_install': False, 'images': ['images/config_chart_l10n_lu.jpeg','images/l10n_lu_chart.jpeg'], } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/test/l10n_lu_report.yml b/addons/l10n_lu/test/l10n_lu_report.yml deleted file mode 100644 index 0ee032d581c..00000000000 --- a/addons/l10n_lu/test/l10n_lu_report.yml +++ /dev/null @@ -1,18 +0,0 @@ -- - It is demo data for the account.tax.code -- - !record {model: account.tax.code, id: account_tax_code_id_r1}: - name: a - -- - In order to test the PDF reports defined on a l10u_lu, we will print a VAT Report -- - !python {model: res.partner}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [], 'l10n_lu.tax.report.print', {'model':'ir.ui.menu', 'form':{'tax_code_id': ref('account_tax_code_id_r1'), 'period_id': ref('account.period_1')}}, {}) - if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'l10n_lu-vat_report.'+format), 'wb+').write(data) - - diff --git a/addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf b/addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf deleted file mode 100644 index 9df4ae34065..00000000000 Binary files a/addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf and /dev/null differ diff --git a/addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf b/addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf deleted file mode 100644 index 0699bbcb7d9..00000000000 Binary files a/addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf and /dev/null differ diff --git a/addons/l10n_lu/wizard/__init__.py b/addons/l10n_lu/wizard/__init__.py deleted file mode 100644 index 140f04905ab..00000000000 --- a/addons/l10n_lu/wizard/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import print_vat - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/wizard/pdf_ext.py b/addons/l10n_lu/wizard/pdf_ext.py deleted file mode 100644 index 94f150e41d7..00000000000 --- a/addons/l10n_lu/wizard/pdf_ext.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -""" Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -manipulate pdf and fdf files. pdftk recommended. - -Notes regarding pdftk, pdf forms and fdf files (form definition file) -fields names can be extracted with: - pdftk orig.pdf generate_fdf output truc.fdf -to merge fdf and pdf: - pdftk orig.pdf fill_form test.fdf output result.pdf [flatten] -without flatten, one could further edit the resulting form. -with flatten, everything is turned into text. -""" - -import os -from openerp import tools - -HEAD="""%FDF-1.2 -%\xE2\xE3\xCF\xD3 -1 0 obj -<< -/FDF -<< -/Fields [ -""" - -TAIL="""] ->> ->> -endobj -trailer - -<< -/Root 1 0 R ->> -%%EOF -""" - -def output_field(f): - return "\xfe\xff" + "".join( [ "\x00"+c for c in f ] ) - -def extract_keys(lines): - keys = [] - for line in lines: - if line.startswith('/V'): - pass - elif line.startswith('/T'): - key = line[7:-2] - key = ''.join(key.split('\x00')) - keys.append( key ) - return keys - -def write_field(out, key, value): - out.write("<<\n") - if value: - out.write("/V (%s)\n" %value) - else: - out.write("/V /\n") - out.write("/T (%s)\n" % output_field(key) ) - out.write(">> \n") - -def write_fields(out, fields): - out.write(HEAD) - for key in fields: - value = fields[key] - write_field(out, key, value) - out.write(TAIL) - -def extract_keys_from_pdf(filename): - # what about using 'pdftk filename dump_data_fields' and parsing the output ? - os.system('pdftk %s generate_fdf output /tmp/toto.fdf' % filename) - lines = file('/tmp/toto.fdf').readlines() - return extract_keys(lines) - - -def fill_pdf(infile, outfile, fields): - write_fields(file('/tmp/toto.fdf', 'w'), fields) - os.system('pdftk %s fill_form /tmp/toto.fdf output %s flatten' % (infile, outfile)) - -def testfill_pdf(infile, outfile): - keys = extract_keys_from_pdf(infile) - fields = [] - for key in keys: - fields.append( (key, key, '') ) - fill_pdf(infile, outfile, fields) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/l10n_lu/wizard/print_vat.py b/addons/l10n_lu/wizard/print_vat.py deleted file mode 100644 index 04d4fe9a3b7..00000000000 --- a/addons/l10n_lu/wizard/print_vat.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) Vincent Cardon -# Denis Cardon and Emmanuel RICHARD. -#Ingenieur fondateur -#Tranquil IT Systems - -from __future__ import with_statement - -import openerp -from openerp.osv import fields, osv -from openerp import tools -from openerp.modules.module import get_module_resource -from openerp.tools.translate import _ -from openerp.report.render import render -from openerp.report.interface import report_int -import tempfile -import os - -class external_pdf(render): - - def __init__(self, pdf): - render.__init__(self) - self.pdf = pdf - self.output_type='pdf' - - def _render(self): - return self.pdf - - -class report_custom(report_int): - - def create(self, cr, uid, ids, datas, context=None): - - registry = openerp.registry(cr.dbname) - taxobj = registry['account.tax.code'] - - if context is None: - context = {} - code_ids = taxobj.search(cr, uid, [('parent_id','child_of',[datas['form']['tax_code_id']])]) - result = {} - for t in taxobj.browse(cr, uid, code_ids, {'period_id': datas['form']['period_id']}): - if str(t.code): - result['case_'+str(t.code)] = '%.2f' % (t.sum_period or 0.0, ) - user = registry['res.users'].browse(cr, uid, uid, context) - - # Not Clean, to be changed - partner = user.company_id.partner_id - result['info_name'] = user.company_id.name - result['info_vatnum'] = partner.vat - if partner: - result['info_address'] = partner.street - result['info_address2'] = (partner.zip or '') + ' ' + (partner.city or '') - try: - tmp_file = tempfile.mkstemp(".pdf")[1] - try: - tools.pdf_utils.fill_pdf(get_module_resource('l10n_lu','wizard', '2008_DECL_F_M10.pdf'), tmp_file, result) - with open(tmp_file, "r") as ofile: - self.obj = external_pdf(ofile.read()) - finally: - try: - os.remove(tmp_file) - except: - pass # nothing to do - self.obj.render() - return (self.obj.pdf, 'pdf') - except Exception: - raise osv.except_osv(_('PDF Not Created!'), _('Please check if package pdftk is installed!')) - -report_custom('report.l10n_lu.tax.report.print') - -class vat_declaration_report(osv.osv_memory): - _name = 'vat.declaration.report' - _description = 'VAT Declaration Report' - - _columns = { - 'tax_code_id': fields.many2one('account.tax.code', 'Company', readonly=False, required=True, domain=[('parent_id','=',False)]), - 'type': fields.selection([('monthly','Monthly'),('quarterly','Quaterly'),('yearly','Yearly')], 'Type', required=True), - 'period_id' : fields.many2one('account.period', 'From Period', required=True), - 'to_period_id': fields.many2one('account.period', 'To Period', required=True), - } - - _defaults = { - 'type': 'monthly', - } - - def print_vat_declaration_report(self, cr, uid, ids, context=None): - active_ids = context.get('active_ids',[]) - data = {} - data['form'] = {} - data['ids'] = active_ids - data['form']['tax_code_id'] = self.browse(cr, uid, ids)[0].tax_code_id.id - data['form']['period_id'] = self.browse(cr, uid, ids)[0].period_id.id - return { 'type': 'ir.actions.report.xml', 'report_name': 'l10n_lu.tax.report.print', 'datas': data} - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/wizard/print_vat_view.xml b/addons/l10n_lu/wizard/print_vat_view.xml deleted file mode 100644 index 61a29378163..00000000000 --- a/addons/l10n_lu/wizard/print_vat_view.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - VAT Declaration Report - vat.declaration.report - -

    - - - - - - -
    -
    -
    - - - - - VAT Declaration Report - ir.actions.act_window - vat.declaration.report - form - form - - new - - - - - - - - diff --git a/addons/l10n_pa/__openerp__.py b/addons/l10n_pa/__openerp__.py index 05e7ad5aefc..792c3de07ea 100644 --- a/addons/l10n_pa/__openerp__.py +++ b/addons/l10n_pa/__openerp__.py @@ -44,8 +44,6 @@ Con la Colaboración de ], "demo_xml": [ ], - "data": [ - ], "active": False, "installable": True, "certificate" : "", diff --git a/addons/lunch/__openerp__.py b/addons/lunch/__openerp__.py index f8a4a1ddcf2..955a1278c03 100644 --- a/addons/lunch/__openerp__.py +++ b/addons/lunch/__openerp__.py @@ -23,7 +23,7 @@ 'name': 'Lunch Orders', 'author': 'OpenERP SA', 'version': '0.2', - 'depends': ['base'], + 'depends': ['base', 'report'], 'category' : 'Tools', 'summary': 'Lunch Order, Meal, Food', 'description': """ diff --git a/addons/lunch/report/order.py b/addons/lunch/report/order.py index 0bb99f01017..85b216ac632 100644 --- a/addons/lunch/report/order.py +++ b/addons/lunch/report/order.py @@ -20,11 +20,11 @@ ############################################################################## import time -from openerp.addons.web import http -from openerp.addons.web.http import request +from openerp.report import report_sxw +from openerp.osv import osv -class order(http.Controller): +class order(report_sxw.rml_parse): def get_lines(self, user,objects): lines=[] @@ -60,24 +60,23 @@ class order(http.Controller): notes.append(obj.note) return notes - @http.route(['/report/lunch.report_lunchorder/'], type='http', auth='user', website=True, multilang=True) - def report_lunch(self, docids): - self.cr, self.uid, self.context = request.cr, request.uid, request.context - - ids = [int(i) for i in docids.split(',')] - report_obj = request.registry['lunch.order.line'] - docs = report_obj.browse(self.cr, self.uid, ids, context=self.context) - + def __init__(self, cr, uid, name, context): + super(order, self).__init__(cr, uid, name, context) self.net_total=0.0 - docargs = { - 'docs': docs, + self.localcontext.update({ 'time': time, 'get_lines': self.get_lines, 'get_users': self.get_users, 'get_total': self.get_total, 'get_nettotal': self.get_nettotal, 'get_note': self.get_note, - } - return request.registry['report'].render(self.cr, self.uid, [], 'lunch.report_lunchorder', docargs) + }) + + +class report_lunchorder(osv.AbstractModel): + _name = 'report.lunch.report_lunchorder' + _inherit = 'report.abstract_report' + _template = 'lunch.report_lunchorder' + _wrapped_report_class = order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/lunch/security/lunch_security.xml b/addons/lunch/security/lunch_security.xml index e01fab71ea2..5f2a351472c 100644 --- a/addons/lunch/security/lunch_security.xml +++ b/addons/lunch/security/lunch_security.xml @@ -16,5 +16,43 @@ + + + lunch.order: do not see and create other people's order + + + [('user_id', '=', user.id)] + + + lunch.order: do not see and create other people's order + + + [(1, '=', 1)] + + + lunch.order.line: do not see and create other people's order line + + + [('user_id', '=', user.id)] + + + lunch.order.line: do not see and create other people's order line + + + [(1, '=', 1)] + + + lunch.cashmove: do not see and create other people's cashmove + + + [('user_id', '=', user.id)] + + + lunch.cashmove: do not see and create other people's cashmove + + + [(1, '=', 1)] + + diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml index 4a2dc6d06f0..cdd7eb12c69 100644 --- a/addons/mail/data/mail_data.xml +++ b/addons/mail/data/mail_data.xml @@ -40,6 +40,17 @@ () + + + Open Messaging Menu + reload + + + + + open + + none diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 5a51bce04d9..aef0131346a 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -579,7 +579,7 @@ .openerp .oe_followers button.oe_follower{ display: block; text-align: center; - width:100%; + width:135px; } .openerp .oe_followers button.oe_follower.oe_following{ color: white; diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index e7c8ede6867..04f01efb8af 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -70,7 +70,17 @@ openerp_mail_followers = function(session, mail) { self.do_unfollow(); }); // event: click on a subtype, that (un)subscribe for this subtype - this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription); + this.$el.on('click', '.oe_subtype_list input', function(event) { + self.do_update_subscription(event); + var $list = self.$('.oe_subtype_list'); + if(!$list.hasClass('open')) { + $list.addClass('open'); + } + if(self.$('.oe_subtype_list ul')[0].children.length < 1) { + $list.removeClass('open'); + } + event.stopPropagation(); + }); // event: click on 'invite' button, that opens the invite wizard this.$('.oe_invite').on('click', self.on_invite_follower); // event: click on 'edit_subtype(pencil)' button to edit subscription @@ -244,8 +254,14 @@ openerp_mail_followers = function(session, mail) { if (user_pid) { dialog = true; } else { - var subtype_list_ul = this.$('.oe_subtype_list').empty(); - if (! this.message_is_follower) return; + var subtype_list_ul = this.$('.oe_subtype_list ul').empty(); + if (! this.message_is_follower) { + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true); + return; + } + else { + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false); + } } var id = this.view.datarecord.id; this.ds_model.call('message_get_subscription_data', [[id], user_pid, new session.web.CompoundContext(this.build_context(), {})]) @@ -259,9 +275,8 @@ openerp_mail_followers = function(session, mail) { var $list = self.$dialog; } else { - var $list = this.$('.oe_subtype_list'); + var $list = this.$('.oe_subtype_list ul'); } - $list.empty().hide(); var records = data[id].message_subtype_data; this.records_length = $.map(records, function(value, index) { return index; }).length; if (this.records_length > 1) { self.display_followers(); } @@ -276,15 +291,13 @@ openerp_mail_followers = function(session, mail) { } record.name = record_name; record.followed = record.followed || undefined; - $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo($list); + $(session.web.qweb.render('mail.followers.subtype', {'record': record, 'dialog': dialog})).appendTo($list); }); - if (_.size(records) > 1) { - $list.show(); - } }, do_follow: function () { var context = new session.web.CompoundContext(this.build_context(), {}); + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false); this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context]) .then(this.proxy('read_value')); @@ -294,11 +307,13 @@ openerp_mail_followers = function(session, mail) { }, do_unfollow: function (user_pid) { + var self = this; if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) { _(this.$('.oe_msg_subtype_check')).each(function (record) { $(record).attr('checked',false); }); var action_unsubscribe = 'message_unsubscribe_users'; + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true); var follower_ids = [this.session.uid]; if (user_pid) { action_unsubscribe = 'message_unsubscribe'; @@ -332,6 +347,8 @@ openerp_mail_followers = function(session, mail) { if (!checklist.length) { if (!this.do_unfollow(user_pid)) { $(event.target).attr("checked", "checked"); + } else { + self.$('.oe_subtype_list ul').empty(); } } else { var context = new session.web.CompoundContext(this.build_context(), {}); diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index 6e8682cb533..35a5ad320bb 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -5,17 +5,23 @@ followers main template Template used to display the followers, the actions and the subtypes in a record. --> -
    +
    - +
    + + + +
    +
    -

    Followers

    @@ -42,8 +48,12 @@ - - + +
    + + + +
    diff --git a/addons/mrp/__openerp__.py b/addons/mrp/__openerp__.py index ef68b27a489..859e676c68f 100644 --- a/addons/mrp/__openerp__.py +++ b/addons/mrp/__openerp__.py @@ -29,7 +29,7 @@ 'sequence': 18, 'summary': 'Manufacturing Orders, Bill of Materials, Routing', 'images': ['images/bill_of_materials.jpeg', 'images/manufacturing_order.jpeg', 'images/planning_manufacturing_order.jpeg', 'images/manufacturing_analysis.jpeg', 'images/production_dashboard.jpeg','images/routings.jpeg','images/work_centers.jpeg'], - 'depends': ['product','procurement', 'stock', 'resource', 'purchase','process'], + 'depends': ['product','procurement', 'stock', 'resource', 'purchase','process', 'report'], 'description': """ Manage the Manufacturing process in OpenERP =========================================== @@ -76,8 +76,6 @@ Dashboard / Reports for MRP will include: 'views/report_mrpbomstructure.xml', ], 'demo': ['mrp_demo.xml'], - #TODO: This yml tests are needed to be completely reviewed again because the product wood panel is removed in product demo as it does not suit for new demo context of computer and consultant company - # so the ymls are too complex to change at this stage 'test': [ 'test/bom_with_service_type_product.yml', 'test/mrp_users.yml', diff --git a/addons/mrp/report/bom_structure.py b/addons/mrp/report/bom_structure.py index 98949ed75dc..1b286feac46 100644 --- a/addons/mrp/report/bom_structure.py +++ b/addons/mrp/report/bom_structure.py @@ -19,22 +19,18 @@ # ############################################################################## +import time from openerp.osv import osv +from openerp.report import report_sxw -class bom_structure(osv.AbstractModel): - _name = 'report.mrp.report_mrpbomstructure' - - def render_html(self, cr, uid, ids, data=None, context=None): - mrpbom_obj = self.pool['mrp.bom'] - report_obj = self.pool['report'] - docs = mrpbom_obj.browse(cr, uid, ids, context=context) - - docargs = { - 'docs': docs, - 'get_children': self.get_children, - } - return report_obj.render(cr, uid, [], 'mrp.report_mrpbomstructure', docargs, context=context) +class bom_structure(report_sxw.rml_parse): + def __init__(self, cr, uid, name, context): + super(bom_structure, self).__init__(cr, uid, name, context=context) + self.localcontext.update({ + 'time': time, + 'get_children':self.get_children, + }) def get_children(self, object, level=0): result = [] @@ -62,4 +58,11 @@ class bom_structure(osv.AbstractModel): return children + +class report_lunchorder(osv.AbstractModel): + _name = 'report.mrp.report_mrpbomstructure' + _inherit = 'report.abstract_report' + _template = 'mpr.report_mrpbomstructure' + _wrapped_report_class = bom_structure + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 8cfe7b17939..9ddc4324659 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_account_analytic_line_user,account.analytic.line,account.model_account_analytic_line,group_mrp_user,1,1,1,0 access_mrp_workcenter,mrp.workcenter,model_mrp_workcenter,mrp.group_mrp_user,1,0,0,0 access_mrp_routing,mrp.routing,model_mrp_routing,mrp.group_mrp_user,1,0,0,0 access_mrp_routing_workcenter,mrp.routing.workcenter,model_mrp_routing_workcenter,mrp.group_mrp_user,1,0,0,0 diff --git a/addons/note/note.py b/addons/note/note.py index 7f03f43b36a..38b2395a852 100644 --- a/addons/note/note.py +++ b/addons/note/note.py @@ -116,7 +116,7 @@ class note_note(osv.osv): } _order = 'sequence' - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): if groupby and groupby[0]=="stage_id": #search all stages @@ -169,7 +169,7 @@ class note_note(osv.osv): else: return super(note_note, self).read_group(self, cr, uid, domain, fields, groupby, - offset=offset, limit=limit, context=context, orderby=orderby) + offset=offset, limit=limit, context=context, orderby=orderby,lazy=lazy) #upgrade config setting page to configure pad, fancy and tags mode diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 99752c864fa..f18edf39e85 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -517,7 +517,8 @@ class pos_order(osv.osv): # Keep only new orders submitted_references = [o['data']['name'] for o in orders] - existing_orders = self.search_read(cr, uid, domain=[('pos_reference', 'in', submitted_references)], fields=['pos_reference'], context=context) + existing_order_ids = self.search(cr, uid, [('pos_reference', 'in', submitted_references)], context=context) + existing_orders = self.read(cr, uid, existing_order_ids, ['pos_reference'], context=context) existing_references = set([o['pos_reference'] for o in existing_orders]) orders_to_save = [o for o in orders if o['data']['name'] not in existing_references] diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 5e3f8b54752..1e7076d9c8f 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -439,7 +439,8 @@ class procurement_order(osv.osv): if len(to_cancel): move_obj.action_cancel(cr, uid, to_cancel) if len(to_assign): - move_obj.write(cr, uid, to_assign, {'state': 'assigned'}) + move_obj.write(cr, uid, to_assign, {'state': 'confirmed'}) + move_obj.action_assign(cr, uid, to_assign) self.write(cr, uid, ids, {'state': 'cancel'}) for id in ids: workflow.trg_trigger(uid, 'procurement.order', id, cr) diff --git a/addons/procurement/schedulers.py b/addons/procurement/schedulers.py index d82fa94c132..b86a799e19c 100644 --- a/addons/procurement/schedulers.py +++ b/addons/procurement/schedulers.py @@ -59,7 +59,7 @@ class procurement_order(osv.osv): context = {} try: if use_new_cursor: - cr = openerp.registry(use_new_cursor).db.cursor() + cr = openerp.registry(use_new_cursor).cursor() procurement_obj = self.pool.get('procurement.order') if not skip_exception: @@ -199,7 +199,7 @@ class procurement_order(osv.osv): if context is None: context = {} if use_new_cursor: - cr = openerp.registry(use_new_cursor).db.cursor() + cr = openerp.registry(use_new_cursor).cursor() orderpoint_obj = self.pool.get('stock.warehouse.orderpoint') procurement_obj = self.pool.get('procurement.order') diff --git a/addons/procurement/wizard/orderpoint_procurement.py b/addons/procurement/wizard/orderpoint_procurement.py index afc8e2a721f..c8d41c5c655 100644 --- a/addons/procurement/wizard/orderpoint_procurement.py +++ b/addons/procurement/wizard/orderpoint_procurement.py @@ -49,7 +49,7 @@ class procurement_compute(osv.osv_memory): """ proc_obj = self.pool.get('procurement.order') #As this function is in a new thread, I need to open a new cursor, because the old one may be closed - new_cr = self.pool.db.cursor() + new_cr = self.pool.cursor() for proc in self.browse(new_cr, uid, ids, context=context): proc_obj._procure_orderpoint_confirm(new_cr, uid, automatic=proc.automatic, use_new_cursor=new_cr.dbname, context=context) #close the new cursor diff --git a/addons/procurement/wizard/schedulers_all.py b/addons/procurement/wizard/schedulers_all.py index aab9657ae5d..c0f1cfcc2df 100644 --- a/addons/procurement/wizard/schedulers_all.py +++ b/addons/procurement/wizard/schedulers_all.py @@ -45,7 +45,7 @@ class procurement_compute_all(osv.osv_memory): """ proc_obj = self.pool.get('procurement.order') #As this function is in a new thread, i need to open a new cursor, because the old one may be closed - new_cr = self.pool.db.cursor() + new_cr = self.pool.cursor() for proc in self.browse(new_cr, uid, ids, context=context): proc_obj.run_scheduler(new_cr, uid, automatic=proc.automatic, use_new_cursor=new_cr.dbname,\ context=context) diff --git a/addons/product/i18n/pl.po b/addons/product/i18n/pl.po index ac059f0a556..9e9b65a8545 100644 --- a/addons/product/i18n/pl.po +++ b/addons/product/i18n/pl.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0dev_rc3\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-21 17:06+0000\n" -"PO-Revision-Date: 2012-12-16 19:25+0000\n" -"Last-Translator: Grzegorz Grzelak (OpenGLOBE.pl) \n" +"PO-Revision-Date: 2014-04-07 13:25+0000\n" +"Last-Translator: Dariusz Żbikowski (Krokus) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-27 06:41+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-08 06:18+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: product #: field:product.packaging,rows:0 @@ -735,7 +735,7 @@ msgstr "Jeśli zaznaczone, to wiadomość wymaga twojej uwagi" #. module: product #: field:product.product,ean13:0 msgid "EAN13 Barcode" -msgstr "" +msgstr "Kod kreskowy EAN13" #. module: product #: model:ir.actions.act_window,name:product.action_product_price_list @@ -1188,7 +1188,7 @@ msgstr "Wiadomości i historia komunikacji" #. module: product #: model:product.uom,name:product.product_uom_kgm msgid "kg" -msgstr "" +msgstr "kg" #. module: product #: selection:product.template,state:0 @@ -1198,7 +1198,7 @@ msgstr "Zdezaktualizowany" #. module: product #: model:product.uom,name:product.product_uom_km msgid "km" -msgstr "" +msgstr "km" #. module: product #: field:product.template,standard_price:0 @@ -1354,6 +1354,8 @@ msgid "" "This field holds the image used as image for the product, limited to " "1024x1024px." msgstr "" +"To pole utrzymuje obraz użyty jako zdjęcie produktu, limitowany rozmiar " +"1024x1024." #. module: product #: help:product.pricelist.item,categ_id:0 @@ -1519,7 +1521,7 @@ msgstr "" #. module: product #: model:product.uom,name:product.product_uom_cm msgid "cm" -msgstr "" +msgstr "cm" #. module: product #: model:ir.model,name:product.model_product_uom diff --git a/addons/product_email_template/__openerp__.py b/addons/product_email_template/__openerp__.py index 2fdce7f2889..9b7af6f992b 100644 --- a/addons/product_email_template/__openerp__.py +++ b/addons/product_email_template/__openerp__.py @@ -10,7 +10,7 @@ Add email templates to products to be send on invoice confirmation ================================================================== With this module, link your products to a template to send complete information and tools to your customer. -For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.' +For instance when invoicing a training, the training agenda and materials will automatically be sent to your customers.' """, 'website': 'http://www.openerp.com', 'demo': [ diff --git a/addons/product_email_template/models/product.py b/addons/product_email_template/models/product.py index cafdef7ab9d..6b463ffbeb5 100644 --- a/addons/product_email_template/models/product.py +++ b/addons/product_email_template/models/product.py @@ -13,7 +13,7 @@ class product_template(osv.Model): _columns = { 'email_template_id': fields.many2one( 'email.template', 'Product Email Template', - help='When validating an invoice, an email will be send to the customer' + help='When validating an invoice, an email will be sent to the customer' 'based on this template. The customer will receive an email for each' 'product linked to an email template.'), } diff --git a/addons/project/project.py b/addons/project/project.py index 9dcf069a856..5c6143148d4 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -287,7 +287,9 @@ class project(osv.osv): "- Followers Only: employees see only the followed tasks or issues; if portal\n" " is activated, portal users see the followed tasks or issues."), 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), - 'doc_count':fields.function(_get_attached_docs, string="Number of documents attached", type='int') + 'doc_count': fields.function( + _get_attached_docs, string="Number of documents attached", type='integer' + ) } def _get_type_common(self, cr, uid, context): @@ -723,9 +725,10 @@ class task(osv.osv): context = {} if default is None: default = {} - stage = self._get_default_stage_id(cr, uid, context=context) - if stage: - default['stage_id'] = stage + if not context.get('copy', False): + stage = self._get_default_stage_id(cr, uid, context=context) + if stage: + default['stage_id'] = stage return super(task, self).copy(cr, uid, id, default, context) def _is_template(self, cr, uid, ids, field_name, arg, context=None): @@ -749,7 +752,7 @@ class task(osv.osv): 'description': fields.text('Description'), 'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True), 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."), - 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', + 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', select=True, domain="[('project_ids', '=', project_id)]"), 'categ_ids': fields.many2many('project.category', string='Tags'), 'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready for next stage')], 'Kanban State', @@ -765,7 +768,7 @@ class task(osv.osv): 'date_end': fields.datetime('Ending Date',select=True), 'date_deadline': fields.date('Deadline',select=True), 'date_last_stage_update': fields.datetime('Last Stage Update', select=True), - 'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select="1", track_visibility='onchange', change_default=True), + 'project_id': fields.many2one('project.project', 'Project', ondelete='set null', select=True, track_visibility='onchange', change_default=True), 'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'), 'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'), 'notes': fields.text('Notes'), @@ -791,7 +794,7 @@ class task(osv.osv): 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['work_ids', 'remaining_hours', 'planned_hours'], 10), 'project.task.work': (_get_task, ['hours'], 10), }), - 'user_id': fields.many2one('res.users', 'Assigned to', track_visibility='onchange'), + 'user_id': fields.many2one('res.users', 'Assigned to', select=True, track_visibility='onchange'), 'delegated_user_id': fields.related('child_ids', 'user_id', type='many2one', relation='res.users', string='Delegated To'), 'partner_id': fields.many2one('res.partner', 'Customer'), 'work_ids': fields.one2many('project.task.work', 'task_id', 'Work done'), @@ -1045,7 +1048,7 @@ class task(osv.osv): if vals.get('project_id') and not context.get('default_project_id'): context['default_project_id'] = vals.get('project_id') # user_id change: update date_start - if vals.get('user_id'): + if vals.get('user_id') and not vals.get('start_date'): vals['date_start'] = fields.datetime.now() # context: no_log, because subtype already handle this @@ -1062,7 +1065,7 @@ class task(osv.osv): if 'stage_id' in vals: vals['date_last_stage_update'] = fields.datetime.now() # user_id change: update date_start - if vals.get('user_id'): + if vals.get('user_id') and 'date_start' not in vals: vals['date_start'] = fields.datetime.now() # Overridden to reset the kanban_state to normal whenever diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 08738227f5a..3ee673a4d2f 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -381,7 +381,7 @@ - + diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 84abc33a7e6..bfc65ca7d88 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -264,9 +264,9 @@ class project_issue(osv.Model): 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True), 'version_id': fields.many2one('project.issue.version', 'Version'), 'stage_id': fields.many2one ('project.task.type', 'Stage', - track_visibility='onchange', + track_visibility='onchange', select=True, domain="[('project_ids', '=', project_id)]"), - 'project_id':fields.many2one('project.project', 'Project', track_visibility='onchange'), + 'project_id': fields.many2one('project.project', 'Project', track_visibility='onchange', select=True), 'duration': fields.float('Duration'), 'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"), 'day_open': fields.function(_compute_day, string='Days to Open', \ diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index 0d0a372a3d0..009cbf00b78 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -46,7 +46,7 @@ Dashboard / Reports for Purchase Management will include: 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images' : ['images/purchase_order.jpeg', 'images/purchase_analysis.jpeg', 'images/request_for_quotation.jpeg'], - 'depends': ['stock', 'process', 'procurement'], + 'depends': ['stock', 'process', 'procurement', 'report'], 'data': [ 'security/purchase_security.xml', 'security/ir.model.access.csv', diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py index 87db14c5a90..0d293631a1a 100644 --- a/addons/purchase/res_config.py +++ b/addons/purchase/res_config.py @@ -62,7 +62,7 @@ class purchase_config_settings(osv.osv_memory): } _defaults = { - 'default_invoice_method': 'manual', + 'default_invoice_method': 'order', } def onchange_purchase_analytic_plans(self, cr, uid, ids, module_purchase_analytic_plans, context=None): diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index 5ce57dab811..319cceb1e1a 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -107,7 +107,7 @@ class purchase_requisition(osv.osv): seller_delay = product_supplier.delay seller_qty = product_supplier.qty supplier_pricelist = supplier.property_product_pricelist_purchase or False - seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, False, {'uom': default_uom_po_id})[supplier_pricelist.id] + seller_price = pricelist.price_get(cr, uid, [supplier_pricelist.id], product.id, qty, supplier.id, {'uom': default_uom_po_id})[supplier_pricelist.id] if seller_qty: qty = max(qty,seller_qty) date_planned = self._planned_date(requisition_line.requisition_id, seller_delay) diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index 5cff7b4aae2..d3a683cccdc 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -22,48 +22,43 @@ from openerp.addons.web.http import Controller, route, request import simplejson -import urlparse -from werkzeug import exceptions +from werkzeug import exceptions, url_decode +from werkzeug.test import Client +from werkzeug.wrappers import BaseResponse +from werkzeug.datastructures import Headers from reportlab.graphics.barcode import createBarcodeDrawing class ReportController(Controller): #------------------------------------------------------ - # Generic reports controller + # Report controllers #------------------------------------------------------ - @route('/report//', type='http', auth='user', website=True, multilang=True) - def report_html(self, reportname, docids): - cr, uid, context = request.cr, request.uid, request.context - docids = self._eval_params(docids) - return request.registry['report'].get_html(cr, uid, docids, reportname, context=context) - - @route('/report/pdf/report//', type='http', auth="user", website=True) - def report_pdf(self, reportname, docids): - cr, uid, context = request.cr, request.uid, request.context - docids = self._eval_params(docids) - pdf = request.registry['report'].get_pdf(cr, uid, docids, reportname, context=context) - pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] - return request.make_response(pdf, headers=pdfhttpheaders) - - #------------------------------------------------------ - # Particular reports controller - #------------------------------------------------------ - @route('/report/', type='http', auth='user', website=True, multilang=True) - def report_html_particular(self, reportname, **data): - cr, uid, context = request.cr, request.uid, request.context + @route([ + '/report//', + '/report///', + ], type='http', auth='user', website=True, multilang=True) + def report_routes(self, reportname, docids=None, converter=None, **data): report_obj = request.registry['report'] - data = self._eval_params(data) # Sanitizing - return report_obj.get_html(cr, uid, [], reportname, data=data, context=context) - - @route('/report/pdf/report/', type='http', auth='user', website=True, multilang=True) - def report_pdf_particular(self, reportname, **data): cr, uid, context = request.cr, request.uid, request.context - report_obj = request.registry['report'] - data = self._eval_params(data) # Sanitizing - pdf = report_obj.get_pdf(cr, uid, [], reportname, data=data, context=context) - pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] - return request.make_response(pdf, headers=pdfhttpheaders) + + if docids: + docids = [int(i) for i in docids.split(',')] + options_data = None + if data.get('options'): + options_data = simplejson.loads(data['options']) + if data.get('context'): + context.update(simplejson.loads(data['context'])) + + if converter == 'html': + html = report_obj.get_html(cr, uid, docids, reportname, data=options_data, context=context) + return request.make_response(html) + elif converter == 'pdf': + pdf = report_obj.get_pdf(cr, uid, docids, reportname, data=options_data, context=context) + pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] + return request.make_response(pdf, headers=pdfhttpheaders) + else: + raise exceptions.HTTPException(description='Converter %s not implemented.' % converter) #------------------------------------------------------ # Misc. route utils @@ -94,7 +89,7 @@ class ReportController(Controller): @route(['/report/download'], type='http', auth="user", website=True) def report_download(self, data, token): """This function is used by 'qwebactionmanager.js' in order to trigger the download of - a pdf report. + a pdf/controller report. :param data: a javascript array JSON.stringified containg report internal url ([0]) and type [1] @@ -102,26 +97,26 @@ class ReportController(Controller): """ requestcontent = simplejson.loads(data) url, type = requestcontent[0], requestcontent[1] - if type == 'qweb-pdf': - reportname = url.split('/report/pdf/report/')[1].split('?')[0].split('/')[0] - if '?' not in url: + if type == 'qweb-pdf': + reportname = url.split('/report/pdf/')[1].split('?')[0] + + docids = None + if '/' in reportname: + reportname, docids = reportname.split('/') + + if docids: # Generic report: - docids = url.split('/')[-1] - response = self.report_pdf(reportname, docids) + response = self.report_routes(reportname, docids=docids, converter='pdf') else: # Particular report: - querystring = url.split('?')[1] - querystring = dict(urlparse.parse_qsl(querystring)) - response = self.report_pdf_particular(reportname, **querystring) + data = url_decode(url.split('?')[1]).items() # decoding the args represented in JSON + response = self.report_routes(reportname, converter='pdf', **dict(data)) response.headers.add('Content-Disposition', 'attachment; filename=%s.pdf;' % reportname) response.set_cookie('fileToken', token) return response elif type =='controller': - from werkzeug.test import Client - from werkzeug.wrappers import BaseResponse - from werkzeug.datastructures import Headers reqheaders = Headers(request.httprequest.headers) response = Client(request.httprequest.app, BaseResponse).get(url, headers=reqheaders, follow_redirects=True) response.set_cookie('fileToken', token) @@ -132,28 +127,3 @@ class ReportController(Controller): @route(['/report/check_wkhtmltopdf'], type='json', auth="user") def check_wkhtmltopdf(self): return request.registry['report']._check_wkhtmltopdf() - - def _eval_params(self, param): - """Parse a dict generated by the webclient (javascript) into a python dict. - """ - if isinstance(param, dict): - for key, value in param.iteritems(): - if value.lower() == 'false': - param[key] = False - elif value.lower() == 'true': - param[key] = True - elif ',' in value: - param[key] = [int(i) for i in value.split(',')] - else: - try: - param[key] = int(value) - except (ValueError, TypeError): - pass - else: - if isinstance(param, (str, unicode)): - param = [int(i) for i in param.split(',')] - if isinstance(param, list): - param = list(set(param)) - if isinstance(param, int): - param = [param] - return param diff --git a/addons/report/models/__init__.py b/addons/report/models/__init__.py index e048e10eb91..d21f03e5bcb 100644 --- a/addons/report/models/__init__.py +++ b/addons/report/models/__init__.py @@ -1,2 +1,3 @@ import report import report_paperformat +import abstract_report diff --git a/addons/report/models/abstract_report.py b/addons/report/models/abstract_report.py new file mode 100644 index 00000000000..2da32b6c0f6 --- /dev/null +++ b/addons/report/models/abstract_report.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import osv + + +class AbstractReport(osv.AbstractModel): + """Model used to embed old style reports""" + _name = 'report.abstract_report' + _template = None + _wrapped_report_class = None + + def render_html(self, cr, uid, ids, data=None, context=None): + if context is None: + context = {} + + # If the key 'landscape' is present in data['form'], passing it into the context + if data and data.get('form', {}).get('landscape'): + context['landscape'] = True + + if context and context.get('active_ids'): + # Browse the selected objects via their reference in context + model = context.get('active_model') or context.get('model') + objects_model = self.pool[model] + objects = objects_model.browse(cr, uid, context['active_ids'], context=context) + else: + # If no context is set (for instance, during test execution), build one + model = self.pool['report']._get_report_from_name(cr, uid, self._template).model + objects_model = self.pool[model] + objects = objects_model.browse(cr, uid, ids, context=context) + context['active_model'] = model + context['active_ids'] = ids + + # Generate the old style report + wrapped_report = self._wrapped_report_class(cr, uid, '', context=context) + wrapped_report.set_context(objects, data, context['active_ids']) + + # Rendering self._template with the wrapped report instance localcontext as + # rendering environment + docargs = wrapped_report.localcontext + docargs['docs'] = docargs.get('objects') + + # Used in template translating (see render_doc method from report model) + docargs['doc_ids'] = context['active_ids'] + docargs['doc_model'] = model + + return self.pool['report'].render(cr, uid, [], self._template, docargs, context=context) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 8abe8e544eb..8dd8a4dce6f 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -20,9 +20,10 @@ ############################################################################## from openerp.osv import osv +from openerp.tools import config from openerp.tools.translate import _ -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, config -from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field +from openerp.addons.web.http import request +from openerp.tools.safe_eval import safe_eval as eval import os import time @@ -34,8 +35,6 @@ import tempfile import lxml.html import cStringIO import subprocess -from datetime import datetime -from functools import partial from distutils.version import LooseVersion try: from pyPdf import PdfFileWriter, PdfFileReader @@ -46,7 +45,7 @@ except ImportError: _logger = logging.getLogger(__name__) -"""Check the presence of wkhtmltopdf and return its version.""" +"""Check the presence of wkhtmltopdf and return its version at OpnerERP start-up.""" wkhtmltopdf_state = 'install' try: process = subprocess.Popen( @@ -70,98 +69,26 @@ class Report(osv.Model): public_user = None + MINIMAL_HTML_PAGE = """ + + + + + + + + + + {subst} + + + {body} + +""" + #-------------------------------------------------------------------------- # Extension of ir_ui_view.render with arguments frequently used in reports #-------------------------------------------------------------------------- - - def _get_digits(self, cr, uid, obj=None, f=None, dp=None): - d = DEFAULT_DIGITS = 2 - if dp: - decimal_precision_obj = self.pool['decimal.precision'] - ids = decimal_precision_obj.search(cr, uid, [('name', '=', dp)]) - if ids: - d = decimal_precision_obj.browse(cr, uid, ids)[0].digits - elif obj and f: - res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16, DEFAULT_DIGITS))) - if isinstance(res_digits, tuple): - d = res_digits[1] - else: - d = res_digits(cr)[1] - elif (hasattr(obj, '_field') and - isinstance(obj._field, (float_field, function_field)) and - obj._field.digits): - d = obj._field.digits[1] or DEFAULT_DIGITS - return d - - def _get_lang_dict(self, cr, uid): - pool_lang = self.pool['res.lang'] - lang = self.localcontext.get('lang', 'en_US') or 'en_US' - lang_ids = pool_lang.search(cr, uid, [('code', '=', lang)])[0] - lang_obj = pool_lang.browse(cr, uid, lang_ids) - lang_dict = { - 'lang_obj': lang_obj, - 'date_format': lang_obj.date_format, - 'time_format': lang_obj.time_format - } - self.lang_dict.update(lang_dict) - self.default_lang[lang] = self.lang_dict.copy() - return True - - def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False, currency_obj=False, cr=None, uid=None): - """ - Assuming 'Account' decimal.precision=3: - formatLang(value) -> digits=2 (default) - formatLang(value, digits=4) -> digits=4 - formatLang(value, dp='Account') -> digits=3 - formatLang(value, digits=5, dp='Account') -> digits=5 - """ - def get_date_length(date_format=DEFAULT_SERVER_DATE_FORMAT): - return len((datetime.now()).strftime(date_format)) - - if digits is None: - if dp: - digits = self._get_digits(cr, uid, dp=dp) - else: - digits = self._get_digits(cr, uid, value) - - if isinstance(value, (str, unicode)) and not value: - return '' - - if not self.lang_dict_called: - self._get_lang_dict(cr, uid) - self.lang_dict_called = True - - if date or date_time: - if not str(value): - return '' - - date_format = self.lang_dict['date_format'] - parse_format = DEFAULT_SERVER_DATE_FORMAT - if date_time: - value = value.split('.')[0] - date_format = date_format + " " + self.lang_dict['time_format'] - parse_format = DEFAULT_SERVER_DATETIME_FORMAT - if isinstance(value, basestring): - # FIXME: the trimming is probably unreliable if format includes day/month names - # and those would need to be translated anyway. - date = datetime.strptime(value[:get_date_length(parse_format)], parse_format) - elif isinstance(value, time.struct_time): - date = datetime(*value[:6]) - else: - date = datetime(*value.timetuple()[:6]) - if date_time: - # Convert datetime values to the expected client/context timezone - date = datetime_field.context_timestamp(cr, uid, timestamp=date, context=self.localcontext) - return date.strftime(date_format.encode('utf-8')) - - res = self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary) - if currency_obj: - if currency_obj.position == 'after': - res = '%s %s' % (res, currency_obj.symbol) - elif currency_obj and currency_obj.position == 'before': - res = '%s %s' % (currency_obj.symbol, res) - return res - def render(self, cr, uid, ids, template, values=None, context=None): """Allow to render a QWeb template python-side. This function returns the 'ir.ui.view' render but embellish it with some variables/methods used in reports. @@ -175,28 +102,19 @@ class Report(osv.Model): if context is None: context = {} - self.lang_dict = self.default_lang = {} - self.lang_dict_called = False - self.localcontext = { - 'lang': context.get('lang'), - 'tz': context.get('tz'), - 'uid': context.get('uid'), - } - self._get_lang_dict(cr, uid) - view_obj = self.pool['ir.ui.view'] - def render_doc(doc_id, model, template): - """Helper used when a report should be translated into the associated - partner's lang. + def translate_doc(doc_id, model, lang_field, template): + """Helper used when a report should be translated into a specific lang. - + :param doc_id: id of the record to translate :param model: model of the record to translate - :param template: name of the template to translate into the partner's lang + :param lang_field': field of the record containing the lang + :param template: name of the template to translate into the lang_field """ ctx = context.copy() doc = self.pool[model].browse(cr, uid, doc_id, context=ctx) @@ -205,26 +123,28 @@ class Report(osv.Model): if ctx.get('translatable') is True: qcontext['o'] = doc else: - ctx['lang'] = doc.partner_id.lang + # Reach the lang we want to translate the doc into + ctx['lang'] = eval('doc.%s' % lang_field, {'doc': doc}) qcontext['o'] = self.pool[model].browse(cr, uid, doc_id, context=ctx) return view_obj.render(cr, uid, template, qcontext, context=ctx) + user = self.pool['res.users'].browse(cr, uid, uid) + website = None + if request and hasattr(request, 'website'): + website = request.website values.update({ 'time': time, - 'formatLang': partial(self.formatLang, cr=cr, uid=uid), - 'get_digits': self._get_digits, - 'render_doc': render_doc, + 'translate_doc': translate_doc, 'editable': True, # Will active inherit_branding - 'res_company': self.pool['res.users'].browse(cr, uid, uid).company_id, - 'website': False, # Will be overidden by ir.ui.view if the request has website enabled + 'user': user, + 'res_company': user.company_id, + 'website': website, }) - return view_obj.render(cr, uid, template, values, context=context) #-------------------------------------------------------------------------- - # Main reports methods + # Main report methods #-------------------------------------------------------------------------- - def get_html(self, cr, uid, ids, report_name, data=None, context=None): """This method generates and returns html version of a report. """ @@ -233,7 +153,7 @@ class Report(osv.Model): try: report_model_name = 'report.%s' % report_name particularreport_obj = self.pool[report_model_name] - return particularreport_obj.render_html(cr, uid, ids, data={'form': data}, context=context) + return particularreport_obj.render_html(cr, uid, ids, data=data, context=context) except KeyError: report = self._get_report_from_name(cr, uid, report_name) report_obj = self.pool[report.model] @@ -254,15 +174,122 @@ class Report(osv.Model): if html is None: html = self.get_html(cr, uid, ids, report_name, data=data, context=context) - html = html.decode('utf-8') + html = html.decode('utf-8') # Ensure the current document is utf-8 encoded. # Get the ir.actions.report.xml record we are working on. report = self._get_report_from_name(cr, uid, report_name) + # Check if we have to save the report or if we have to get one from the db. + save_in_attachment = self._check_attachment_use(cr, uid, ids, report) + # Get the paperformat associated to the report, otherwise fallback on the company one. + if not report.paperformat_id: + user = self.pool['res.users'].browse(cr, uid, uid) + paperformat = user.company_id.paperformat_id + else: + paperformat = report.paperformat_id - # Check attachment_use field. If set to true and an existing pdf is already saved, load - # this one now. Else, mark save it. + # Preparing the minimal html pages + subst = " " + css = '' # Will contain local css + headerhtml = [] + contenthtml = [] + footerhtml = [] + base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') + + # The received html report must be simplified. We convert it in a xml tree + # in order to extract headers, bodies and footers. + try: + root = lxml.html.fromstring(html) + + for node in root.xpath("//html/head/style"): + css += node.text + + for node in root.xpath("//div[@class='header']"): + body = lxml.html.tostring(node) + header = self.MINIMAL_HTML_PAGE.format(css=css, subst=subst, body=body, base_url=base_url) + headerhtml.append(header) + + for node in root.xpath("//div[@class='footer']"): + body = lxml.html.tostring(node) + footer = self.MINIMAL_HTML_PAGE.format(css=css, subst=subst, body=body, base_url=base_url) + footerhtml.append(footer) + + for node in root.xpath("//div[@class='page']"): + # Previously, we marked some reports to be saved in attachment via their ids, so we + # must set a relation between report ids and report's content. We use the QWeb + # branding in order to do so: searching after a node having a data-oe-model + # attribute with the value of the current report model and read its oe-id attribute + oemodelnode = node.find(".//*[@data-oe-model='%s']" % report.model) + if oemodelnode is not None: + reportid = oemodelnode.get('data-oe-id') + if reportid: + reportid = int(reportid) + else: + reportid = False + + body = lxml.html.tostring(node) + reportcontent = self.MINIMAL_HTML_PAGE.format(css=css, subst='', body=body, base_url=base_url) + + # FIXME: imo the best way to extract record id from html reports is by using the + # qweb branding. As website editor is not yet splitted in a module independant from + # website, when we print a unique report we can use the id passed in argument to + # identify it. + if ids and len(ids) == 1: + reportid = ids[0] + + contenthtml.append(tuple([reportid, reportcontent])) + + except lxml.etree.XMLSyntaxError: + contenthtml = [] + contenthtml.append(html) + save_in_attachment = {} # Don't save this potentially malformed document + + # Get paperformat arguments set in the root html tag. They are prioritized over + # paperformat-record arguments. + specific_paperformat_args = {} + for attribute in root.items(): + if attribute[0].startswith('data-report-'): + specific_paperformat_args[attribute[0]] = attribute[1] + + # Run wkhtmltopdf process + pdf = self._generate_wkhtml_pdf( + cr, uid, headerhtml, footerhtml, contenthtml, context.get('landscape'), + paperformat, specific_paperformat_args, save_in_attachment + ) + return pdf + + def get_action(self, cr, uid, ids, report_name, data=None, context=None): + """Return an action of type ir.actions.report.xml. + + :param report_name: Name of the template to generate an action for + """ + if context is None: + context = {} + + report_obj = self.pool['ir.actions.report.xml'] + idreport = report_obj.search(cr, uid, [('report_name', '=', report_name)], context=context) + try: + report = report_obj.browse(cr, uid, idreport[0], context=context) + except IndexError: + raise osv.except_osv(_('Bad Report'), _('This report is not loaded into the database.')) + + action = { + 'context': context, + 'data': data, + 'type': 'ir.actions.report.xml', + 'report_name': report.report_name, + 'report_type': report.report_type, + 'report_file': report.report_file, + } + return action + + #-------------------------------------------------------------------------- + # Report generation helpers + #-------------------------------------------------------------------------- + def _check_attachment_use(self, cr, uid, ids, report): + """ Check attachment_use field. If set to true and an existing pdf is already saved, load + this one now. Else, mark save it. + """ save_in_attachment = {} - if report.attachment_use is True: save_in_attachment['model'] = report.model save_in_attachment['loaded_documents'] = {} @@ -287,132 +314,8 @@ class Report(osv.Model): _logger.info('The PDF document %s was loaded from the database' % filename) else: # Mark current document to be saved - save_in_attachment[id] = filename - - # Get the paperformat associated to the report, otherwise fallback on the company one. - if not report.paperformat_id: - user = self.pool['res.users'].browse(cr, uid, uid) - paperformat = user.company_id.paperformat_id - else: - paperformat = report.paperformat_id - - # Preparing the minimal html pages - #subst = self._get_url_content('/report/static/src/js/subst.js')[0] # Used in age numbering - subst = " " - css = '' # Will contain local css - - headerhtml = [] - contenthtml = [] - footerhtml = [] - base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') - - minimalhtml = """ - - - - - - - - - - {subst} - - - {body} - -""" - - # The retrieved html report must be simplified. We convert it into a xml tree - # via lxml in order to extract headers, footers and content. - try: - root = lxml.html.fromstring(html) - - for node in root.xpath("//html/head/style"): - css += node.text - - for node in root.xpath("//div[@class='header']"): - body = lxml.html.tostring(node) - header = minimalhtml.format(css=css, subst=subst, body=body, base_url=base_url) - headerhtml.append(header) - - for node in root.xpath("//div[@class='footer']"): - body = lxml.html.tostring(node) - footer = minimalhtml.format(css=css, subst=subst, body=body, base_url=base_url) - footerhtml.append(footer) - - for node in root.xpath("//div[@class='page']"): - # Previously, we marked some reports to be saved in attachment via their ids, so we - # must set a relation between report ids and report's content. We use the QWeb - # branding in order to do so: searching after a node having a data-oe-model - # attribute with the value of the current report model and read its oe-id attribute - oemodelnode = node.find(".//*[@data-oe-model='%s']" % report.model) - if oemodelnode is not None: - reportid = oemodelnode.get('data-oe-id') - if reportid: - reportid = int(reportid) - else: - reportid = False - - body = lxml.html.tostring(node) - reportcontent = minimalhtml.format(css=css, subst='', body=body, base_url=base_url) - contenthtml.append(tuple([reportid, reportcontent])) - - except lxml.etree.XMLSyntaxError: - contenthtml = [] - contenthtml.append(html) - save_in_attachment = {} # Don't save this potentially malformed document - - # Get paperformat arguments set in the root html tag. They are prioritized over - # paperformat-record arguments. - specific_paperformat_args = {} - for attribute in root.items(): - if attribute[0].startswith('data-report-'): - specific_paperformat_args[attribute[0]] = attribute[1] - - # Run wkhtmltopdf process - pdf = self._generate_wkhtml_pdf( - cr, uid, headerhtml, footerhtml, contenthtml, context.get('landscape'), - paperformat, specific_paperformat_args, save_in_attachment - ) - return pdf - - def get_action(self, cr, uid, ids, report_name, datas=None, context=None): - """Return an action of type ir.actions.report.xml. - - :param report_name: Name of the template to generate an action for - """ - # TODO: return the action for the ids passed in args - if context is None: - context = {} - - if datas is None: - datas = {} - - report_obj = self.pool.get('ir.actions.report.xml') - idreport = report_obj.search(cr, uid, [('report_name', '=', report_name)], context=context) - - try: - report = report_obj.browse(cr, uid, idreport[0], context=context) - except IndexError: - raise osv.except_osv(_('Bad Report'), - _('This report is not loaded into the database.')) - - action = { - 'type': 'ir.actions.report.xml', - 'report_name': report.report_name, - 'report_type': report.report_type, - 'report_file': report.report_file, - } - - if datas: - action['datas'] = datas - - return action - - #-------------------------------------------------------------------------- - # Report generation helpers - #-------------------------------------------------------------------------- + save_in_attachment[record_id] = filename + return save_in_attachment def _check_wkhtmltopdf(self): return wkhtmltopdf_state @@ -436,8 +339,8 @@ class Report(osv.Model): # Passing the cookie to wkhtmltopdf in order to resolve URL. try: - from openerp.addons.web.http import request - command_args.extend(['--cookie', 'session_id', request.session.sid]) + if request: + command_args.extend(['--cookie', 'session_id', request.session.sid]) except AttributeError: pass @@ -445,6 +348,8 @@ class Report(osv.Model): if paperformat: command_args.extend(self._build_wkhtmltopdf_args(paperformat, spec_paperformat_args)) + command_args.extend(['--load-error-handling', 'ignore']) + if landscape and '--orientation' in command_args: command_args_copy = list(command_args) for index, elem in enumerate(command_args_copy): @@ -464,7 +369,7 @@ class Report(osv.Model): # Directly load the document if we have it if save_in_attachment and save_in_attachment['loaded_documents'].get(reporthtml[0]): pdfreport.write(save_in_attachment['loaded_documents'].get(reporthtml[0])) - pdfreport.flush() + pdfreport.seek(0) pdfdocuments.append(pdfreport) continue @@ -473,7 +378,7 @@ class Report(osv.Model): head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.', dir=tmp_dir, mode='w+') head_file.write(headers[index]) - head_file.flush() + head_file.seek(0) command_arg_local.extend(['--header-html', head_file.name]) # Footer stuff @@ -481,14 +386,14 @@ class Report(osv.Model): foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.', dir=tmp_dir, mode='w+') foot_file.write(footers[index]) - foot_file.flush() + foot_file.seek(0) command_arg_local.extend(['--footer-html', foot_file.name]) # Body stuff content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.', dir=tmp_dir, mode='w+') content_file.write(reporthtml[1]) - content_file.flush() + content_file.seek(0) try: # If the server is running with only one worker, ask to create a secund to be able @@ -525,7 +430,7 @@ class Report(osv.Model): _logger.info('The PDF document %s is now saved in the ' 'database' % attachment['name']) - pdfreport.flush() + pdfreport.seek(0) pdfdocuments.append(pdfreport) if headers: @@ -566,15 +471,24 @@ class Report(osv.Model): command_args.extend(['--page-size', paperformat.format]) if paperformat.page_height and paperformat.page_width and paperformat.format == 'custom': - command_args.extend(['--page-width', str(paperformat.page_width) + 'in']) - command_args.extend(['--page-height', str(paperformat.page_height) + 'in']) + command_args.extend(['--page-width', str(paperformat.page_width) + 'mm']) + command_args.extend(['--page-height', str(paperformat.page_height) + 'mm']) - if specific_paperformat_args and specific_paperformat_args['data-report-margin-top']: - command_args.extend(['--margin-top', - str(specific_paperformat_args['data-report-margin-top'])]) + if specific_paperformat_args and specific_paperformat_args.get('data-report-margin-top'): + command_args.extend(['--margin-top', str(specific_paperformat_args['data-report-margin-top'])]) elif paperformat.margin_top: command_args.extend(['--margin-top', str(paperformat.margin_top)]) + if specific_paperformat_args and specific_paperformat_args.get('data-report-dpi'): + command_args.extend(['--dpi', str(specific_paperformat_args['data-report-dpi'])]) + elif paperformat.dpi: + command_args.extend(['--dpi', str(paperformat.dpi)]) + + if specific_paperformat_args and specific_paperformat_args.get('data-report-header-spacing'): + command_args.extend(['--header-spacing', str(specific_paperformat_args['data-report-header-spacing'])]) + elif paperformat.header_spacing: + command_args.extend(['--header-spacing', str(paperformat.header_spacing)]) + if paperformat.margin_left: command_args.extend(['--margin-left', str(paperformat.margin_left)]) if paperformat.margin_bottom: @@ -583,12 +497,8 @@ class Report(osv.Model): command_args.extend(['--margin-right', str(paperformat.margin_right)]) if paperformat.orientation: command_args.extend(['--orientation', str(paperformat.orientation)]) - if paperformat.header_spacing: - command_args.extend(['--header-spacing', str(paperformat.header_spacing)]) if paperformat.header_line: command_args.extend(['--header-line']) - if paperformat.dpi: - command_args.extend(['--dpi', str(paperformat.dpi)]) return command_args diff --git a/addons/report/models/report_paperformat.py b/addons/report/models/report_paperformat.py index e3e747b81a4..6b84f3d3363 100644 --- a/addons/report/models/report_paperformat.py +++ b/addons/report/models/report_paperformat.py @@ -69,8 +69,8 @@ class report_paperformat(osv.Model): 'margin_bottom': fields.integer('Bottom Margin (mm)'), 'margin_left': fields.integer('Left Margin (mm)'), 'margin_right': fields.integer('Right Margin (mm)'), - 'page_height': fields.integer('Page height (in)'), - 'page_width': fields.integer('Page width (in)'), + 'page_height': fields.integer('Page height (mm)'), + 'page_width': fields.integer('Page width (mm)'), 'orientation': fields.selection([('Landscape', 'Landscape'), ('Portrait', 'Portrait')], 'Orientation'), diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js index b75003942d2..7e55661be86 100644 --- a/addons/report/static/src/js/qwebactionmanager.js +++ b/addons/report/static/src/js/qwebactionmanager.js @@ -1,13 +1,20 @@ openerp.report = function(instance) { var wkhtmltopdf_state; + var trigger_download = function(session, response, c) { + session.get_file({ + url: '/report/download', + data: {data: JSON.stringify(response)}, + complete: openerp.web.unblockUI, + error: c.rpc_error.bind(c) + }); + } + instance.web.ActionManager = instance.web.ActionManager.extend({ ir_actions_report_xml: function(action, options) { var self = this; instance.web.blockUI(); action = _.clone(action); - var eval_contexts = ([instance.session.user_context] || []).concat([action.context]); - action.context = instance.web.pyeval.eval('contexts',eval_contexts); _t = instance.web._t; // QWeb reports @@ -15,49 +22,40 @@ openerp.report = function(instance) { var report_url = ''; switch (action.report_type) { case 'qweb-html': - report_url = '/report/' + action.report_name; + report_url = '/report/html/' + action.report_name; break; case 'qweb-pdf': - report_url = '/report/pdf/report/' + action.report_name; + report_url = '/report/pdf/' + action.report_name; break; case 'controller': report_url = action.report_file; break; default: - report_url = '/report/' + action.report_name; + report_url = '/report/html/' + action.report_name; break; } - // single/multiple id(s): no query string - // wizard: query string of action.datas.form - if (!('datas' in action)) { + // generic report: no query string + // particular: query string of action.data.form and context + if (!('data' in action) || !(action.data)) { if ('active_ids' in action.context) { report_url += "/" + action.context.active_ids.join(','); } } else { - _.each(action.datas.form, function(value, key) { - // will be erased when all wizards are rewritten - if (key.substring(0, 12) === 'used_context') { - delete action.datas.form[key]; - } - - if ($.type(value) === 'array') { - action.datas.form[key] = value.join(','); - } - }); - report_url += "?" + $.param(action.datas.form); + report_url += "?options=" + encodeURIComponent(JSON.stringify(action.data)); + report_url += "&context=" + encodeURIComponent(JSON.stringify(action.context)); } + + var response = new Array(); + response[0] = report_url; + response[1] = action.report_type; + var c = openerp.webclient.crashmanager; + if (action.report_type == 'qweb-html') { - // Open the html report in a popup window.open(report_url, '_blank', 'height=900,width=1280'); instance.web.unblockUI(); - return; } else { // Trigger the download of the pdf/controller report - var c = openerp.webclient.crashmanager; - var response = new Array(); - response[0] = report_url; - response[1] = action.report_type; if (action.report_type == 'qweb-pdf') { (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) { @@ -66,8 +64,10 @@ openerp.report = function(instance) { self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \ system. The report will be shown in html.

    \ wkhtmltopdf.org'), true); - window.open(report_url.substring(12), '_blank', 'height=768,width=1024'); + report_url = report_url.substring(12) + window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024'); instance.web.unblockUI(); + return; } else { if (presence == 'upgrade') { self.do_notify(_t('Report'), _t('You should upgrade your version of\ @@ -75,22 +75,13 @@ openerp.report = function(instance) { support for table-breaking between pages.

    wkhtmltopdf.org'), true); } - self.session.get_file({ - url: '/report/download', - data: {data: JSON.stringify(response)}, - complete: openerp.web.unblockUI, - error: c.rpc_error.bind(c) - }); } + return trigger_download(self.session, response, c); }); - } else { - self.session.get_file({ - url: '/report/download', - data: {data: JSON.stringify(response)}, - complete: openerp.web.unblockUI, - error: c.rpc_error.bind(c) - }); - } + } + else if (action.report_type == 'controller') { + return trigger_download(self.session, response, c); + } } } else { return self._super(action, options); diff --git a/addons/report/tests/test_reports.py b/addons/report/tests/test_reports.py index dda14442709..b1853489573 100644 --- a/addons/report/tests/test_reports.py +++ b/addons/report/tests/test_reports.py @@ -1,5 +1,23 @@ # -*- coding: utf-8 -*- - +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## import logging import openerp @@ -11,26 +29,24 @@ _logger = logging.getLogger(__name__) @openerp.tests.common.post_install(True) class TestReports(openerp.tests.TransactionCase): def test_reports(self): - return # commented out until post_install tests are working - registry, cr, uid = self.registry, self.cr, self.uid r_model = registry('ir.actions.report.xml') domain = [('report_type', 'like', 'qweb')] for r in r_model.browse(cr, uid, r_model.search(cr, uid, domain)): report_model = 'report.%s' % r.report_name - particular_model = registry('ir.model').search(cr, uid, [('model', '=', report_model)]) - + try: + registry(report_model) + except KeyError: # Only test the generic reports here - if particular_model: + _logger.info("testing report %s", r.report_name) + report_model = registry(r.model) + report_model_ids = report_model.search(cr, uid, [], limit=10) + if not report_model_ids: + _logger.info("no record found skipping report %s", r.report_name) + if not r.multi: + report_model_ids = report_model_ids[:1] + + # Test report generation + registry('report').get_html(cr, uid, report_model_ids, r.report_name) + else: continue - - _logger.info("testing report %s", r.report_name) - report_model = registry(r.model) - report_model_ids = report_model.search(cr, uid, [], limit=10) - if not report_model_ids: - _logger.info("no record found skipping report %s", r.report_name) - if not r.multi: - report_model_ids = report_model_ids[:1] - - # Test report generation - registry('report').get_html(cr, uid, report_model_ids, r.report_name) diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml index 588775fc41e..4f5104c726b 100644 --- a/addons/report/views/layouts.xml +++ b/addons/report/views/layouts.xml @@ -6,7 +6,10 @@ + t-att-data-main-object="repr(main_object) if editable else None" + t-att-data-report-margin-top="data_report_margin_top if data_report_margin_top else None" + t-att-data-report-header-spacing="data_report_header_spacing if data_report_header_spacing else None" + t-att-data-report-dpi="data_report_dpi if data_report_dpi else None"> @@ -64,6 +67,9 @@ .table-condensed > thead > tr > th { border-bottom: 1px solid black !important; } + .zero_min_height { + min-height: 0px !important; + } + diff --git a/addons/report_intrastat/__init__.py b/addons/report_intrastat/__init__.py index d2f598434a2..119777f2c70 100644 --- a/addons/report_intrastat/__init__.py +++ b/addons/report_intrastat/__init__.py @@ -20,7 +20,5 @@ ############################################################################## import report_intrastat -import report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/report_intrastat/__openerp__.py b/addons/report_intrastat/__openerp__.py index 0fa57977db1..4682a777ccc 100644 --- a/addons/report_intrastat/__openerp__.py +++ b/addons/report_intrastat/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Intrastat Reporting', 'version': '1.0', @@ -37,7 +36,8 @@ European Union.""", 'security/ir.model.access.csv', 'report_intrastat_view.xml', 'intrastat_report.xml', - 'report_intrastat_data.xml' + 'report_intrastat_data.xml', + 'views/report_intrastatinvoice.xml' ], 'demo': [], 'test': ['test/report_intrastat_report.yml'], @@ -45,4 +45,5 @@ European Union.""", 'auto_install': False, 'images': ['images/country_intrastat_code.jpeg','images/intrastat_code.jpeg'], } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/intrastat_report.xml b/addons/report_intrastat/intrastat_report.xml index 124cf899efb..c5a8e9e7f84 100644 --- a/addons/report_intrastat/intrastat_report.xml +++ b/addons/report_intrastat/intrastat_report.xml @@ -1,13 +1,13 @@ - - - + + + - - diff --git a/addons/report_intrastat/report/__init__.py b/addons/report_intrastat/report/__init__.py deleted file mode 100644 index 64e530bc278..00000000000 --- a/addons/report_intrastat/report/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -import invoice -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/report/invoice.py b/addons/report_intrastat/report/invoice.py deleted file mode 100644 index c38a62774ac..00000000000 --- a/addons/report_intrastat/report/invoice.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import time -from openerp.report import report_sxw - -class account_invoice_intrastat(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(account_invoice_intrastat, self).__init__(cr, uid, name, context=context) - self.total=0 - self.localcontext.update({ - 'time': time, - }) - -report_sxw.report_sxw('report.account.invoice.intrastat', 'account.invoice', 'addons/report_intrastat/report/invoice.rml', parser=account_invoice_intrastat) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/report/invoice.rml b/addons/report_intrastat/report/invoice.rml deleted file mode 100644 index fc410e04ce0..00000000000 --- a/addons/report_intrastat/report/invoice.rml +++ /dev/null @@ -1,401 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.partner_id.lang) ]] - -
    - - - - - [[ (o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]] - [[ o.partner_id and display_address(o.partner_id) ]] - - - - Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]] - Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]] - VAT : [[ (o.partner_id.vat) or removeParentNode('para') ]] -
    - Document - - Invoice Date - - Partner Ref. -
    - [[ o.name or ' ' ]] - - [[ formatLang(o.date_invoice,date=True) ]] - - [[ (o.partner_id.ref) or ' ' ]] -
    - Description - - Taxes - - Intrastat - - Weight - - Quantity - - Unit Price - - Disc. (%) - - Price -
    - [[ l.name ]] - - [[ ', '.join([lt.name for lt in l.invoice_line_tax_id]) ]] - - [[l.product_id and l.product_id.intrastat_id and l.product_id.intrastat_id.name or '']] - - [[ l.product_id and l.product_id.weight or '']] - - [[ formatLang(l.quantity) ]] [[ (l.uos_id and l.uos_id.name) or '' ]] - - [[ formatLang(l.price_unit) ]] - - [[ l.discount and formatLang (l.discount) or '' ]] - - [[ formatLang(l.price_subtotal, currency_obj=o.currency_id) ]] -
    - [[ format(l.note or removeParentNode('tr')) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - Total (excl. taxes): - - [[ formatLang(o.amount_untaxed, currency_obj=o.currency_id) ]] -
    - - - - - Taxes: - - [[ formatLang(o.amount_tax, currency_obj=o.currency_id) ]] -
    - - - - - Total (inclu. taxes): - - [[ formatLang(o.amount_total, currency_obj=o.currency_id) ]] -
    - Tax [[ o.tax_line==[] and removeParentNode('blockTable') ]] - - Base - - Amount - - - - -
    - [[ t.name ]] - - [[ formatLang(t.base, digits=get_digits(dp='Account'), currency_obj = o.currency_id) ]] - - [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - -
    - Fiscal Position Remark : - - [[ (o.fiscal_position and o.fiscal_position.note and format(o.fiscal_position.note)) or removeParentNode('blockTable') ]] -
    @@ -973,7 +985,7 @@ -
    +
    diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index b5402c3e285..913fbfb76ae 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -12,11 +12,12 @@ class Ecommerce(Ecommerce): cr, uid, context = request.cr, request.uid, request.context order = self.get_order() carrier_id = post.get('carrier_id') - - if order and carrier_id: - # recompute delivery costs - request.registry['website']._check_carrier_quotation(cr,uid,order,carrier_id,context=context) - return request.redirect("/shop/payment") + if carrier_id: + carrier_id = int(carrier_id) + if order: + request.registry['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=carrier_id, context=context) + if carrier_id: + return request.redirect("/shop/payment") res = super(Ecommerce, self).payment(**post) return res diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 9074e6768ea..c6ac851d9d4 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -56,6 +56,57 @@ class SaleOrder(orm.Model): ), } + def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): + carrier_obj = self.pool.get('delivery.carrier') + + # check to add or remove carrier_id + if not order: + return False + if all(line.product_id.type == "service" for line in order.website_order_line): + order.write({'carrier_id': None}, context=context) + self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, [order.id], context=context) + return True + else: + carrier_id = force_carrier_id or order.carrier_id.id + carrier_ids = self._get_delivery_methods(cr, uid, order, context=context) + if carrier_id: + if carrier_id not in carrier_ids: + carrier_id = False + else: + carrier_ids.remove(carrier_id) + carrier_ids.insert(0, carrier_id) + if force_carrier_id or not carrier_id or not carrier_id in carrier_ids: + for delivery_id in carrier_ids: + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) + if grid_id: + carrier_id = delivery_id + break + order.write({'carrier_id': carrier_id}, context=context) + if carrier_id: + order.delivery_set(context=context) + else: + order._delivery_unset(context=context) + + return bool(carrier_id) + + def _get_delivery_methods(self, cr, uid, order, context=None): + carrier_obj = self.pool.get('delivery.carrier') + delivery_ids = carrier_obj.search(cr, uid, [('website_published','=',True)], context=context) + # Following loop is done to avoid displaying delivery methods who are not available for this order + # This can surely be done in a more efficient way, but at the moment, it mimics the way it's + # done in delivery_set method of sale.py, from delivery module + for delivery_id in list(delivery_ids): + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) + if not grid_id: + delivery_ids.remove(delivery_id) + return delivery_ids + + def _get_errors(self, cr, uid, order, context=None): + errors = super(SaleOrder, self)._get_errors(cr, uid, order, context=context) + if not self._get_delivery_methods(cr, uid, order, context=context): + errors.append(('No delivery method available', 'There is no available delivery method for your order')) + return errors + def _get_website_data(self, cr, uid, order, context=None): """ Override to add delivery-related website data. """ values = super(SaleOrder, self)._get_website_data(cr, uid, order, context=context) @@ -69,6 +120,7 @@ class SaleOrder(orm.Model): delivery_ctx = dict(context, order_id=order.id) DeliveryCarrier = self.pool.get('delivery.carrier') - delivery_ids = DeliveryCarrier.search(cr, uid, [('website_published','=',True)], context=context) + delivery_ids = self._get_delivery_methods(cr, uid, order, context=context) + values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx) return values diff --git a/addons/website_sale_delivery/models/website.py b/addons/website_sale_delivery/models/website.py index 5c4585de17f..efd8b2233d2 100644 --- a/addons/website_sale_delivery/models/website.py +++ b/addons/website_sale_delivery/models/website.py @@ -9,7 +9,7 @@ class Website(orm.Model): def _ecommerce_create_quotation(self, cr, uid, context=None): order_id = super(Website, self)._ecommerce_create_quotation(cr, uid, context=context) order = self.pool['sale.order'].browse(cr, SUPERUSER_ID, order_id, context=context) - self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) + self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) return order_id def _ecommerce_add_product_to_cart(self, cr, uid, product_id=0, order_line_id=0, number=1, set_number=-1, context=None): @@ -17,31 +17,4 @@ class Website(orm.Model): product_id=product_id, order_line_id=order_line_id, number=number, set_number=set_number, context=context) order = self.ecommerce_get_current_order(cr, uid, context=context) - return self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None - - def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): - # check to add or remove carrier_id - carrier_id = False - for line in order.website_order_line: - if line.product_id.type != "service": - carrier_id = True - break - - if not carrier_id: - order.write({'carrier_id': None}, context=context) - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - return True - else: - if order.carrier_id: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) - carrier_id = force_carrier_id or (carrier_ids and carrier_ids[0]) - order.write({'carrier_id': carrier_id}, context=context) - #If carrier_id have no grid, we don't have delivery ! - if carrier_id: - order.delivery_set(context=context) - else: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - return bool(carrier_id) + return self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None