- 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
-
- 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') ]]
-
-
- [[ 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) ]]
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') ]]
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') ]]
- [[ 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))}) ]]
-
[[ (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))}) ]]
-
[[ (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))}) ]]
-
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') ]]
- 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') ]]
-
- [[ (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 '']]
-
- 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') ]]
-
- [[ (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 '']]
-
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') ]]
-
[[ data['model']=='account.journal.period'and 'Company' or removeParentNode('para') ]]
- [[ data['model']=='ir.ui.menu' and 'Chart of Accounts' or removeParentNode('para') ]]
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') ]]
[[ 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) ]]
- 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') ]]
-
- 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') ]]
-
- [[ 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) ]]
-
- [[ 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))) ]]
-
- [[ 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) ]]
-
-
-
-
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/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/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/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/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 cc661f2bf7f..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
===========================================
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/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/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;
+ }
@@ -84,11 +90,11 @@
-
+
-
+
@@ -158,5 +164,6 @@
+
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') ]]
-
-
-
- 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 ]]
-
-
-
-
-
-
- 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
-
-
-
-
- [[ repeatIn(o.invoice_line,'l') ]]
-
-
-
- [[ 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 '' ]]
-