[MERGE] forward port of branch saas-4 up to revid 9410 chs@openerp.com-20140507164207-kmme4tsrd4w1m7l1
bzr revid: chs@openerp.com-20140507170112-bjeltv2b0coy60am
This commit is contained in:
commit
b8089a1521
|
@ -409,7 +409,7 @@ 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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_invoice', context=context)
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account.report_invoice', context=context)
|
||||
|
||||
def action_invoice_sent(self, cr, uid, ids, context=None):
|
||||
'''
|
||||
|
|
|
@ -1040,7 +1040,7 @@ class account_move_line(osv.osv):
|
|||
if opening_reconciliation:
|
||||
obj_move_rec.write(cr, uid, unlink_ids, {'opening_reconciliation': False})
|
||||
obj_move_rec.unlink(cr, uid, unlink_ids)
|
||||
if all_moves:
|
||||
if len(all_moves) >= 2:
|
||||
obj_move_line.reconcile_partial(cr, uid, all_moves, 'auto',context=context)
|
||||
return True
|
||||
|
||||
|
|
|
@ -50,6 +50,6 @@ class account_analytic_balance(osv.osv_memory):
|
|||
|
||||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_analyticbalance', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -49,6 +49,6 @@ class account_analytic_cost_ledger_journal_report(osv.osv_memory):
|
|||
}
|
||||
|
||||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_analyticcostledgerquantity', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -49,6 +49,6 @@ class account_analytic_cost_ledger(osv.osv_memory):
|
|||
|
||||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_analyticcostledger', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -47,6 +47,6 @@ class account_analytic_inverted_balance(osv.osv_memory):
|
|||
'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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_invertedanalyticbalance', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -57,7 +57,7 @@ class account_analytic_journal_report(osv.osv_memory):
|
|||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_analyticjournal', data=datas, context=context2)
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
if context is None:
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Quantity</th>
|
||||
<th groups="product.group_uom">Unit of measure</th>
|
||||
<th class="text-right">Unit Price</th>
|
||||
<th class="text-right" groups="sale.group_discount_per_so_line">Discount (%)</th>
|
||||
<th class="text-right">Taxes</th>
|
||||
|
@ -57,8 +56,10 @@
|
|||
<tbody class="invoice_tbody">
|
||||
<tr t-foreach="o.invoice_line" t-as="l">
|
||||
<td><span t-field="l.name"/></td>
|
||||
<td><span t-field="l.quantity"/></td>
|
||||
<td groups="product.group_uom"><span t-field="l.uos_id"/></td>
|
||||
<td>
|
||||
<span t-field="l.quantity"/>
|
||||
<span t-field="l.uos_id" groups="product.group_uom"/>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="l.price_unit"/>
|
||||
</td>
|
||||
|
@ -100,7 +101,7 @@
|
|||
</div>
|
||||
|
||||
<div class="row" t-if="o.tax_line">
|
||||
<div class="col-xs-3">
|
||||
<div class="col-xs-6">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -136,7 +137,7 @@
|
|||
</p>
|
||||
<p t-if="o.fiscal_position">
|
||||
<strong>Fiscal Position:</strong>
|
||||
<span t-field="o.fiscal_position.note"/>
|
||||
<span t-field="o.fiscal_position"/>
|
||||
</p>
|
||||
</div>
|
||||
</t>
|
||||
|
|
|
@ -89,6 +89,6 @@ class accounting_report(osv.osv_memory):
|
|||
|
||||
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 self.pool['report'].get_action(cr, uid, ids, 'account.report_financial', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_financial', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class account_balance_report(osv.osv_memory):
|
||||
_inherit = "account.common.account.report"
|
||||
_name = 'account.balance.report'
|
||||
|
@ -36,6 +37,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 self.pool['report'].get_action(cr, uid, ids, 'account.report_trialbalance', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_trialbalance', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -81,6 +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 self.pool['report'].get_action(cr, uid, ids, 'account.report_agedpartnerbalance', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_agedpartnerbalance', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class account_central_journal(osv.osv_memory):
|
||||
_name = 'account.central.journal'
|
||||
_description = 'Account Central Journal'
|
||||
|
@ -32,6 +33,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 self.pool['report'].get_action(cr, uid, ids, 'account.report_centraljournal', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_centraljournal', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class account_general_journal(osv.osv_memory):
|
||||
_inherit = "account.common.journal.report"
|
||||
_name = 'account.general.journal'
|
||||
|
@ -32,6 +33,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 self.pool['report'].get_action(cr, uid, ids, 'account.report_generaljournal', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_generaljournal', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -59,6 +59,6 @@ class account_report_general_ledger(osv.osv_memory):
|
|||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_generalledger', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -44,6 +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 self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerbalance', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_partnerbalance', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -58,7 +58,7 @@ class account_partner_ledger(osv.osv_memory):
|
|||
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'].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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_partnerledgerother', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_partnerledger', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -67,8 +67,8 @@ class account_print_journal(osv.osv_memory):
|
|||
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'):
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account.report_salepurchasejournal', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_salepurchasejournal', data=data, context=context)
|
||||
else:
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account.report_journal', data=data, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_journal', data=data, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -61,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', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_vat', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -652,12 +652,10 @@ class account_analytic_account(osv.osv):
|
|||
'nodestroy': True,
|
||||
}
|
||||
|
||||
def _prepare_invoice(self, cr, uid, contract, context=None):
|
||||
def _prepare_invoice_data(self, cr, uid, contract, context=None):
|
||||
context = context or {}
|
||||
|
||||
inv_obj = self.pool.get('account.invoice')
|
||||
journal_obj = self.pool.get('account.journal')
|
||||
fpos_obj = self.pool.get('account.fiscal.position')
|
||||
|
||||
if not contract.partner_id:
|
||||
raise osv.except_osv(_('No Customer Defined!'),_("You must first select a Customer for Contract %s!") % contract.name )
|
||||
|
@ -678,33 +676,36 @@ class account_analytic_account(osv.osv):
|
|||
elif contract.company_id:
|
||||
currency_id = contract.company_id.currency_id.id
|
||||
|
||||
inv_data = {
|
||||
'reference': contract.code or False,
|
||||
invoice = {
|
||||
'account_id': contract.partner_id.property_account_receivable.id,
|
||||
'type': 'out_invoice',
|
||||
'partner_id': contract.partner_id.id,
|
||||
'currency_id': currency_id,
|
||||
'journal_id': len(journal_ids) and journal_ids[0] or False,
|
||||
'date_invoice': contract.recurring_next_date,
|
||||
'origin': contract.name,
|
||||
'origin': contract.code,
|
||||
'fiscal_position': fpos and fpos.id,
|
||||
'payment_term': partner_payment_term,
|
||||
'company_id': contract.company_id.id or False,
|
||||
}
|
||||
invoice_id = inv_obj.create(cr, uid, inv_data, context=context)
|
||||
return invoice
|
||||
|
||||
def _prepare_invoice_lines(self, cr, uid, contract, fiscal_position_id, context=None):
|
||||
fpos_obj = self.pool.get('account.fiscal.position')
|
||||
fiscal_position = fpos_obj.browse(cr, uid, fiscal_position_id, context=context)
|
||||
invoice_lines = []
|
||||
for line in contract.recurring_invoice_line_ids:
|
||||
|
||||
res = line.product_id
|
||||
account_id = res.property_account_income.id
|
||||
if not account_id:
|
||||
account_id = res.categ_id.property_account_income_categ.id
|
||||
account_id = fpos_obj.map_account(cr, uid, fpos, account_id)
|
||||
account_id = fpos_obj.map_account(cr, uid, fiscal_position, account_id)
|
||||
|
||||
taxes = res.taxes_id or False
|
||||
tax_id = fpos_obj.map_tax(cr, uid, fpos, taxes)
|
||||
tax_id = fpos_obj.map_tax(cr, uid, fiscal_position, taxes)
|
||||
|
||||
invoice_line_vals = {
|
||||
invoice_lines.append((0, 0, {
|
||||
'name': line.name,
|
||||
'account_id': account_id,
|
||||
'account_analytic_id': contract.id,
|
||||
|
@ -712,13 +713,14 @@ class account_analytic_account(osv.osv):
|
|||
'quantity': line.quantity,
|
||||
'uos_id': line.uom_id.id or False,
|
||||
'product_id': line.product_id.id or False,
|
||||
'invoice_id' : invoice_id,
|
||||
'invoice_line_tax_id': [(6, 0, tax_id)],
|
||||
}
|
||||
self.pool.get('account.invoice.line').create(cr, uid, invoice_line_vals, context=context)
|
||||
}))
|
||||
return invoice_lines
|
||||
|
||||
inv_obj.button_compute(cr, uid, [invoice_id], context=context)
|
||||
return invoice_id
|
||||
def _prepare_invoice(self, cr, uid, contract, context=None):
|
||||
invoice = self._prepare_invoice_data(cr, uid, contract, context=context)
|
||||
invoice['invoice_line'] = self._prepare_invoice_lines(cr, uid, contract, invoice['fiscal_position'], context=context)
|
||||
return invoice
|
||||
|
||||
def recurring_create_invoice(self, cr, uid, ids, context=None):
|
||||
return self._recurring_create_invoice(cr, uid, ids, context=context)
|
||||
|
@ -728,6 +730,7 @@ class account_analytic_account(osv.osv):
|
|||
|
||||
def _recurring_create_invoice(self, cr, uid, ids, automatic=False, context=None):
|
||||
context = context or {}
|
||||
invoice_ids = []
|
||||
current_date = time.strftime('%Y-%m-%d')
|
||||
if ids:
|
||||
contract_ids = ids
|
||||
|
@ -735,8 +738,8 @@ class account_analytic_account(osv.osv):
|
|||
contract_ids = self.search(cr, uid, [('recurring_next_date','<=', current_date), ('state','=', 'open'), ('recurring_invoices','=', True), ('type', '=', 'contract')])
|
||||
for contract in self.browse(cr, uid, contract_ids, context=context):
|
||||
try:
|
||||
invoice_id = self._prepare_invoice(cr, uid, contract, context=context)
|
||||
|
||||
invoice_values = self._prepare_invoice(cr, uid, contract, context=context)
|
||||
invoice_ids.append(self.pool['account.invoice'].create(cr, uid, invoice_values, context=context))
|
||||
next_date = datetime.datetime.strptime(contract.recurring_next_date or current_date, "%Y-%m-%d")
|
||||
interval = contract.recurring_interval
|
||||
if contract.recurring_rule_type == 'daily':
|
||||
|
@ -754,7 +757,7 @@ class account_analytic_account(osv.osv):
|
|||
_logger.error(traceback.format_exc())
|
||||
else:
|
||||
raise
|
||||
return True
|
||||
return invoice_ids
|
||||
|
||||
class account_analytic_account_summary_user(osv.osv):
|
||||
_name = "account_analytic_analysis.summary.user"
|
||||
|
|
|
@ -24,6 +24,7 @@ import time
|
|||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class account_crossovered_analytic(osv.osv_memory):
|
||||
_name = "account.crossovered.analytic"
|
||||
_description = "Print Crossovered Analytic"
|
||||
|
@ -65,6 +66,6 @@ class account_crossovered_analytic(osv.osv_memory):
|
|||
'model': 'account.analytic.account',
|
||||
'form': data
|
||||
}
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account_analytic_plans.report_crossoveredanalyticplans', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_analytic_plans.report_crossoveredanalyticplans', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -46,6 +46,6 @@ class account_budget_analytic(osv.osv_memory):
|
|||
'form': data
|
||||
}
|
||||
datas['form']['ids'] = datas['ids']
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_analyticaccountbudget', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_budget.report_analyticaccountbudget', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -47,6 +47,6 @@ class account_budget_crossvered_report(osv.osv_memory):
|
|||
}
|
||||
datas['form']['ids'] = datas['ids']
|
||||
datas['form']['report'] = 'analytic-full'
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_budget.report_crossoveredbudget', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -49,6 +49,6 @@ class account_budget_crossvered_summary_report(osv.osv_memory):
|
|||
}
|
||||
datas['form']['ids'] = datas['ids']
|
||||
datas['form']['report'] = 'analytic-one'
|
||||
return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_budget.report_crossoveredbudget', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -47,6 +47,6 @@ class account_budget_report(osv.osv_memory):
|
|||
}
|
||||
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)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_budget.report_budget', data=datas, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -74,26 +74,17 @@ class account_voucher(osv.osv):
|
|||
|
||||
def print_check(self, cr, uid, ids, context=None):
|
||||
if not ids:
|
||||
return {}
|
||||
raise osv.except_osv(_('Printing error'), _('No check selected '))
|
||||
|
||||
check_layout_report = {
|
||||
'top' : 'account.print.check.top',
|
||||
'middle' : 'account.print.check.middle',
|
||||
'bottom' : 'account.print.check.bottom',
|
||||
data = {
|
||||
'id': ids and ids[0],
|
||||
'ids': ids,
|
||||
}
|
||||
|
||||
check_layout = self.browse(cr, uid, ids[0], context=context).company_id.check_layout
|
||||
return {
|
||||
'type': 'ir.actions.report.xml',
|
||||
'report_name':check_layout_report[check_layout],
|
||||
'datas': {
|
||||
'model':'account.voucher',
|
||||
'id': ids and ids[0] or False,
|
||||
'ids': ids and ids or [],
|
||||
'report_type': 'pdf'
|
||||
},
|
||||
'nodestroy': True
|
||||
}
|
||||
return self.pool['report'].get_action(
|
||||
cr, uid, [], 'account_check_writing.report_check', data=data, context=context
|
||||
)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if vals.get('amount') and vals.get('journal_id') and 'amount_in_word' not in vals:
|
||||
vals['amount_in_word'] = self._amount_to_text(cr, uid, vals['amount'], vals.get('currency_id') or \
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class account_check_write(osv.osv_memory):
|
||||
_name = 'account.check.write'
|
||||
_description = 'Prin Check in Batch'
|
||||
|
@ -64,23 +64,11 @@ class account_check_write(osv.osv_memory):
|
|||
ir_sequence_obj.write(cr, uid, sequence_id, {'number_next': new_value})
|
||||
|
||||
#print the checks
|
||||
check_layout_report = {
|
||||
'top' : 'account.print.check.top',
|
||||
'middle' : 'account.print.check.middle',
|
||||
'bottom' : 'account.print.check.bottom',
|
||||
data = {
|
||||
'id': voucher_ids and voucher_ids[0],
|
||||
'ids': voucher_ids,
|
||||
}
|
||||
check_layout = voucher_obj.browse(cr, uid, voucher_ids[0], context=context).company_id.check_layout
|
||||
if not check_layout:
|
||||
check_layout = 'top'
|
||||
return {
|
||||
'type': 'ir.actions.report.xml',
|
||||
'report_name':check_layout_report[check_layout],
|
||||
'datas': {
|
||||
'model':'account.voucher',
|
||||
'ids': voucher_ids,
|
||||
'report_type': 'pdf'
|
||||
},
|
||||
'nodestroy': True
|
||||
}
|
||||
|
||||
|
||||
return self.pool['report'].get_action(
|
||||
cr, uid, [], 'account_check_writing.report_check', data=data, context=context
|
||||
)
|
||||
|
|
|
@ -188,7 +188,7 @@ class res_partner(osv.osv):
|
|||
'model': 'account_followup.followup',
|
||||
'form': data
|
||||
}
|
||||
return self.pool['report'].get_action(cr, uid, wizard_partner_ids, 'account_followup.report_followup', data=datas, context=context)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account_followup.report_followup', data=datas, context=context)
|
||||
|
||||
def do_partner_mail(self, cr, uid, partner_ids, context=None):
|
||||
if context is None:
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<field name="name" />
|
||||
<field name="client_id" />
|
||||
<field name="enabled" />
|
||||
<field name="body" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="auth_endpoint" />
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<record model="crm.case.stage" id="stage_lead2">
|
||||
<field name="name">Dead</field>
|
||||
<field name="case_default">1</field>
|
||||
<field name="fold">1</field>
|
||||
<field name="probability">0</field>
|
||||
<field name="on_change">1</field>
|
||||
<field name="sequence">30</field>
|
||||
|
|
|
@ -88,7 +88,7 @@ Find duplicates, merge leads and assign them to the right salesperson in one ope
|
|||
<p class="oe_mt32">
|
||||
Get your opportunities organized to stay focused on the best deals. Manage all your customer interactions from the opportunity like emails, phone calls, internal notes, meetings and quotations.
|
||||
</p><p>
|
||||
Follow opportunities that interrests you to get notified upon specific events: deal won or lost, stage changed, new customer demand, etc.
|
||||
Follow opportunities that interest you to get notified upon specific events: deal won or lost, stage changed, new customer demand, etc.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -217,15 +217,7 @@ class gamification_challenge(osv.Model):
|
|||
vals['user_ids'] = []
|
||||
vals['user_ids'] += [(4, user_id) for user_id in user_ids]
|
||||
|
||||
create_res = super(gamification_challenge, self).create(cr, uid, vals, context=context)
|
||||
|
||||
# subscribe new users to the challenge
|
||||
if vals.get('user_ids'):
|
||||
# done with browse after super to be sure catch all after orm process
|
||||
challenge = self.browse(cr, uid, create_res, context=context)
|
||||
self.message_subscribe_users(cr, uid, [challenge.id], [user.id for user in challenge.user_ids], context=context)
|
||||
|
||||
return create_res
|
||||
return super(gamification_challenge, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int,long)):
|
||||
|
@ -240,6 +232,11 @@ class gamification_challenge(osv.Model):
|
|||
|
||||
write_res = super(gamification_challenge, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
if vals.get('report_message_frequency', 'never') != 'never':
|
||||
# _recompute_challenge_users do not set users for challenges with no reports, subscribing them now
|
||||
for challenge in self.browse(cr, uid, ids, context=context):
|
||||
self.message_subscribe(cr, uid, [challenge.id], [user.partner_id.id for user in challenge.user_ids], context=context)
|
||||
|
||||
if vals.get('state') == 'inprogress':
|
||||
self._recompute_challenge_users(cr, uid, ids, context=context)
|
||||
self._generate_goals_from_challenge(cr, uid, ids, context=context)
|
||||
|
@ -264,6 +261,9 @@ class gamification_challenge(osv.Model):
|
|||
- Create the missing goals (eg: modified the challenge to add lines)
|
||||
- Update every running challenge
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
# start scheduled challenges
|
||||
planned_challenge_ids = self.search(cr, uid, [
|
||||
('state', '=', 'draft'),
|
||||
|
@ -281,6 +281,9 @@ class gamification_challenge(osv.Model):
|
|||
if not ids:
|
||||
ids = self.search(cr, uid, [('state', '=', 'inprogress')], context=context)
|
||||
|
||||
# in cron mode, will do intermediate commits
|
||||
# TODO in trunk: replace by parameter
|
||||
context.update({'commit_gamification': True})
|
||||
return self._update_all(cr, uid, ids, context=context)
|
||||
|
||||
def _update_all(self, cr, uid, ids, context=None):
|
||||
|
@ -355,11 +358,6 @@ class gamification_challenge(osv.Model):
|
|||
if write_op:
|
||||
self.write(cr, uid, [challenge.id], {'user_ids': write_op}, context=context)
|
||||
|
||||
if to_remove_ids:
|
||||
self.message_unsubscribe_users(cr, uid, [challenge.id], to_remove_ids, context=None)
|
||||
if to_add_ids:
|
||||
self.message_subscribe_users(cr, uid, [challenge.id], to_add_ids, context=context)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -393,9 +391,9 @@ class gamification_challenge(osv.Model):
|
|||
:param list(int) ids: the list of challenge concerned"""
|
||||
|
||||
goal_obj = self.pool.get('gamification.goal')
|
||||
to_update = []
|
||||
for challenge in self.browse(cr, uid, ids, context=context):
|
||||
(start_date, end_date) = start_end_date_for_period(challenge.period)
|
||||
to_update = []
|
||||
|
||||
# if no periodicity, use challenge dates
|
||||
if not start_date and challenge.start_date:
|
||||
|
@ -426,7 +424,15 @@ class gamification_challenge(osv.Model):
|
|||
|
||||
cr.execute(query, query_params)
|
||||
user_with_goal_ids = cr.dictfetchall()
|
||||
user_without_goal_ids = list(set([user.id for user in challenge.user_ids]) - set([user['user_id'] for user in user_with_goal_ids]))
|
||||
|
||||
participant_user_ids = [user.id for user in challenge.user_ids]
|
||||
user_without_goal_ids = list(set(participant_user_ids) - set([user['user_id'] for user in user_with_goal_ids]))
|
||||
user_squating_challenge_ids = list(set([user['user_id'] for user in user_with_goal_ids]) - set(participant_user_ids))
|
||||
if user_squating_challenge_ids:
|
||||
# users that used to match the challenge
|
||||
goal_to_remove_ids = goal_obj.search(cr, uid, [('challenge_id', '=', challenge.id), ('user_id', 'in', user_squating_challenge_ids)], context=context)
|
||||
goal_obj.unlink(cr, uid, goal_to_remove_ids, context=context)
|
||||
|
||||
|
||||
values = {
|
||||
'definition_id': line.definition_id.id,
|
||||
|
@ -614,9 +620,10 @@ class gamification_challenge(osv.Model):
|
|||
ctx.update({'challenge_lines': lines_boards})
|
||||
body_html = temp_obj.render_template(cr, uid, challenge.report_template_id.body_html, 'gamification.challenge', challenge.id, context=ctx)
|
||||
|
||||
# send to every follower of the challenge
|
||||
# send to every follower and participant of the challenge
|
||||
self.message_post(cr, uid, challenge.id,
|
||||
body=body_html,
|
||||
partner_ids=[user.partner_id.id for user in challenge.user_ids],
|
||||
context=context,
|
||||
subtype='mail.mt_comment')
|
||||
if challenge.report_message_group_id:
|
||||
|
@ -698,34 +705,35 @@ class gamification_challenge(osv.Model):
|
|||
rewarded_users = []
|
||||
challenge_ended = end_date == yesterday.strftime(DF) or force
|
||||
if challenge.reward_id and challenge_ended or challenge.reward_realtime:
|
||||
for user in challenge.user_ids:
|
||||
reached_goal_ids = self.pool.get('gamification.goal').search(cr, uid, [
|
||||
('challenge_id', '=', challenge.id),
|
||||
('user_id', '=', user.id),
|
||||
('start_date', '=', start_date),
|
||||
('end_date', '=', end_date),
|
||||
('state', '=', 'reached')
|
||||
], context=context)
|
||||
if len(reached_goal_ids) == len(challenge.line_ids):
|
||||
# not using start_date as intemportal goals have a start date but no end_date
|
||||
reached_goals = self.pool.get('gamification.goal').read_group(cr, uid, [
|
||||
('challenge_id', '=', challenge.id),
|
||||
('end_date', '=', end_date),
|
||||
('state', '=', 'reached')
|
||||
], fields=['user_id'], groupby=['user_id'], context=context)
|
||||
for reach_goals_user in reached_goals:
|
||||
if reach_goals_user['user_id_count'] == len(challenge.line_ids):
|
||||
# the user has succeeded every assigned goal
|
||||
user_id = reach_goals_user['user_id'][0]
|
||||
if challenge.reward_realtime:
|
||||
badges = self.pool['gamification.badge.user'].search(cr, uid, [
|
||||
('challenge_id', '=', challenge.id),
|
||||
('badge_id', '=', challenge.reward_id.id),
|
||||
('user_id', '=', user.id),
|
||||
('user_id', '=', user_id),
|
||||
], count=True, context=context)
|
||||
if badges > 0:
|
||||
# has already recieved the badge for this challenge
|
||||
continue
|
||||
self.reward_user(cr, uid, user.id, challenge.reward_id.id, challenge.id, context=context)
|
||||
rewarded_users.append(user)
|
||||
self.reward_user(cr, uid, user_id, challenge.reward_id.id, challenge.id, context=context)
|
||||
rewarded_users.append(user_id)
|
||||
|
||||
if challenge_ended:
|
||||
# open chatter message
|
||||
message_body = _("The challenge %s is finished." % challenge.name)
|
||||
|
||||
if rewarded_users:
|
||||
message_body += _("<br/>Reward (badge %s) for every succeeding user was sent to %s." % (challenge.reward_id.name, ", ".join([user.name for user in rewarded_users])))
|
||||
user_names = self.pool['res.users'].name_get(cr, uid, rewarded_users, context=context)
|
||||
message_body += _("<br/>Reward (badge %s) for every succeeding user was sent to %s." % (challenge.reward_id.name, ", ".join([name for (user_id, name) in user_names])))
|
||||
else:
|
||||
message_body += _("<br/>Nobody has succeeded to reach every goal, no badge is rewared for this challenge.")
|
||||
|
||||
|
@ -746,7 +754,10 @@ class gamification_challenge(osv.Model):
|
|||
self.reward_user(cr, uid, third_user.id, challenge.reward_second_id.id, challenge.id, context=context)
|
||||
message_body += "<br/> 3. %s - %s" % (third_user.name, challenge.reward_third_id.name)
|
||||
|
||||
self.message_post(cr, uid, challenge.id, body=message_body, context=context)
|
||||
self.message_post(cr, uid, challenge.id,
|
||||
partner_ids=[user.partner_id.id for user in challenge.user_ids],
|
||||
body=message_body,
|
||||
context=context)
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -138,7 +138,6 @@ class gamification_goal(osv.Model):
|
|||
|
||||
_name = 'gamification.goal'
|
||||
_description = 'Gamification goal instance'
|
||||
_inherit = 'mail.thread'
|
||||
|
||||
def _get_completion(self, cr, uid, ids, field_name, arg, context=None):
|
||||
"""Return the percentage of completeness of the goal, between 0 and 100"""
|
||||
|
@ -226,8 +225,7 @@ class gamification_goal(osv.Model):
|
|||
temp_obj = self.pool.get('email.template')
|
||||
template_id = self.pool['ir.model.data'].get_object(cr, uid, 'gamification', 'email_template_goal_reminder', context)
|
||||
body_html = temp_obj.render_template(cr, uid, template_id.body_html, 'gamification.goal', goal.id, context=context)
|
||||
|
||||
self.message_post(cr, uid, goal.id, body=body_html, partner_ids=[goal.user_id.partner_id.id], context=context, subtype='mail.mt_comment')
|
||||
self.pool['mail.thread'].message_post(cr, uid, 0, body=body_html, partner_ids=[goal.user_id.partner_id.id], context=context, subtype='mail.mt_comment')
|
||||
return {'to_update': True}
|
||||
return {}
|
||||
|
||||
|
@ -241,9 +239,9 @@ class gamification_goal(osv.Model):
|
|||
the target value being reached, the goal is set as failed."""
|
||||
if context is None:
|
||||
context = {}
|
||||
commit = context.get('commit_gamification', False)
|
||||
|
||||
goals_by_definition = {}
|
||||
goals_to_write = {}
|
||||
all_goals = {}
|
||||
for goal in self.browse(cr, uid, ids, context=context):
|
||||
if goal.state in ('draft', 'canceled'):
|
||||
|
@ -251,10 +249,10 @@ class gamification_goal(osv.Model):
|
|||
continue
|
||||
|
||||
goals_by_definition.setdefault(goal.definition_id, []).append(goal)
|
||||
goals_to_write[goal.id] = {}
|
||||
all_goals[goal.id] = goal
|
||||
|
||||
for definition, goals in goals_by_definition.items():
|
||||
goals_to_write = dict((goal.id, {}) for goal in goals)
|
||||
if definition.computation_mode == 'manually':
|
||||
for goal in goals:
|
||||
goals_to_write[goal.id].update(self._check_remind_delay(cr, uid, goal, context))
|
||||
|
@ -345,22 +343,24 @@ class gamification_goal(osv.Model):
|
|||
if new_value != goal.current:
|
||||
goals_to_write[goal.id]['current'] = new_value
|
||||
|
||||
for goal_id, value in goals_to_write.items():
|
||||
if not value:
|
||||
continue
|
||||
goal = all_goals[goal_id]
|
||||
for goal_id, value in goals_to_write.items():
|
||||
if not value:
|
||||
continue
|
||||
goal = all_goals[goal_id]
|
||||
|
||||
# check goal target reached
|
||||
if (goal.definition_condition == 'higher' and value.get('current', goal.current) >= goal.target_goal) \
|
||||
or (goal.definition_condition == 'lower' and value.get('current', goal.current) <= goal.target_goal):
|
||||
value['state'] = 'reached'
|
||||
# check goal target reached
|
||||
if (goal.definition_condition == 'higher' and value.get('current', goal.current) >= goal.target_goal) \
|
||||
or (goal.definition_condition == 'lower' and value.get('current', goal.current) <= goal.target_goal):
|
||||
value['state'] = 'reached'
|
||||
|
||||
# check goal failure
|
||||
elif goal.end_date and fields.date.today() > goal.end_date:
|
||||
value['state'] = 'failed'
|
||||
value['closed'] = True
|
||||
if value:
|
||||
self.write(cr, uid, [goal.id], value, context=context)
|
||||
# check goal failure
|
||||
elif goal.end_date and fields.date.today() > goal.end_date:
|
||||
value['state'] = 'failed'
|
||||
value['closed'] = True
|
||||
if value:
|
||||
self.write(cr, uid, [goal.id], value, context=context)
|
||||
if commit:
|
||||
cr.commit()
|
||||
return True
|
||||
|
||||
def action_start(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -86,10 +86,6 @@
|
|||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -248,7 +248,13 @@ class hr_employee(osv.osv):
|
|||
'image': _get_default_image,
|
||||
'color': 0,
|
||||
}
|
||||
|
||||
|
||||
def copy_data(self, cr, uid, ids, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({'child_ids': False})
|
||||
return super(hr_employee, self).copy_data(cr, uid, ids, default, context=context)
|
||||
|
||||
def _broadcast_welcome(self, cr, uid, employee_id, context=None):
|
||||
""" Broadcast the welcome message to all users in the employee company. """
|
||||
employee = self.browse(cr, uid, employee_id, context=context)
|
||||
|
@ -421,18 +427,23 @@ class hr_department(osv.osv):
|
|||
res.append((record['id'], name))
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, ids, default=None, context=None):
|
||||
def copy_data(self, cr, uid, ids, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
default['member_ids'] = []
|
||||
return super(hr_department, self).copy(cr, uid, ids, default, context=context)
|
||||
return super(hr_department, self).copy_data(cr, uid, ids, default, context=context)
|
||||
|
||||
|
||||
class res_users(osv.osv):
|
||||
_name = 'res.users'
|
||||
_inherit = 'res.users'
|
||||
|
||||
def copy_data(self, cr, uid, ids, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({'employee_ids': False})
|
||||
return super(res_users, self).copy_data(cr, uid, ids, default, context=context)
|
||||
|
||||
_columns = {
|
||||
'employee_ids': fields.one2many('hr.employee', 'user_id', 'Related employees'),
|
||||
}
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
import time
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from pytz import timezone
|
||||
import pytz
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.translate import _
|
||||
|
||||
class hr_timesheet_sheet(osv.osv):
|
||||
|
@ -410,22 +412,56 @@ class hr_attendance(osv.osv):
|
|||
attendance_ids.extend([row[0] for row in cr.fetchall()])
|
||||
return attendance_ids
|
||||
|
||||
def _get_current_sheet(self, cr, uid, employee_id, date=False, context=None):
|
||||
def _get_attendance_employee_tz(self, cr, uid, employee_id, date, context=None):
|
||||
""" Simulate timesheet in employee timezone
|
||||
|
||||
Return the attendance date in string format in the employee
|
||||
tz converted from utc timezone as we consider date of employee
|
||||
timesheet is in employee timezone
|
||||
"""
|
||||
employee_obj = self.pool['hr.employee']
|
||||
|
||||
tz = False
|
||||
if employee_id:
|
||||
employee = employee_obj.browse(cr, uid, employee_id, context=context)
|
||||
tz = employee.user_id.partner_id.tz
|
||||
|
||||
if not date:
|
||||
date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
# ending date with no time to avoid timesheet with early date_to
|
||||
date_to = date[0:10]+' 00:00:00'
|
||||
# limit=1 because only one sheet possible for an employee between 2 dates
|
||||
sheet_ids = self.pool.get('hr_timesheet_sheet.sheet').search(cr, uid, [
|
||||
('date_to', '>=', date_to), ('date_from', '<=', date),
|
||||
('employee_id', '=', employee_id)
|
||||
], limit=1, context=context)
|
||||
|
||||
att_tz = timezone(tz or 'utc')
|
||||
|
||||
attendance_dt = datetime.strptime(date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
att_tz_dt = pytz.utc.localize(attendance_dt)
|
||||
att_tz_dt = att_tz_dt.astimezone(att_tz)
|
||||
# We take only the date omiting the hours as we compare with timesheet
|
||||
# date_from which is a date format thus using hours would lead to
|
||||
# be out of scope of timesheet
|
||||
att_tz_date_str = datetime.strftime(att_tz_dt, DEFAULT_SERVER_DATE_FORMAT)
|
||||
return att_tz_date_str
|
||||
|
||||
def _get_current_sheet(self, cr, uid, employee_id, date=False, context=None):
|
||||
|
||||
sheet_obj = self.pool['hr_timesheet_sheet.sheet']
|
||||
if not date:
|
||||
date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
|
||||
att_tz_date_str = self._get_attendance_employee_tz(
|
||||
cr, uid, employee_id,
|
||||
date=date, context=context)
|
||||
sheet_ids = sheet_obj.search(cr, uid,
|
||||
[('date_from', '<=', att_tz_date_str),
|
||||
('date_to', '>=', att_tz_date_str),
|
||||
('employee_id', '=', employee_id)],
|
||||
limit=1, context=context)
|
||||
return sheet_ids and sheet_ids[0] or False
|
||||
|
||||
def _sheet(self, cursor, user, ids, name, args, context=None):
|
||||
res = {}.fromkeys(ids, False)
|
||||
for attendance in self.browse(cursor, user, ids, context=context):
|
||||
res[attendance.id] = self._get_current_sheet(cursor, user, attendance.employee_id.id, attendance.name, context=context)
|
||||
res[attendance.id] = self._get_current_sheet(
|
||||
cursor, user, attendance.employee_id.id, attendance.name,
|
||||
context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
|
@ -447,10 +483,13 @@ class hr_attendance(osv.osv):
|
|||
|
||||
sheet_id = context.get('sheet_id') or self._get_current_sheet(cr, uid, vals.get('employee_id'), vals.get('name'), context=context)
|
||||
if sheet_id:
|
||||
att_tz_date_str = self._get_attendance_employee_tz(
|
||||
cr, uid, vals.get('employee_id'),
|
||||
date=vals.get('name'), context=context)
|
||||
ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, sheet_id, context=context)
|
||||
if ts.state not in ('draft', 'new'):
|
||||
raise osv.except_osv(_('Error!'), _('You can not enter an attendance in a submitted timesheet. Ask your manager to reset it before adding attendance.'))
|
||||
elif ts.date_from > vals.get('name') or ts.date_to < vals.get('name'):
|
||||
elif ts.date_from > att_tz_date_str or ts.date_to < att_tz_date_str:
|
||||
raise osv.except_osv(_('User Error!'), _('You can not enter an attendance date outside the current timesheet dates.'))
|
||||
return super(hr_attendance,self).create(cr, uid, vals, context=context)
|
||||
|
||||
|
@ -619,4 +658,3 @@ class hr_employee(osv.osv):
|
|||
'timesheet_count': fields.function(_timesheet_count, type='integer', string='Timesheets'),
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from openerp import SUPERUSER_ID
|
|||
from openerp import http
|
||||
from openerp.http import request
|
||||
from openerp.addons.web.controllers.main import content_disposition
|
||||
import mimetypes
|
||||
|
||||
|
||||
class MailController(http.Controller):
|
||||
|
@ -19,10 +20,11 @@ class MailController(http.Controller):
|
|||
if res:
|
||||
filecontent = base64.b64decode(res.get('base64'))
|
||||
filename = res.get('filename')
|
||||
content_type = mimetypes.guess_type(filename)
|
||||
if filecontent and filename:
|
||||
return request.make_response(
|
||||
filecontent,
|
||||
headers=[('Content-Type', 'application/octet-stream'),
|
||||
headers=[('Content-Type', content_type[0] or 'application/octet-stream'),
|
||||
('Content-Disposition', content_disposition(filename))])
|
||||
return request.not_found()
|
||||
|
||||
|
|
|
@ -238,6 +238,7 @@ class mail_mail(osv.Model):
|
|||
if context is None:
|
||||
context = {}
|
||||
ir_mail_server = self.pool.get('ir.mail_server')
|
||||
ir_attachment = self.pool['ir.attachment']
|
||||
for mail in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
try:
|
||||
# TDE note: remove me when model_id field is present on mail.message - done here to avoid doing it multiple times in the sub method
|
||||
|
@ -248,10 +249,15 @@ class mail_mail(osv.Model):
|
|||
model = None
|
||||
if model:
|
||||
context['model_name'] = model.name
|
||||
# handle attachments
|
||||
attachments = []
|
||||
for attach in mail.attachment_ids:
|
||||
attachments.append((attach.datas_fname, base64.b64decode(attach.datas)))
|
||||
|
||||
# load attachment binary data with a separate read(), as prefetching all
|
||||
# `datas` (binary field) could bloat the browse cache, triggerring
|
||||
# soft/hard mem limits with temporary data.
|
||||
attachment_ids = [a.id for a in mail.attachment_ids]
|
||||
attachments = [(a['datas_fname'], base64.b64decode(a['datas']))
|
||||
for a in ir_attachment.read(cr, SUPERUSER_ID, attachment_ids,
|
||||
['datas_fname', 'datas'])]
|
||||
|
||||
# specific behavior to customize the send email for notified partners
|
||||
email_list = []
|
||||
if mail.email_to:
|
||||
|
@ -300,6 +306,14 @@ class mail_mail(osv.Model):
|
|||
# /!\ can't use mail.state here, as mail.refresh() will cause an error
|
||||
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
|
||||
self._postprocess_sent_message(cr, uid, mail, context=context, mail_sent=mail_sent)
|
||||
_logger.info('Mail with ID %r and Message-Id %r successfully sent', mail.id, mail.message_id)
|
||||
except MemoryError:
|
||||
# prevent catching transient MemoryErrors, bubble up to notify user or abort cron job
|
||||
# instead of marking the mail as failed
|
||||
_logger.exception('MemoryError while processing mail with ID %r and Msg-Id %r. '\
|
||||
'Consider raising the --limit-memory-hard startup option',
|
||||
mail.id, mail.message_id)
|
||||
raise
|
||||
except Exception as e:
|
||||
_logger.exception('failed sending mail.mail %s', mail.id)
|
||||
mail.write({'state': 'exception'})
|
||||
|
|
|
@ -433,14 +433,14 @@ class mail_thread(osv.AbstractModel):
|
|||
fol_obj.unlink(cr, SUPERUSER_ID, fol_ids, context=context)
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
# avoid tracking multiple temporary changes during copy
|
||||
context = dict(context or {}, mail_notrack=True)
|
||||
|
||||
default = default or {}
|
||||
default['message_ids'] = []
|
||||
default['message_follower_ids'] = []
|
||||
return super(mail_thread, self).copy(cr, uid, id, default=default, context=context)
|
||||
return super(mail_thread, self).copy_data(cr, uid, id, default=default, context=context)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Automatically log tracked fields
|
||||
|
|
|
@ -34,14 +34,14 @@ class project_configuration(osv.TransientModel):
|
|||
}
|
||||
|
||||
def get_default_alias_domain(self, cr, uid, ids, context=None):
|
||||
alias_domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", context=context)
|
||||
if not alias_domain:
|
||||
alias_domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", default=None, context=context)
|
||||
if alias_domain is None:
|
||||
domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context)
|
||||
try:
|
||||
alias_domain = urlparse.urlsplit(domain).netloc.split(':')[0]
|
||||
except Exception:
|
||||
pass
|
||||
return {'alias_domain': alias_domain}
|
||||
return {'alias_domain': alias_domain or False}
|
||||
|
||||
def set_alias_domain(self, cr, uid, ids, context=None):
|
||||
config_parameters = self.pool.get("ir.config_parameter")
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<record id="res_company_oerp_us" model="res.company">
|
||||
<field name="partner_id" ref="res_partner_oerp_us"/>
|
||||
<field name="parent_id" ref="res_company_oerp_editor"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="currency_id" ref="base.USD"/>
|
||||
<field name="name">OpenERP US</field>
|
||||
</record>
|
||||
<record id="res_company_oerp_be" model="res.company">
|
||||
|
@ -400,7 +400,7 @@
|
|||
</record>
|
||||
<record id="project.project_project_3" model="project.project">
|
||||
<field name="company_id" ref="res_company_oerp_us"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="currency_id" ref="base.USD"/>
|
||||
</record>
|
||||
<record id="project.project_project_4" model="project.project">
|
||||
<field name="company_id" ref="res_company_oerp_be"/>
|
||||
|
|
|
@ -1162,8 +1162,8 @@ class pos_order(osv.osv):
|
|||
return self.write(cr, uid, ids, {'state': 'payment'}, context=context)
|
||||
|
||||
def action_paid(self, cr, uid, ids, context=None):
|
||||
self.create_picking(cr, uid, ids, context=context)
|
||||
self.write(cr, uid, ids, {'state': 'paid'}, context=context)
|
||||
self.create_picking(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -260,8 +260,14 @@ class Report(osv.Model):
|
|||
def get_action(self, cr, uid, ids, report_name, data=None, context=None):
|
||||
"""Return an action of type ir.actions.report.xml.
|
||||
|
||||
:param ids: Ids of the records to print (if not used, pass an empty list)
|
||||
:param report_name: Name of the template to generate an action for
|
||||
"""
|
||||
if ids:
|
||||
if not isinstance(ids, list):
|
||||
ids = [ids]
|
||||
context['active_ids'] = ids
|
||||
|
||||
report_obj = self.pool['ir.actions.report.xml']
|
||||
idreport = report_obj.search(cr, uid, [('report_name', '=', report_name)], context=context)
|
||||
try:
|
||||
|
@ -272,7 +278,7 @@ class Report(osv.Model):
|
|||
_('This report is not loaded into the database: %s.' % report_name)
|
||||
)
|
||||
|
||||
action = {
|
||||
return {
|
||||
'context': context,
|
||||
'data': data,
|
||||
'type': 'ir.actions.report.xml',
|
||||
|
@ -280,7 +286,6 @@ class Report(osv.Model):
|
|||
'report_type': report.report_type,
|
||||
'report_file': report.report_file,
|
||||
}
|
||||
return action
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Report generation helpers
|
||||
|
|
|
@ -105,7 +105,9 @@ class product_product(osv.osv):
|
|||
'compute_child': False
|
||||
})
|
||||
|
||||
qty = product.qty_available
|
||||
# qty_available depends of the location in the context
|
||||
qty = self.read(cr, uid, [product.id], ['qty_available'], context=c)[0]['qty_available']
|
||||
|
||||
diff = product.standard_price - new_price
|
||||
if not diff: raise osv.except_osv(_('Error!'), _("No difference between standard price and new price!"))
|
||||
if qty:
|
||||
|
|
|
@ -2312,7 +2312,9 @@ class stock_move(osv.osv):
|
|||
|
||||
# if product is set to average price and a specific value was entered in the picking wizard,
|
||||
# we use it
|
||||
if move.product_id.cost_method == 'average' and move.price_unit:
|
||||
if move.location_dest_id.usage != 'internal' and move.product_id.cost_method == 'average':
|
||||
reference_amount = qty * move.product_id.standard_price
|
||||
elif move.product_id.cost_method == 'average' and move.price_unit:
|
||||
reference_amount = qty * move.price_unit
|
||||
reference_currency_id = move.price_currency_id.id or reference_currency_id
|
||||
|
||||
|
|
|
@ -811,7 +811,7 @@
|
|||
</group>
|
||||
<notebook>
|
||||
<page string="Products">
|
||||
<field name="move_lines" context="{'address_in_id': partner_id, 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree', 'picking_type': 'internal'}" options='{"reload_on_button": true}'/>
|
||||
<field name="move_lines" string="Stock Move" context="{'address_in_id': partner_id, 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree', 'picking_type': 'internal'}" options='{"reload_on_button": true}'/>
|
||||
<field name="note" placeholder="Add an internal note..." class="oe_inline"/>
|
||||
</page>
|
||||
<page string="Additional Info">
|
||||
|
@ -945,7 +945,7 @@
|
|||
<field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Customer" domain="[('customer','=',True)]" />
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_lines']" position="replace">
|
||||
<field name="move_lines" context="{'address_out_id': partner_id, 'picking_type': 'out', 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree'}" options='{"reload_on_button": true}'/>
|
||||
<field name="move_lines" string="Stock Move" context="{'address_out_id': partner_id, 'picking_type': 'out', 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree'}" options='{"reload_on_button": true}'/>
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
|
@ -1072,7 +1072,7 @@
|
|||
<field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Supplier" domain="[('supplier','=',True)]" context="{'default_supplier':1,'default_customer':0}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='move_lines']" position="replace">
|
||||
<field name="move_lines" context="{'address_in_id': partner_id, 'picking_type': 'in', 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree'}" options='{"reload_on_button": true}'/>
|
||||
<field name="move_lines" string="Stock Move" context="{'address_in_id': partner_id, 'picking_type': 'in', 'form_view_ref':'stock.view_move_picking_form', 'tree_view_ref':'stock.view_move_picking_tree'}" options='{"reload_on_button": true}'/>
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
|
@ -1359,7 +1359,7 @@
|
|||
|
||||
<group string="Locations" groups="stock.group_locations">
|
||||
<field name="location_id" domain="[('usage','<>','view')]"/>
|
||||
<field name="location_dest_id" domain="[('usage','=','internal')]" groups="stock.group_locations"/>
|
||||
<field name="location_dest_id" domain="[('usage','in', ['internal', 'supplier', 'customer'])]" groups="stock.group_locations"/>
|
||||
</group>
|
||||
|
||||
<group groups="stock.group_tracking_lot" string="Traceability">
|
||||
|
|
|
@ -62,14 +62,14 @@ class sale_order(osv.osv):
|
|||
message = False
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, part, context=context)
|
||||
if partner.sale_warn != 'no-message':
|
||||
if partner.sale_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.sale_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.sale_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message,
|
||||
}
|
||||
if partner.sale_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(sale_order, self).onchange_partner_id(cr, uid, ids, part, context=context)
|
||||
|
||||
|
@ -90,14 +90,15 @@ class purchase_order(osv.osv):
|
|||
message = False
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, part)
|
||||
if partner.purchase_warn != 'no-message':
|
||||
if partner.purchase_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.purchase_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.purchase_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message
|
||||
}
|
||||
if partner.purchase_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(purchase_order, self).onchange_partner_id(cr, uid, ids, part)
|
||||
|
||||
if result.get('warning',False):
|
||||
|
@ -123,15 +124,16 @@ class account_invoice(osv.osv):
|
|||
message = False
|
||||
partner = self.pool.get('res.partner').browse(cr, uid, partner_id)
|
||||
if partner.invoice_warn != 'no-message':
|
||||
if partner.invoice_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.invoice_warn_msg)
|
||||
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.invoice_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message
|
||||
}
|
||||
|
||||
if partner.invoice_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(account_invoice, self).onchange_partner_id(cr, uid, ids, type, partner_id,
|
||||
date_invoice=date_invoice, payment_term=payment_term,
|
||||
partner_bank_id=partner_bank_id, company_id=company_id)
|
||||
|
@ -154,14 +156,15 @@ class stock_picking(osv.osv):
|
|||
title = False
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message
|
||||
}
|
||||
if partner.picking_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(stock_picking, self).onchange_partner_in(cr, uid, ids, partner_id, context)
|
||||
if result.get('warning',False):
|
||||
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
|
||||
|
@ -183,14 +186,15 @@ class stock_picking_in(osv.osv):
|
|||
title = False
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message
|
||||
}
|
||||
if partner.picking_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(stock_picking_in, self).onchange_partner_in(cr, uid, ids, partner_id, context)
|
||||
if result.get('warning',False):
|
||||
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
|
||||
|
@ -209,14 +213,15 @@ class stock_picking_out(osv.osv):
|
|||
title = False
|
||||
message = False
|
||||
if partner.picking_warn != 'no-message':
|
||||
if partner.picking_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (partner.name), partner.picking_warn_msg)
|
||||
title = _("Warning for %s") % partner.name
|
||||
message = partner.picking_warn_msg
|
||||
warning = {
|
||||
'title': title,
|
||||
'message': message
|
||||
}
|
||||
if partner.picking_warn == 'block':
|
||||
return {'value': {'partner_id': False}, 'warning': warning}
|
||||
|
||||
result = super(stock_picking_out, self).onchange_partner_in(cr, uid, ids, partner_id, context)
|
||||
if result.get('warning',False):
|
||||
warning['title'] = title and title +' & '+ result['warning']['title'] or result['warning']['title']
|
||||
|
@ -256,12 +261,12 @@ class sale_order_line(osv.osv):
|
|||
message = False
|
||||
|
||||
if product_info.sale_line_warn != 'no-message':
|
||||
if product_info.sale_line_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (product_info.name), product_info.sale_line_warn_msg)
|
||||
title = _("Warning for %s") % product_info.name
|
||||
message = product_info.sale_line_warn_msg
|
||||
warning['title'] = title
|
||||
warning['message'] = message
|
||||
if product_info.sale_line_warn == 'block':
|
||||
return {'value': {'product_id': False}, 'warning': warning}
|
||||
|
||||
result = super(sale_order_line, self).product_id_change( cr, uid, ids, pricelist, product, qty,
|
||||
uom, qty_uos, uos, name, partner_id,
|
||||
|
@ -288,12 +293,12 @@ class purchase_order_line(osv.osv):
|
|||
message = False
|
||||
|
||||
if product_info.purchase_line_warn != 'no-message':
|
||||
if product_info.purchase_line_warn == 'block':
|
||||
raise osv.except_osv(_('Alert for %s!') % (product_info.name), product_info.purchase_line_warn_msg)
|
||||
title = _("Warning for %s") % product_info.name
|
||||
message = product_info.purchase_line_warn_msg
|
||||
warning['title'] = title
|
||||
warning['message'] = message
|
||||
if product_info.purchase_line_warn == 'block':
|
||||
return {'value': {'product_id': False}, 'warning': warning}
|
||||
|
||||
result = super(purchase_order_line, self).onchange_product_id(cr, uid, ids, pricelist, product, qty, uom,
|
||||
partner_id, date_order, fiscal_position_id)
|
||||
|
|
|
@ -2,6 +2,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|||
access_website_public,website,website.model_website,,1,0,0,0
|
||||
access_website,website,website.model_website,base.group_website_designer,1,1,1,1
|
||||
access_website_menu,access_website_menu,model_website_menu,,1,0,0,0
|
||||
access_website_menu_designer,Web Menu Manager,model_website_menu,base.group_website_designer,1,1,1,1
|
||||
access_website,web menu manager,website.model_website,base.group_website_designer,1,1,1,1
|
||||
access_website_converter_test,access_website_converter_test,model_website_converter_test,,1,1,1,1
|
||||
access_website_converter_test_sub,access_website_converter_test_sub,model_website_converter_test_sub,,1,1,1,1
|
||||
|
|
|
|
@ -1056,6 +1056,7 @@
|
|||
this.trigger("saved");
|
||||
},
|
||||
cancel: function () {
|
||||
this.trigger("cancel");
|
||||
},
|
||||
close: function () {
|
||||
this.$el.modal('hide');
|
||||
|
|
|
@ -879,20 +879,29 @@
|
|||
this._super(np);
|
||||
if (np.$next) {
|
||||
if (np.$next.hasClass("oe_custom_bg")) {
|
||||
var editor = new website.editor.ImageDialog();
|
||||
editor.on('start', self, function (o) {o.url = np.$prev && np.$prev.data("src") || np.$next && np.$next.data("src") || "";});
|
||||
editor.on('save', self, function (o) {
|
||||
self._set_bg(o.url);
|
||||
np.$next.data("src", o.url);
|
||||
var $image = $('<img class="hidden"/>');
|
||||
$image.attr("src", np.$prev ? np.$prev.data("src") : '');
|
||||
$image.appendTo(self.$target);
|
||||
|
||||
self.element = new CKEDITOR.dom.element($image[0]);
|
||||
var editor = new website.editor.MediaDialog(self, self.element);
|
||||
editor.appendTo(document.body);
|
||||
editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
|
||||
|
||||
$image.on('saved', self, function (o) {
|
||||
var src = $image.attr("src");
|
||||
self._set_bg(src);
|
||||
np.$next.data("src", src);
|
||||
self.$target.trigger("snippet-style-change", [self, np]);
|
||||
$image.remove();
|
||||
});
|
||||
editor.on('cancel', self, function () {
|
||||
if (!np.$prev || np.$prev.data("src") === "") {
|
||||
self.$target.removeClass(np.$next.data("value"));
|
||||
self.$target.trigger("snippet-style-change", [self, np]);
|
||||
}
|
||||
$image.remove();
|
||||
});
|
||||
editor.appendTo($('body'));
|
||||
} else {
|
||||
this._set_bg(np.$next.data("src"));
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ class WebsiteForum(http.Controller):
|
|||
values.update({
|
||||
'main_object': tag or forum,
|
||||
'question_ids': question_ids,
|
||||
'question_count': question_count,
|
||||
'pager': pager,
|
||||
'tag': tag,
|
||||
'filters': filters,
|
||||
|
@ -134,7 +135,7 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route(['/forum/<model("forum.forum"):forum>/faq'], type='http', auth="public", website=True, multilang=True)
|
||||
def forum_faq(self, forum, **post):
|
||||
values = self._prepare_forum_values(forum=forum, searches=dict(), **post)
|
||||
values = self._prepare_forum_values(forum=forum, searches=dict(), header={'is_guidelines': True}, **post)
|
||||
return request.website.render("website_forum.faq", values)
|
||||
|
||||
@http.route('/forum/get_tags', type='http', auth="public", multilang=True, methods=['GET'], website=True)
|
||||
|
@ -147,7 +148,7 @@ class WebsiteForum(http.Controller):
|
|||
def tags(self, forum, page=1, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
Tag = request.registry['forum.tag']
|
||||
obj_ids = Tag.search(cr, uid, [('forum_id', '=', forum.id)], limit=None, context=context)
|
||||
obj_ids = Tag.search(cr, uid, [('forum_id', '=', forum.id), ('posts_count', '>', 0)], limit=None, order='posts_count DESC', context=context)
|
||||
tags = Tag.browse(cr, uid, obj_ids, context=context)
|
||||
values = self._prepare_forum_values(forum=forum, searches={'tags': True}, **post)
|
||||
values.update({
|
||||
|
@ -427,7 +428,7 @@ class WebsiteForum(http.Controller):
|
|||
tag_count = User.search(cr, SUPERUSER_ID, [('karma', '>', 1)], count=True, context=context)
|
||||
pager = request.website.pager(url="/forum/users", total=tag_count, page=page, step=step, scope=30)
|
||||
|
||||
obj_ids = User.search(cr, SUPERUSER_ID, [('karma', '>', 1)], limit=step, offset=pager['offset'], context=context)
|
||||
obj_ids = User.search(cr, SUPERUSER_ID, [('karma', '>', 1)], limit=step, offset=pager['offset'], order='karma DESC', context=context)
|
||||
users = User.browse(cr, SUPERUSER_ID, obj_ids, context=context)
|
||||
searches['users'] = 'True'
|
||||
|
||||
|
@ -591,12 +592,13 @@ class WebsiteForum(http.Controller):
|
|||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/comment/<model("mail.message"):comment>/convert_to_answer', type='http', auth="public", multilang=True, website=True)
|
||||
def convert_comment_to_answer(self, forum, post, comment, **kwarg):
|
||||
values = {
|
||||
'content': comment.body,
|
||||
}
|
||||
body = comment.body
|
||||
request.registry['mail.message'].unlink(request.cr, request.uid, [comment.id], context=request.context)
|
||||
question = post.parent_id if post.parent_id else post
|
||||
return self.post_new(forum, question, **values)
|
||||
for answer in question.child_ids:
|
||||
if answer.create_uid.id == request.uid:
|
||||
return self.post_comment(forum, answer, comment=html2plaintext(body))
|
||||
return self.post_new(forum, question, content=body)
|
||||
|
||||
@http.route('/forum/<model("forum.forum"):forum>/post/<model("forum.post"):post>/convert_to_comment', type='http', auth="user", multilang=True, website=True)
|
||||
def convert_answer_to_comment(self, forum, post, **kwarg):
|
||||
|
|
|
@ -13,10 +13,7 @@
|
|||
<field name="sequence" type="int">35</field>
|
||||
</record>
|
||||
|
||||
<record id="default_allow_auth_signup" model="ir.config_parameter">
|
||||
<field name="key">auth_signup.allow_uninvited</field>
|
||||
<field name="value" eval="True"/>
|
||||
</record>
|
||||
<function model="ir.config_parameter" name="set_param" eval="('auth_signup.allow_uninvited', True)" />
|
||||
|
||||
<!-- JUMP TO FORUM AT INSTALL -->
|
||||
<record id="action_open_forum" model="ir.actions.act_url">
|
||||
|
|
|
@ -70,6 +70,7 @@ class Post(osv.Model):
|
|||
_name = 'forum.post'
|
||||
_description = 'Forum Post'
|
||||
_inherit = ['mail.thread', 'website.seo.metadata']
|
||||
_order = "is_correct DESC, vote_count DESC"
|
||||
|
||||
def _get_user_vote(self, cr, uid, ids, field_name, arg, context):
|
||||
res = dict.fromkeys(ids, 0)
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
background-color: #cccccc;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.question .badge-active {
|
||||
background-color: #428bca;
|
||||
}
|
||||
|
||||
.oe_grey {
|
||||
background-color: #eeeeee;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
.badge
|
||||
background-color: #ccc
|
||||
margin-left: 4px
|
||||
.badge-active
|
||||
background-color: #428bca
|
||||
|
||||
.oe_grey
|
||||
background-color: #eeeeee
|
||||
|
|
|
@ -94,7 +94,8 @@
|
|||
</div>
|
||||
<div class="panel-body">
|
||||
<t t-raw="forum.description"/><br/>
|
||||
<a t-attf-href="/forum/#{slug(forum)}/faq" class="fa fa-arrow-right"> Read Guidelines</a>
|
||||
<a t-if="not header.get('is_guidelines')" t-attf-href="/forum/#{slug(forum)}/faq" class="fa fa-arrow-right"> Read Guidelines</a>
|
||||
<a t-if="header.get('is_guidelines')" t-attf-href="/forum/#{slug(forum)}" class="fa fa-arrow-right"> Back to <span t-field="forum.name"/></a>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="header.get('question_data')">
|
||||
|
@ -146,8 +147,11 @@
|
|||
<span t-if="not question.active"><b> [Deleted]</b></span>
|
||||
<span t-if="question.state == 'close'"><b> [Closed]</b></span>
|
||||
</div>
|
||||
<t t-foreach="question.tag_ids" t-as="tag">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag/#{ tag.id }/questions" class="badge pull-right" t-field="tag.name"/>
|
||||
<t t-foreach="question.tag_ids" t-as="question_tag">
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/tag/#{slug(question_tag)}/questions">
|
||||
<span t-attf-class="pull-right badge #{tag and tag.name == question_tag.name and 'badge-active' ''}" t-field="question_tag.name"
|
||||
style="margin-right: 4px;"/>
|
||||
</a>
|
||||
</t>
|
||||
<div class="text-muted">
|
||||
by <a t-attf-href="/forum/#{ slug(forum) }/user/#{ question.create_uid.id }"
|
||||
|
@ -210,14 +214,14 @@
|
|||
<template id="forum_index" name="Forum">
|
||||
<t t-call="website_forum.header">
|
||||
<h1 class="page-header mt0">
|
||||
<t t-esc="len(question_ids)"/> <span>Questions</span>
|
||||
<t t-esc="question_count"/> <span>Questions</span>
|
||||
<t t-esc="search"/>
|
||||
<small class="dropdown" t-if="filters in ('all', 'unanswered','followed', 'tag')">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<t t-if="filters == 'all'">All</t>
|
||||
<t t-if="filters == 'unanswered'">Unanswered</t>
|
||||
<t t-if="filters == 'followed'">Followed</t>
|
||||
<t t-if="filters == 'tag'">Tag</t>
|
||||
<t t-if="tag"><span t-field="tag.name"/></t>
|
||||
<t t-if="sorting == 'date'"> by activity date</t>
|
||||
<t t-if="sorting == 'answered'"> by most answered</t>
|
||||
<t t-if="sorting == 'vote'"> by most voted</t>
|
||||
|
@ -334,12 +338,12 @@
|
|||
users having a high karma can see closed questions to moderate
|
||||
them.
|
||||
</p>
|
||||
<form t-attf-action="/forum/#{ slug(forum) }/question/#{slug(post)}/close" method="post" role="form" class="form-horizontal mt32 mb64">
|
||||
<form t-attf-action="/forum/#{ slug(forum) }/question/#{slug(question)}/close" method="post" role="form" class="form-horizontal mt32 mb64">
|
||||
<input name="post_id" t-att-value="question.id" type="hidden"/>
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label" for="reason">Question:</label>
|
||||
<div class="col-md-8 mt8">
|
||||
<span t-field="post.name"/>
|
||||
<span t-field="question.name"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -356,7 +360,7 @@
|
|||
<div class="col-md-offset-3 col-md-8">
|
||||
<button class="btn btn-primary">Close question</button>
|
||||
<span class="text-muted">or</span>
|
||||
<a class="btn btn-link" t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(post) }">back to question</a>
|
||||
<a class="btn btn-link" t-attf-href="/forum/#{ slug(forum) }/question/#{ slug(question) }">back to question</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -453,7 +457,7 @@
|
|||
<a class="text-muted fa fa-times" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)}/ask_for_close"> Close</a>
|
||||
</li>
|
||||
<li t-if="question.state == 'close' and ((user.id == question.create_uid.id and can_close_own) or can_close_all)">
|
||||
<a class="text-muted fa fa-undo" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)/reopen"> Reopen</a>
|
||||
<a class="text-muted fa fa-undo" t-attf-href="/forum/#{ slug(forum) }/question/#{slug(question)}/reopen"> Reopen</a>
|
||||
</li>
|
||||
<li t-if="(user.id == question.create_uid.id and can_edit_own) or can_edit_all">
|
||||
<a class="text-muted fa fa-edit" t-attf-href="/forum/#{ slug(forum) }/post/#{slug(question)}/edit"> Edit</a>
|
||||
|
@ -469,7 +473,7 @@
|
|||
<div>
|
||||
<span t-field="question.create_uid.image" t-field-options='{"widget": "image", "class":"pull-left img img-circle img-avatar"}'/>
|
||||
<div>
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/user/#{ user.id }"
|
||||
<a t-attf-href="/forum/#{ slug(forum) }/user/#{ question.create_uid.id }"
|
||||
t-field="question.create_uid"
|
||||
t-field-options='{"widget": "contact", "country_image": true, "fields": ["name", "country_id"]}'
|
||||
style="display: inline-block;"/>
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
}
|
||||
</style>
|
||||
<script>var partner_url = '<t t-raw="partner_url or ''"/>';</script>
|
||||
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
|
||||
<script src="//maps.google.com/maps/api/js?sensor=false"></script>
|
||||
<script type="text/javascript" t-attf-src="/google_map/partners.json?partner_ids=#{ partner_ids }"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/markerclusterer_compiled.js"></script>
|
||||
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
|
||||
<script src="//code.jquery.com/jquery-1.6.1.min.js"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/google_map.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row">
|
||||
<h2 class="oe_slogan">Fine Tune Your Catalog</h2>
|
||||
<h3 class="oe_slogan">Boost Sales by Emphasazing Best Products</h3>
|
||||
<h3 class="oe_slogan">Boost Sales by Emphasizing Best Products</h3>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Get a full control on how you display your products in
|
||||
|
|
Loading…
Reference in New Issue