diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 1b4795f02a8..5b09f815f54 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -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): ''' diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 729c9d16b7a..628cc7229e5 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -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 diff --git a/addons/account/partner.py b/addons/account/partner.py index df4c1ec4888..cafd5505cad 100644 --- a/addons/account/partner.py +++ b/addons/account/partner.py @@ -172,18 +172,15 @@ class res_partner(osv.osv): return result def _journal_item_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'journal_item_count': 0, 'contracts_count': 0 }), ids)) - - # the user may not have access rights - try: - for partner in self.browse(cr, uid, ids, context=context): - res[partner.id] = { - 'journal_item_count': len(partner.journal_item_ids), - 'contracts_count': len(partner.contract_ids) - } - except: - pass - return res + MoveLine = self.pool('account.move.line') + AnalyticAccount = self.pool('account.analytic.account') + return { + partner_id: { + 'journal_item_count': MoveLine.search_count(cr, uid, [('partner_id', '=', partner_id)], context=context), + 'contracts_count': AnalyticAccount.search_count(cr,uid, [('partner_id', '=', partner_id)], context=context) + } + for partner_id in ids + } def has_something_to_reconcile(self, cr, uid, partner_id, context=None): ''' @@ -215,7 +212,6 @@ class res_partner(osv.osv): 'debit_limit': fields.float('Payable Limit'), 'total_invoiced': fields.function(_invoice_total, string="Total Invoiced", type='float'), 'contracts_count': fields.function(_journal_item_count, string="Contracts", type='integer', multi="invoice_journal"), - 'journal_item_ids': fields.one2many('account.move.line', 'partner_id', 'Journal Items'), 'journal_item_count': fields.function(_journal_item_count, string="Journal Items", type="integer", multi="invoice_journal"), 'property_account_payable': fields.property( type='many2one', diff --git a/addons/account/project/wizard/account_analytic_balance_report.py b/addons/account/project/wizard/account_analytic_balance_report.py index 3a3c301cffc..062945fa53e 100644 --- a/addons/account/project/wizard/account_analytic_balance_report.py +++ b/addons/account/project/wizard/account_analytic_balance_report.py @@ -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: diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py index 125dfda46fb..ab84af4880a 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py @@ -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: diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_report.py index 5f00c3c9ac5..978863f5900 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_report.py @@ -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: diff --git a/addons/account/project/wizard/account_analytic_inverted_balance_report.py b/addons/account/project/wizard/account_analytic_inverted_balance_report.py index ad79c0b33f6..93946960297 100644 --- a/addons/account/project/wizard/account_analytic_inverted_balance_report.py +++ b/addons/account/project/wizard/account_analytic_inverted_balance_report.py @@ -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: diff --git a/addons/account/project/wizard/account_analytic_journal_report.py b/addons/account/project/wizard/account_analytic_journal_report.py index f2e406bc3a5..d8790e805d8 100644 --- a/addons/account/project/wizard/account_analytic_journal_report.py +++ b/addons/account/project/wizard/account_analytic_journal_report.py @@ -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: diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml index 6757095a7d4..6c4b701c6cf 100644 --- a/addons/account/views/report_invoice.xml +++ b/addons/account/views/report_invoice.xml @@ -47,7 +47,6 @@ Description Quantity - Unit of measure Unit Price Discount (%) Taxes @@ -57,8 +56,10 @@ - - + + + + @@ -100,7 +101,7 @@
-
+
@@ -136,7 +137,7 @@

Fiscal Position: - +

diff --git a/addons/account/wizard/account_financial_report.py b/addons/account/wizard/account_financial_report.py index 6c1b57fa428..721e47193a2 100644 --- a/addons/account/wizard/account_financial_report.py +++ b/addons/account/wizard/account_financial_report.py @@ -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: diff --git a/addons/account/wizard/account_report_account_balance.py b/addons/account/wizard/account_report_account_balance.py index 3b9d3c21777..9eba5f24b99 100644 --- a/addons/account/wizard/account_report_account_balance.py +++ b/addons/account/wizard/account_report_account_balance.py @@ -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: diff --git a/addons/account/wizard/account_report_aged_partner_balance.py b/addons/account/wizard/account_report_aged_partner_balance.py index c918a1119fd..d7b57eaba02 100644 --- a/addons/account/wizard/account_report_aged_partner_balance.py +++ b/addons/account/wizard/account_report_aged_partner_balance.py @@ -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: diff --git a/addons/account/wizard/account_report_central_journal.py b/addons/account/wizard/account_report_central_journal.py index 9f22d49afac..a31fef91ae4 100644 --- a/addons/account/wizard/account_report_central_journal.py +++ b/addons/account/wizard/account_report_central_journal.py @@ -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: diff --git a/addons/account/wizard/account_report_general_journal.py b/addons/account/wizard/account_report_general_journal.py index 3d9d55b19c1..c35a5920428 100644 --- a/addons/account/wizard/account_report_general_journal.py +++ b/addons/account/wizard/account_report_general_journal.py @@ -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: diff --git a/addons/account/wizard/account_report_general_ledger.py b/addons/account/wizard/account_report_general_ledger.py index c75477da40a..5f0a302d720 100644 --- a/addons/account/wizard/account_report_general_ledger.py +++ b/addons/account/wizard/account_report_general_ledger.py @@ -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: diff --git a/addons/account/wizard/account_report_partner_balance.py b/addons/account/wizard/account_report_partner_balance.py index d4b5fb27d14..7485bec67fe 100644 --- a/addons/account/wizard/account_report_partner_balance.py +++ b/addons/account/wizard/account_report_partner_balance.py @@ -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: diff --git a/addons/account/wizard/account_report_partner_ledger.py b/addons/account/wizard/account_report_partner_ledger.py index eb743e32e4f..38ff6988fd7 100644 --- a/addons/account/wizard/account_report_partner_ledger.py +++ b/addons/account/wizard/account_report_partner_ledger.py @@ -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: diff --git a/addons/account/wizard/account_report_print_journal.py b/addons/account/wizard/account_report_print_journal.py index 3aafc63acf4..1f6b6e0cf4d 100644 --- a/addons/account/wizard/account_report_print_journal.py +++ b/addons/account/wizard/account_report_print_journal.py @@ -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: diff --git a/addons/account/wizard/account_vat.py b/addons/account/wizard/account_vat.py index 5cc5c678df1..e7c806be2f9 100644 --- a/addons/account/wizard/account_vat.py +++ b/addons/account/wizard/account_vat.py @@ -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: diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 5aa4b5a49db..6c71f940e8a 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -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" diff --git a/addons/account_analytic_default/account_analytic_default.py b/addons/account_analytic_default/account_analytic_default.py index 1faf75d5eee..ac8698ae342 100644 --- a/addons/account_analytic_default/account_analytic_default.py +++ b/addons/account_analytic_default/account_analytic_default.py @@ -117,15 +117,12 @@ class sale_order_line(osv.osv): class product_product(osv.Model): _inherit = 'product.product' def _rules_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for rule in self.browse(cr, uid, ids, context=context): - res[rule.id] = len(rule.rules_ids) - except: - pass - return res + Analytic = self.pool['account.analytic.default'] + return { + product_id: Analytic.search_count(cr, uid, [('product_id', '=', product_id)], context=context) + for product_id in ids + } _columns = { - 'rules_ids': fields.one2many('account.analytic.default', 'product_id', 'Analytic Rules '), 'rules_count': fields.function(_rules_count, string='# Analytic Rules', type='integer'), } diff --git a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py index ccac123c681..1bdc91f2995 100644 --- a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py +++ b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py @@ -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: diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index ebeb0cb8e25..0ba7182d0d4 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -238,13 +238,11 @@ class account_asset_asset(osv.osv): val['value_residual'] = purchase_value - salvage_value return {'value': val} def _entry_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for entry in self.browse(cr, uid, ids, context=context): - res[entry.id] = len(entry.account_move_line_ids) - except: - pass - return res + MoveLine = self.pool('account.move.line') + return { + asset_id: MoveLine.search_count(cr, uid, [('asset_id', '=', asset_id)], context=context) + for asset_id in ids + } _columns = { 'account_move_line_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}), 'entry_count': fields.function(_entry_count, string='# Asset Entries', type='integer'), diff --git a/addons/account_budget/wizard/account_budget_analytic.py b/addons/account_budget/wizard/account_budget_analytic.py index a58b804ebbf..bd3bbdc8d99 100644 --- a/addons/account_budget/wizard/account_budget_analytic.py +++ b/addons/account_budget/wizard/account_budget_analytic.py @@ -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: diff --git a/addons/account_budget/wizard/account_budget_crossovered_report.py b/addons/account_budget/wizard/account_budget_crossovered_report.py index 96561df5af0..e47ff5cb421 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_report.py @@ -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: diff --git a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py index 6b676ecc684..d79e6097787 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py @@ -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: diff --git a/addons/account_budget/wizard/account_budget_report.py b/addons/account_budget/wizard/account_budget_report.py index 2308b5ff9ac..fb1814a9171 100644 --- a/addons/account_budget/wizard/account_budget_report.py +++ b/addons/account_budget/wizard/account_budget_report.py @@ -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: diff --git a/addons/account_check_writing/account_voucher.py b/addons/account_check_writing/account_voucher.py index c3abe28eef0..779ff61be44 100644 --- a/addons/account_check_writing/account_voucher.py +++ b/addons/account_check_writing/account_voucher.py @@ -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 \ diff --git a/addons/account_check_writing/wizard/account_check_batch_printing.py b/addons/account_check_writing/wizard/account_check_batch_printing.py index c3a13e2c687..bf59557d904 100644 --- a/addons/account_check_writing/wizard/account_check_batch_printing.py +++ b/addons/account_check_writing/wizard/account_check_batch_printing.py @@ -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 + ) diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py index 820a179efdb..ddeb1f380c4 100644 --- a/addons/account_followup/account_followup.py +++ b/addons/account_followup/account_followup.py @@ -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: diff --git a/addons/auth_oauth/auth_oauth_view.xml b/addons/auth_oauth/auth_oauth_view.xml index ffc39752ec6..5c889d3a686 100644 --- a/addons/auth_oauth/auth_oauth_view.xml +++ b/addons/auth_oauth/auth_oauth_view.xml @@ -11,6 +11,7 @@ + diff --git a/addons/calendar/i18n/zh_CN.po b/addons/calendar/i18n/zh_CN.po index 6c5eaf61576..1193e76da1a 100644 --- a/addons/calendar/i18n/zh_CN.po +++ b/addons/calendar/i18n/zh_CN.po @@ -14,7 +14,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-05-07 06:27+0000\n" +"X-Launchpad-Export-Date: 2014-05-08 05:38+0000\n" "X-Generator: Launchpad (build 16996)\n" "Language: zh_CN\n" diff --git a/addons/claim_from_delivery/__init__.py b/addons/claim_from_delivery/__init__.py index 5e947ee409d..c21aa0d3c3a 100644 --- a/addons/claim_from_delivery/__init__.py +++ b/addons/claim_from_delivery/__init__.py @@ -18,6 +18,7 @@ # ############################################################################## +import stock_picking # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/claim_from_delivery/claim_delivery_view.xml b/addons/claim_from_delivery/claim_delivery_view.xml index 852d602c269..6f9ca5e4a66 100644 --- a/addons/claim_from_delivery/claim_delivery_view.xml +++ b/addons/claim_from_delivery/claim_delivery_view.xml @@ -18,7 +18,7 @@
diff --git a/addons/claim_from_delivery/stock_picking.py b/addons/claim_from_delivery/stock_picking.py new file mode 100644 index 00000000000..6929809bfe2 --- /dev/null +++ b/addons/claim_from_delivery/stock_picking.py @@ -0,0 +1,30 @@ +from openerp.osv import fields, osv + + +class stock_picking(osv.osv): + _inherit = 'stock.picking' + + def _claim_count_out(self, cr, uid, ids, field_name, arg, context=None): + Claim = self.pool['crm.claim'] + return { + id: Claim.search_count(cr, uid, [('ref', '=',('stock.picking.out,' + str(ids[0])))], context=context) + for id in ids + } + + _columns = { + 'claim_count_out': fields.function(_claim_count_out, string='Claims', type='integer'), + } + +# Because of the way inheritance works in the ORM (bug), and the way stock.picking.out +# is defined (inherit from stock.picking, dispatch read to stock.picking), it is necessary +# to add the field claim_count_out to this class, even though the _claim_count_out method +# in stock_picking_out will not be called (but its existence will be checked). +class stock_picking_out(osv.osv): + _inherit = 'stock.picking.out' + + def _claim_count_out(self, cr, uid, ids, field_name, arg, context=None): + return super(stock_picking_out, self)._claim_count_out(cr, uid, ids, field_name, arg, context=context) + + _columns = { + 'claim_count_out': fields.function(_claim_count_out, string='Claims', type='integer'), + } diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index a0805863fe5..cfec1a3d931 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -216,13 +216,11 @@ class crm_lead(format_address, osv.osv): res[lead.id][field] = abs(int(duration)) return res def _meeting_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for meeting in self.browse(cr, uid, ids, context=context): - res[meeting.id] = len(meeting.meeting_ids) - except: - pass - return res + Event = self.pool['calendar.event'] + return { + opp_id: Event.search_count(cr,uid, [('opportunity_id', '=', opp_id)], context=context) + for opp_id in ids + } _columns = { 'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null', track_visibility='onchange', select=True, help="Linked partner (optional). Usually created when converting the lead."), @@ -297,7 +295,6 @@ class crm_lead(format_address, osv.osv): 'payment_mode': fields.many2one('crm.payment.mode', 'Payment Mode', \ domain="[('section_id','=',section_id)]"), 'planned_cost': fields.float('Planned Costs'), - 'meeting_ids': fields.one2many('calendar.event', 'opportunity_id', 'Opportunities'), 'meeting_count': fields.function(_meeting_count, string='# Meetings', type='integer'), } diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index 1abcdac9712..fef80bb8a53 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -14,6 +14,7 @@ Dead 1 + 1 0 1 30 diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py index 62a51bcc4fd..89a1f799b2b 100644 --- a/addons/crm/crm_phonecall.py +++ b/addons/crm/crm_phonecall.py @@ -32,14 +32,6 @@ class crm_phonecall(osv.osv): _order = "id desc" _inherit = ['mail.thread'] - def _meeting_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for meeting in self.browse(cr, uid, ids, context=context): - res[meeting.id] = len(meeting.meeting_ids) - except: - pass - return res _columns = { 'date_action_last': fields.datetime('Last Action', readonly=1), 'date_action_next': fields.datetime('Next Action', readonly=1), @@ -74,8 +66,6 @@ class crm_phonecall(osv.osv): 'date_closed': fields.datetime('Closed', readonly=True), 'date': fields.datetime('Date'), 'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'), - 'meeting_ids': fields.one2many('calendar.event', 'phonecall_id', 'Phonecalls'), - 'meeting_count': fields.function(_meeting_count, string='# Meetings', type='integer'), } def _get_default_state(self, cr, uid, context=None): diff --git a/addons/crm/res_partner.py b/addons/crm/res_partner.py index b34e5c7dbb9..bb216e2040e 100644 --- a/addons/crm/res_partner.py +++ b/addons/crm/res_partner.py @@ -33,10 +33,11 @@ class res_partner(osv.osv): res[partner.id] = { 'opportunity_count': len(partner.opportunity_ids), 'meeting_count': len(partner.meeting_ids), - 'phonecall_count': len(partner.meeting_ids), } except: pass + for partner in self.browse(cr, uid, ids, context): + res[partner.id]['phonecall_count'] = len(partner.phonecall_ids) return res _columns = { diff --git a/addons/crm/static/description/index.html b/addons/crm/static/description/index.html index 5f3fd65cdc2..799dee38cf0 100644 --- a/addons/crm/static/description/index.html +++ b/addons/crm/static/description/index.html @@ -88,7 +88,7 @@ Find duplicates, merge leads and assign them to the right salesperson in one ope

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.

-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.

diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py index fec30dd2163..641c490cabb 100644 --- a/addons/crm_claim/crm_claim.py +++ b/addons/crm_claim/crm_claim.py @@ -191,15 +191,13 @@ class crm_claim(osv.osv): class res_partner(osv.osv): _inherit = 'res.partner' def _claim_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for partner in self.browse(cr, uid, ids, context=context): - res[partner.id] = len(partner.claims_ids) - except: - pass - return res + Claim = self.pool['crm.claim'] + return { + partner_id: Claim.search_count(cr,uid, [('partner_id', '=', partner_id)], context=context) + for partner_id in ids + } + _columns = { - 'claims_ids': fields.one2many('crm.claim', 'partner_id', 'Claims'), 'claim_count': fields.function(_claim_count, string='# Claims', type='integer'), } diff --git a/addons/event_sale/event_sale.py b/addons/event_sale/event_sale.py index b4f42673aba..c96b5d73932 100644 --- a/addons/event_sale/event_sale.py +++ b/addons/event_sale/event_sale.py @@ -37,6 +37,9 @@ class product_template(osv.osv): class product(osv.osv): _inherit = 'product.product' + _columns = { + 'event_ticket_ids': fields.one2many('event.event.ticket', 'product_id', 'Event Tickets'), + } def onchange_event_ok(self, cr, uid, ids, type, event_ok, context=None): # cannot directly forward to product.template as the ids are theoretically different diff --git a/addons/fleet/fleet.py b/addons/fleet/fleet.py index 0e964cafc80..6c5f097d4d1 100644 --- a/addons/fleet/fleet.py +++ b/addons/fleet/fleet.py @@ -315,18 +315,21 @@ class fleet_vehicle(osv.Model): return model_id def _count_all(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'odometer_count': 0, 'fuel_logs_count': 0, 'service_count': 0, 'contract_count': 0, 'cost_count': 0,}), ids)) - try: - for costs in self.browse(cr, uid, ids, context=context): - res[costs.id] = {'odometer_count': len(costs.odometer_ids), - 'fuel_logs_count': len(costs.log_fuel), - 'service_count': len(costs.log_services), - 'contract_count': len(costs.log_contracts), - 'cost_count': len(costs.costs_ids) - } - except: - pass - return res + Odometer = self.pool['fleet.vehicle.odometer'] + LogFuel = self.pool['fleet.vehicle.log.fuel'] + LogService = self.pool['fleet.vehicle.log.services'] + LogContract = self.pool['fleet.vehicle.log.contract'] + Cost = self.pool['fleet.vehicle.cost'] + return { + vehicle_id: { + 'odometer_count': Odometer.search_count(cr, uid, [('vehicle_id', '=', vehicle_id)], context=context), + 'fuel_logs_count': LogFuel.search_count(cr, uid, [('vehicle_id', '=', vehicle_id)], context=context), + 'service_count': LogService.search_count(cr, uid, [('vehicle_id', '=', vehicle_id)], context=context), + 'contract_count': LogContract.search_count(cr, uid, [('vehicle_id', '=', vehicle_id)], context=context), + 'cost_count': Cost.search_count(cr, uid, [('vehicle_id', '=', vehicle_id), ('parent_id', '=', False)], context=context) + } + for vehicle_id in ids + } _name = 'fleet.vehicle' _description = 'Information on a vehicle' @@ -341,8 +344,6 @@ class fleet_vehicle(osv.Model): 'log_fuel': fields.one2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs'), 'log_services': fields.one2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs'), 'log_contracts': fields.one2many('fleet.vehicle.log.contract', 'vehicle_id', 'Contracts'), - 'costs_ids': fields.one2many('fleet.vehicle.cost', 'vehicle_id', 'Costs'), - 'odometer_ids': fields.one2many('fleet.vehicle.odometer', 'vehicle_id', 'Odometer'), 'cost_count': fields.function(_count_all, type='integer', string="Costs" , multi=True), 'contract_count': fields.function(_count_all, type='integer', string='Contracts', multi=True), 'service_count': fields.function(_count_all, type='integer', string='Services', multi=True), diff --git a/addons/gamification/models/challenge.py b/addons/gamification/models/challenge.py index ecb4c495d94..63c23f30cff 100644 --- a/addons/gamification/models/challenge.py +++ b/addons/gamification/models/challenge.py @@ -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 += _("
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 += _("
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 += _("
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 += "
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 diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index af9a763236d..b4a47a0d07a 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -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): diff --git a/addons/gamification/views/goal.xml b/addons/gamification/views/goal.xml index 528d5db0511..884467404ce 100644 --- a/addons/gamification/views/goal.xml +++ b/addons/gamification/views/goal.xml @@ -86,10 +86,6 @@
-
- - -
diff --git a/addons/hr/hr.py b/addons/hr/hr.py index a13a1866493..5bb172eb082 100644 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -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'), } diff --git a/addons/hr_contract/hr_contract.py b/addons/hr_contract/hr_contract.py index d641c490ec2..798ee46832d 100644 --- a/addons/hr_contract/hr_contract.py +++ b/addons/hr_contract/hr_contract.py @@ -39,13 +39,11 @@ class hr_employee(osv.osv): return res def _contracts_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for employee in self.browse(cr, uid, ids, context=context): - res[employee.id] = len(employee.contract_ids) - except: - pass - return res + Contract = self.pool['hr.contract'] + return { + employee_id: Contract.search_count(cr,uid, [('employee_id', '=', employee_id)], context=context) + for employee_id in ids + } _columns = { 'manager': fields.boolean('Is a Manager'), diff --git a/addons/hr_evaluation/hr_evaluation.py b/addons/hr_evaluation/hr_evaluation.py index 5cd960038aa..b52802cd297 100644 --- a/addons/hr_evaluation/hr_evaluation.py +++ b/addons/hr_evaluation/hr_evaluation.py @@ -104,19 +104,15 @@ class hr_employee(osv.Model): _inherit="hr.employee" def _appraisal_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for employee in self.browse(cr, uid, ids, context=context): - res[employee.id] = len(employee.appraisal_ids) - except: - pass - return res - + Evaluation = self.pool['hr.evaluation.interview'] + return { + employee_id: Evaluation.search_count(cr, uid, [('user_to_review_id', '=', employee_id)], context=context) + for employee_id in ids + } _columns = { 'evaluation_plan_id': fields.many2one('hr_evaluation.plan', 'Appraisal Plan'), 'evaluation_date': fields.date('Next Appraisal Date', help="The date of the next appraisal is computed by the appraisal plan's dates (first appraisal + periodicity)."), - 'appraisal_ids': fields.one2many('hr.evaluation.interview', 'user_to_review_id', 'Appraisal Interviews'), 'appraisal_count': fields.function(_appraisal_count, type='integer', string='Appraisal Interviews'), } diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index 67f09faf9c4..2385983f020 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -550,13 +550,11 @@ class hr_employee(osv.osv): return result def _leaves_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for employee in self.browse(cr, uid, ids, context=context): - res[employee.id] = len(employee.leave_ids) - except: - pass - return res + Holidays = self.pool['hr.holidays'] + return { + employee_id: Holidays.search_count(cr,uid, [('employee_id', '=', employee_id)], context=context) + for employee_id in ids + } _columns = { 'remaining_leaves': fields.function(_get_remaining_days, string='Remaining Legal Leaves', fnct_inv=_set_remaining_days, type="float", help='Total number of legal leaves allocated to this employee, change this value to create allocation/leave request. Total based on all the leave types without overriding limit.'), @@ -566,7 +564,6 @@ class hr_employee(osv.osv): 'current_leave_id': fields.function(_get_leave_status, multi="leave_status", string="Current Leave Type",type='many2one', relation='hr.holidays.status'), 'leave_date_from': fields.function(_get_leave_status, multi='leave_status', type='date', string='From Date'), 'leave_date_to': fields.function(_get_leave_status, multi='leave_status', type='date', string='To Date'), - 'leave_ids': fields.one2many('hr.holidays', 'employee_id', 'Leaves'), 'leaves_count': fields.function(_leaves_count, type='integer', string='Leaves'), } diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py index e2cb1b3ad3f..1a34758fb50 100644 --- a/addons/hr_payroll/hr_payroll.py +++ b/addons/hr_payroll/hr_payroll.py @@ -261,11 +261,8 @@ class hr_payslip(osv.osv): def _count_detail_payslip(self, cr, uid, ids, field_name, arg, context=None): res = {} - try: - for details in self.browse(cr, uid, ids, context=context): - res[details.id] = len(details.line_ids) - except: - pass + for details in self.browse(cr, uid, ids, context=context): + res[details.id] = len(details.line_ids) return res _columns = { @@ -285,7 +282,6 @@ class hr_payslip(osv.osv): \n* If the payslip is under verification, the status is \'Waiting\'. \ \n* If the payslip is confirmed then status is set to \'Done\'.\ \n* When user cancel payslip the status is \'Rejected\'.'), -# 'line_ids': fields.one2many('hr.payslip.line', 'slip_id', 'Payslip Line', required=False, readonly=True, states={'draft': [('readonly', False)]}), 'line_ids': one2many_mod2('hr.payslip.line', 'slip_id', 'Payslip Lines', readonly=True, states={'draft':[('readonly',False)]}), 'company_id': fields.many2one('res.company', 'Company', required=False, readonly=True, states={'draft': [('readonly', False)]}), 'worked_days_line_ids': fields.one2many('hr.payslip.worked_days', 'payslip_id', 'Payslip Worked Days', required=False, readonly=True, states={'draft': [('readonly', False)]}), @@ -983,19 +979,16 @@ class hr_employee(osv.osv): return res def _payslip_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for employee in self.browse(cr, uid, ids, context=context): - res[employee.id] = len(employee.payslip_ids) - except: - pass - return res + Payslip = self.pool['hr.payslip'] + return { + employee_id: Payslip.search_count(cr,uid, [('employee_id', '=', employee_id)], context=context) + for employee_id in ids + } _columns = { 'slip_ids':fields.one2many('hr.payslip', 'employee_id', 'Payslips', required=False, readonly=True), 'total_wage': fields.function(_calculate_total_wage, method=True, type='float', string='Total Basic Salary', digits_compute=dp.get_precision('Payroll'), help="Sum of all current contract's wage of employee."), 'payslip_count': fields.function(_payslip_count, type='integer', string='Payslips'), - 'payslip_ids': fields.one2many('hr.payslip', 'employee_id', 'Payslips'), } diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py index b0f8c396793..9c69f5db94b 100644 --- a/addons/hr_recruitment/hr_recruitment.py +++ b/addons/hr_recruitment/hr_recruitment.py @@ -514,15 +514,14 @@ class hr_job(osv.osv): return res def _count_all(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'documents_count': 0, 'application_count': 0,}), ids)) - try: - for job in self.browse(cr, uid, ids, context=context): - res[job.id] = {'documents_count': len(job.document_ids), - 'application_count': len(job.applicant_ids), - } - except: - pass - return res + Applicant = self.pool['hr.applicant'] + return { + job_id: { + 'application_count': Applicant.search_count(cr,uid, [('job_id', '=', job_id)], context=context), + 'documents_count': len(self._get_attached_docs(cr, uid, [job_id], field_name, arg, context=context)[job_id]) + } + for job_id in ids + } _columns = { 'survey_id': fields.many2one('survey.survey', 'Interview Form', help="Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job"), diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index b771714c9b7..d1ad3aa64d1 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -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): @@ -134,15 +136,15 @@ class hr_timesheet_sheet(osv.osv): return hr_employee.attendance_action_change(cr, uid, employee_ids, context=context) def _count_all(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'timesheet_activity_count': 0, 'attendance_count': 0,}), ids)) - try: - for datas in self.browse(cr, uid, ids, context=context): - res[datas.id] = {'timesheet_activity_count': len(datas.timesheet_activity_ids), - 'attendance_count': len(datas.attendances_ids), - } - except: - pass - return res + Timesheet = self.pool['hr.analytic.timesheet'] + Attendance = self.pool['hr.attendance'] + return { + sheet_id: { + 'timesheet_activity_count': Timesheet.search_count(cr,uid, [('sheet_id','=', sheet_id)], context=context), + 'attendance_count': Attendance.search_count(cr,uid, [('sheed_id', '=', sheet_id)], context=context) + } + for sheet_id in ids + } _columns = { 'name': fields.char('Note', size=64, select=1, @@ -174,7 +176,6 @@ class hr_timesheet_sheet(osv.osv): 'account_ids': fields.one2many('hr_timesheet_sheet.sheet.account', 'sheet_id', 'Analytic accounts', readonly=True), 'company_id': fields.many2one('res.company', 'Company'), 'department_id':fields.many2one('hr.department','Department'), - 'timesheet_activity_ids': fields.one2many('hr.analytic.timesheet', 'sheet_id', 'Timesheet Activities'), 'timesheet_activity_count': fields.function(_count_all, type='integer', string='Timesheet Activities', multi=True), 'attendance_count': fields.function(_count_all, type='integer', string="Attendances", multi=True), } @@ -411,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 = { @@ -448,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) @@ -610,17 +648,13 @@ class hr_employee(osv.osv): _description = 'Employee' def _timesheet_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for employee in self.browse(cr, uid, ids, context=context): - res[employee.id] = len(employee.timesheet_ids) - except: - pass - return res + Sheet = self.pool['hr_timesheet_sheet.sheet'] + return { + employee_id: Sheet.search_count(cr,uid, [('employee_id', '=', employee_id)], context=context) + for employee_id in ids + } _columns = { - 'timesheet_ids': fields.one2many('hr_timesheet_sheet.sheet', 'employee_id', 'Timesheets'), - 'timesheet_count': fields.function(_timesheet_count, type='integer', string='Timsheets'), + 'timesheet_count': fields.function(_timesheet_count, type='integer', string='Timesheets'), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index a913d3c067d..4a069cb5428 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -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() diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 7147288f594..92e041bdc4c 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -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'}) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 112dff6bac6..b6166c69aef 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -385,7 +385,7 @@ class mail_thread(osv.AbstractModel): if not context.get('mail_notrack'): tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx) if tracked_fields: - initial_values = {thread_id: dict((item, False) for item in tracked_fields)} + initial_values = {thread_id: dict.fromkeys(tracked_fields, False)} self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx) return thread_id @@ -398,25 +398,24 @@ class mail_thread(osv.AbstractModel): track_ctx = dict(context) if 'lang' not in track_ctx: track_ctx['lang'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).lang + + tracked_fields = None if not context.get('mail_notrack'): tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx) - else: - tracked_fields = [] + if tracked_fields: records = self.browse(cr, uid, ids, context=track_ctx) - initial_values = dict((this.id, dict((key, getattr(this, key)) for key in tracked_fields.keys())) for this in records) + initial_values = dict((record.id, dict((key, getattr(record, key)) for key in tracked_fields)) + for record in records) # Perform write, update followers result = super(mail_thread, self).write(cr, uid, ids, values, context=context) self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values) - if not context.get('mail_notrack'): - # Perform the tracking - tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context) - else: - tracked_fields = None + # Perform the tracking if tracked_fields: self.message_track(cr, uid, ids, tracked_fields, initial_values, context=track_ctx) + return result def unlink(self, cr, uid, ids, context=None): @@ -434,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 @@ -453,14 +452,15 @@ class mail_thread(osv.AbstractModel): :return list: a list of (field_name, column_info obj), containing always tracked fields and modified on_change fields """ - lst = [] + tracked_fields = [] for name, column_info in self._all_columns.items(): visibility = getattr(column_info.column, 'track_visibility', False) if visibility == 'always' or (visibility == 'onchange' and name in updated_fields) or name in self._track: - lst.append(name) - if not lst: - return lst - return self.fields_get(cr, uid, lst, context=context) + tracked_fields.append(name) + + if tracked_fields: + return self.fields_get(cr, uid, tracked_fields, context=context) + return {} def message_track(self, cr, uid, ids, tracked_fields, initial_values, context=None): @@ -1871,4 +1871,4 @@ class mail_thread(osv.AbstractModel): message_obj.write(cr, uid, msg_ids_comment, {"res_id" : new_res_id, "model" : new_model}, context=context) message_obj.write(cr, uid, msg_ids_not_comment, {"res_id" : new_res_id, "model" : new_model, "subtype_id" : None}, context=context) - return True \ No newline at end of file + return True diff --git a/addons/mail/res_config.py b/addons/mail/res_config.py index c19eb4a38ee..2c94b432dc3 100644 --- a/addons/mail/res_config.py +++ b/addons/mail/res_config.py @@ -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") diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 06af2303239..ec7b0fa2911 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -187,7 +187,7 @@ -
+
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 537e3f5bfda..5e5afd9de7c 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -1111,24 +1111,22 @@ class mrp_production_product_line(osv.osv): class product_product(osv.osv): _inherit = "product.product" - def _bom_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'bom_count': 0, 'mo_count': 0, 'bom_strct':0}), ids)) - try: - for bom in self.browse(cr, uid, ids, context=context): - res[bom.id] = { - 'bom_count': len(bom.bom_ids), - 'mo_count': len(bom.mo_ids), - 'bom_strct':len(bom.bom_ids), - } - except: - pass - return res + def _bom_orders_count(self, cr, uid, ids, field_name, arg, context=None): + Bom = self.pool('mrp.bom') + Production = self.pool('mrp.production') + return { + product_id: { + 'bom_count': Bom.search_count(cr, uid, [('product_id', '=', product_id), ('bom_id', '=', False)], context=context), + 'mo_count': Production.search_count(cr,uid, [('product_id', '=', product_id)], context=context), + 'bom_strct': Bom.search_count(cr, uid, [('product_id', '=', product_id), ('bom_id', '=', False)], context=context), + } + for product_id in ids + } _columns = { 'bom_ids': fields.one2many('mrp.bom', 'product_id', 'Bill of Materials'), - 'mo_ids': fields.one2many('mrp.production', 'product_id', 'Manufacturing Orders'), - 'bom_count': fields.function(_bom_count, string='# Bill of Material', type='integer', multi="bom_count"), - 'bom_strct': fields.function(_bom_count, string='# Bill of Material Structure', type='integer', multi="bom_count"), - 'mo_count': fields.function(_bom_count, string='# Manufacturing Orders', type='integer', multi="bom_count"), + 'bom_count': fields.function(_bom_orders_count, string='# Bill of Material', type='integer', multi="_bom_order_count"), + 'bom_strct': fields.function(_bom_orders_count, string='# Bill of Material Structure', type='integer', multi="_bom_order_count"), + 'mo_count': fields.function(_bom_orders_count, string='# Manufacturing Orders', type='integer', multi="_bom_order_count"), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index 44a021c1434..d7d1af24f07 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -59,7 +59,7 @@ - + OpenERP US @@ -400,7 +400,7 @@ - + diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 931188f2ef6..7fe2be499a3 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -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): diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index a34e4171e75..94f428e3df5 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -615,15 +615,12 @@ class product_template(osv.osv): class product_product(osv.osv): _inherit="product.product" def _orderpoint_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for orderpoint in self.browse(cr, uid, ids, context=context): - res[orderpoint.id] = len(orderpoint.orderpoint_ids) - except: - pass - return res + OrderPoints = self.pool('stock.warehouse.orderpoint') + return { + product_id: OrderPoints.search_count(cr, uid, [('product_id', '=', product_id)], context=context) + for product_id in ids + } _columns = { - 'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'), 'orderpoint_count': fields.function(_orderpoint_count, string='# Orderpoints', type='integer'), } diff --git a/addons/project/res_partner.py b/addons/project/res_partner.py index 79af0413385..dd0c5fe0767 100644 --- a/addons/project/res_partner.py +++ b/addons/project/res_partner.py @@ -23,13 +23,11 @@ from openerp.osv import fields,osv class res_partner(osv.osv): def _task_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for partner in self.browse(cr, uid, ids, context): - res[partner.id] = len(partner.task_ids) - except: - pass - return res + Task = self.pool['project.task'] + return { + partner_id: Task.search_count(cr,uid, [('partner_id', '=', partner_id)], context=context) + for partner_id in ids + } """ Inherits partner and adds Tasks information in the partner form """ _inherit = 'res.partner' @@ -46,6 +44,4 @@ class res_partner(osv.osv): return super(res_partner, self).copy( cr, uid, record_id, default=default, context=context) - - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index 0ffd1b99fa5..768b3324f7e 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -474,10 +474,11 @@ class project(osv.Model): return [('project.task', "Tasks"), ("project.issue", "Issues")] def _issue_count(self, cr, uid, ids, field_name, arg, context=None): - res={} - for issues in self.browse(cr, uid, ids, context): - res[issues.id] = len(issues.issue_ids) - return res + Issue = self.pool['project.issue'] + return { + project_id: Issue.search_count(cr,uid, [('project_id', '=', project_id), ('stage_id.fold', '=', False)], context=context) + for project_id in ids + } _columns = { 'project_escalation_id': fields.many2one('project.project', 'Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.', @@ -554,18 +555,15 @@ class project_project(osv.Model): class res_partner(osv.osv): def _issue_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for partner in self.browse(cr, uid, ids, context=context): - res[partner.id] = len(partner.issue_ids) - except: - pass - return res + Issue = self.pool['project.issue'] + return { + partner_id: Issue.search_count(cr,uid, [('partner_id', '=', partner_id)]) + for partner_id in ids + } """ Inherits partner and adds Issue information in the partner form """ _inherit = 'res.partner' _columns = { - 'issue_ids': fields.one2many('project.issue', 'partner_id', 'Issues'), 'issue_count': fields.function(_issue_count, string='# Issues', type='integer'), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/partner.py b/addons/purchase/partner.py index b7757c2f91f..36ad724f0c4 100644 --- a/addons/purchase/partner.py +++ b/addons/purchase/partner.py @@ -25,22 +25,16 @@ class res_partner(osv.osv): _name = 'res.partner' _inherit = 'res.partner' - def _purchase_order_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'purchase_order_count': 0, 'supplier_invoice_count': 0}), ids)) - invoice_ids = self.pool.get('account.invoice').search(cr,uid, [('type', '=', 'in_invoice'), ('partner_id', '=', ids[0])]) - for partner in self.browse(cr, uid, ids, context=context): - res[partner.id] = { - 'purchase_order_count': len(partner.purchase_order_ids), - 'supplier_invoice_count': len(invoice_ids), - } - return res - def copy(self, cr, uid, id, default=None, context=None): - if default is None: - default = {} - - default.update({'purchase_order_ids': []}) - - return super(res_partner, self).copy(cr, uid, id, default=default, context=context) + def _purchase_invoice_count(self, cr, uid, ids, field_name, arg, context=None): + PurchaseOrder = self.pool['purchase.order'] + Invoice = self.pool['account.invoice'] + return { + partner_id: { + 'purchase_order_count': PurchaseOrder.search_count(cr,uid, [('partner_id', '=', partner_id)], context=context), + 'supplier_invoice_count': Invoice.search_count(cr,uid, [('partner_id', '=', partner_id), ('type','=','in_invoice')], context=context) + } + for partner_id in ids + } def _commercial_fields(self, cr, uid, context=None): return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_product_pricelist_purchase'] @@ -52,13 +46,9 @@ class res_partner(osv.osv): domain=[('type','=','purchase')], string="Purchase Pricelist", help="This pricelist will be used, instead of the default one, for purchases from the current partner"), - 'purchase_order_count': fields.function(_purchase_order_count, string='# of Purchase Order', type='integer', multi="count"), - 'purchase_order_ids': fields.one2many('purchase.order','partner_id','Purchase Order'), - 'invoice_ids': fields.one2many('account.invoice','partner_id','Supplier Invoices'), - 'supplier_invoice_count': fields.function(_purchase_order_count, string='# Supplier Invoices', type='integer', multi="count"), + 'purchase_order_count': fields.function(_purchase_invoice_count, string='# of Purchase Order', type='integer', multi="count"), + 'supplier_invoice_count': fields.function(_purchase_invoice_count, string='# Supplier Invoices', type='integer', multi="count"), } - - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 272ea77e7e3..457523d6d97 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -148,15 +148,13 @@ class purchase_order(osv.osv): return res and res[0] or False def _count_all(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,{'shipment_count': 0, 'invoice_count': 0,}), ids)) - try: - for data in self.browse(cr, uid, ids, context=context): - res[data.id] = {'shipment_count': len(data.picking_ids), - 'invoice_count': len(data.invoice_ids), - } - except: - pass - return res + return { + purchase.id: { + 'shipment_count': len(purchase.picking_ids), + 'invoice_count': len(purchase.invoice_ids), + } + for purchase in self.browse(cr, uid, ids, context=context) + } STATE_SELECTION = [ ('draft', 'Draft PO'), @@ -1296,15 +1294,13 @@ class product_product(osv.Model): _inherit = 'product.product' def _purchase_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for purchase in self.browse(cr, uid, ids, context=context): - res[purchase.id] = len(purchase.purchase_ids) - except: - pass - return res + Purchase = self.pool['purchase.order'] + return { + product_id: Purchase.search_count(cr,uid, [('order_line.product_id', '=', product_id)], context=context) + for product_id in ids + } + _columns = { - 'purchase_ids': fields.one2many('purchase.order', 'product_id', 'Purchases'), 'purchase_count': fields.function(_purchase_count, string='# Purchases', type='integer'), } diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 212555dbc8a..8b09fa35419 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -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 diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 9d938a42a0b..9b9cb48e91d 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -626,6 +626,48 @@ class sale_order(osv.osv): def action_done(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'done'}, context=context) + def onchange_fiscal_position(self, cr, uid, ids, fiscal_position, order_lines, context=None): + '''Update taxes of order lines for each line where a product is defined + + :param list ids: not used + :param int fiscal_position: sale order fiscal position + :param list order_lines: command list for one2many write method + ''' + order_line = [] + fiscal_obj = self.pool.get('account.fiscal.position') + product_obj = self.pool.get('product.product') + line_obj = self.pool.get('sale.order.line') + + fpos = False + if fiscal_position: + fpos = fiscal_obj.browse(cr, uid, fiscal_position, context=context) + + for line in order_lines: + # create (0, 0, { fields }) + # update (1, ID, { fields }) + if line[0] in [0, 1]: + prod = None + if line[2].get('product_id'): + prod = product_obj.browse(cr, uid, line[2]['product_id'], context=context) + elif line[1]: + prod = line_obj.browse(cr, uid, line[1], context=context).product_id + if prod and prod.taxes_id: + line[2]['tax_id'] = [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]] + order_line.append(line) + + # link (4, ID) + # link all (6, 0, IDS) + elif line[0] in [4, 6]: + line_ids = line[0] == 4 and [line[1]] or line[2] + for line_id in line_ids: + prod = line_obj.browse(cr, uid, line_id, context=context).product_id + if prod and prod.taxes_id: + order_line.append([1, line_id, {'tax_id': [[6, 0, fiscal_obj.map_tax(cr, uid, fpos, prod.taxes_id)]]}]) + else: + order_line.append([4, line_id]) + else: + order_line.append(line) + return {'value': {'order_line': order_line}} # TODO add a field price_unit_uos @@ -862,15 +904,15 @@ class sale_order_line(osv.osv): lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or {} lang = lang or context.get('lang',False) - if not partner_id: + if not partner_id: raise osv.except_osv(_('No Customer Defined!'), _('Before choosing a product,\n select a customer in the sales form.')) warning = {} product_uom_obj = self.pool.get('product.uom') partner_obj = self.pool.get('res.partner') product_obj = self.pool.get('product.product') context = {'lang': lang, 'partner_id': partner_id} - if partner_id: - lang = partner_obj.browse(cr, uid, partner_id).lang + partner = partner_obj.browse(cr, uid, partner_id) + lang = partner.lang context_partner = {'lang': lang, 'partner_id': partner_id} if not product: @@ -896,7 +938,12 @@ class sale_order_line(osv.osv): uos = False else: uos = False - fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False + + fpos = False + if not fiscal_position: + fpos = partner.property_account_position or False + else: + fpos = self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) if update_tax: #The quantity only have changed result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id) @@ -1027,15 +1074,12 @@ class account_invoice(osv.Model): class product_product(osv.Model): _inherit = 'product.product' def _sales_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for sale in self.browse(cr, uid, ids, context=context): - res[sale.id] = len(sale.sales_ids) - except: - pass - return res + SaleOrderLine = self.pool['sale.order.line'] + return { + product_id: SaleOrderLine.search_count(cr,uid, [('product_id', '=', product_id)], context=context) + for product_id in ids + } _columns = { - 'sales_ids': fields.one2many('sale.order.line', 'product_id', 'Sales '), 'sales_count': fields.function(_sales_count, string='# Sales', type='integer'), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 0090c4a9bfc..600505bfdf1 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -206,7 +206,8 @@ - + diff --git a/addons/stock/product.py b/addons/stock/product.py index 863b7111bb0..9ac1a644f30 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -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: @@ -353,13 +355,11 @@ class product_product(osv.osv): res[id][f] = stock.get(id, 0.0) return res def _move_count(self, cr, uid, ids, field_name, arg, context=None): - res = dict(map(lambda x: (x,0), ids)) - try: - for move in self.browse(cr, uid, ids, context=context): - res[move.id] = len(move.move_ids) - except: - pass - return res + Move = self.pool['stock.move'] + return { + product_id: Move.search_count(cr, uid, [('product_id', '=', product_id)], context=context) + for product_id in ids + } _columns = { 'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'), 'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'), @@ -420,7 +420,6 @@ class product_product(osv.osv): help="If real-time valuation is enabled for a product, the system will automatically write journal entries corresponding to stock moves." \ "The inventory variation account set on the product category will represent the current inventory value, and the stock input and stock output account will hold the counterpart moves for incoming and outgoing products." , required=True), - 'move_ids': fields.one2many('stock.move', 'product_id', 'Moves'), 'move_count': fields.function(_move_count, string='# Moves', type='integer'), } diff --git a/addons/stock/stock.py b/addons/stock/stock.py index dd6c9ca3681..5e527a77fb9 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -636,11 +636,7 @@ class stock_picking(osv.osv): vals['name'] = self.pool.get('ir.sequence').get(cr, user, seq_obj_name) new_id = super(stock_picking, self).create(cr, user, vals, context) return new_id - def _claim_count(self, cr, uid, ids, field_name, arg, context=None): - res = {} - claim = self.pool.get('crm.claim').search(cr, uid, [('ref', '=',('stock.picking.out,' + str(ids[0])))], context=context) - res[ids[0]] = len(claim) - return res + _columns = { 'name': fields.char('Reference', size=64, select=True, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}), 'origin': fields.char('Source Document', size=64, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="Reference of the document", select=True), @@ -684,7 +680,6 @@ class stock_picking(osv.osv): ("none", "Not Applicable")], "Invoice Control", select=True, required=True, readonly=True, track_visibility='onchange', states={'draft': [('readonly', False)]}), 'company_id': fields.many2one('res.company', 'Company', required=True, select=True, states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}), - 'claim_count': fields.function(_claim_count, string='Claims', type='integer'), } _defaults = { 'name': lambda self, cr, uid, context: '/', @@ -2312,7 +2307,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 @@ -3136,8 +3133,6 @@ class stock_picking_out(osv.osv): out_defaults = super(stock_picking_out, self).default_get(cr, uid, fields_list, context=context) defaults.update(out_defaults) return defaults - def _claim_count(self, cr, uid, ids, field_name, arg, context=None): - return super(stock_picking_out, self)._claim_count(cr, uid, ids, field_name, arg, context=context) _columns = { 'backorder_id': fields.many2one('stock.picking.out', 'Back Order of', states={'done':[('readonly', True)], 'cancel':[('readonly',True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True), @@ -3155,7 +3150,6 @@ class stock_picking_out(osv.osv): * Ready to Deliver: products reserved, simply waiting for confirmation.\n * Delivered: has been processed, can't be modified or cancelled anymore\n * Cancelled: has been cancelled, can't be confirmed anymore"""), - 'claim_count': fields.function(_claim_count, string='Claims', type='integer'), } _defaults = { 'type': 'out', diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 8ae9da33c30..ac6636147c1 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -811,7 +811,7 @@ - + @@ -945,7 +945,7 @@ - +
@@ -1072,7 +1072,7 @@ - +
@@ -1359,7 +1359,7 @@ - + diff --git a/addons/warning/warning.py b/addons/warning/warning.py index d582478113a..539316482d2 100644 --- a/addons/warning/warning.py +++ b/addons/warning/warning.py @@ -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) diff --git a/addons/website/__openerp__.py b/addons/website/__openerp__.py index f2b31726468..9de078a8a48 100644 --- a/addons/website/__openerp__.py +++ b/addons/website/__openerp__.py @@ -12,7 +12,7 @@ OpenERP Website CMS 'depends': ['web', 'share', 'mail'], 'installable': True, 'data': [ - 'data/website_data.xml', + 'data/data.xml', 'security/ir.model.access.csv', 'security/ir_ui_view.xml', 'views/website_templates.xml', @@ -23,7 +23,7 @@ OpenERP Website CMS 'views/ir_actions.xml', ], 'demo': [ - 'data/website_demo.xml', + 'data/demo.xml', ], 'qweb': ['static/src/xml/website.backend.xml'], 'application': True, diff --git a/addons/website/data/website_data.xml b/addons/website/data/data.xml similarity index 100% rename from addons/website/data/website_data.xml rename to addons/website/data/data.xml diff --git a/addons/website/data/website_demo.xml b/addons/website/data/demo.xml similarity index 100% rename from addons/website/data/website_demo.xml rename to addons/website/data/demo.xml diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 8d8e0b3c91d..2a774939c60 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -32,6 +32,13 @@ class ir_http(orm.AbstractModel): page=PageConverter, ) + def _auth_method_public(self): + # TODO: select user_id from matching website + if not request.session.uid: + request.uid = self.pool['ir.model.data'].xmlid_to_res_id(request.cr, openerp.SUPERUSER_ID, 'base.public_user') + else: + request.uid = request.session.uid + def _dispatch(self): first_pass = not hasattr(request, 'website') request.website = None @@ -54,7 +61,6 @@ class ir_http(orm.AbstractModel): if first_pass: request.lang = request.website.default_lang_code request.context['lang'] = request.lang - request.website.preprocess_request(request) if not func: path = request.httprequest.path.split('/') langs = [lg[0] for lg in request.website.get_languages()] diff --git a/addons/website/models/website.py b/addons/website/models/website.py index d0aca1c815f..3320ad9a038 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -109,10 +109,6 @@ class website(osv.osv): menu = menus and menus[0] or False return dict( map(lambda x: (x, menu), ids) ) - def _get_public_user(self, cr, uid, ids, name='public_user', arg=(), context=None): - ref = self.get_public_user(cr, uid, context=context) - return dict( map(lambda x: (x, ref), ids) ) - _name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco _description = "Website" _columns = { @@ -129,13 +125,17 @@ class website(osv.osv): 'social_googleplus': fields.char('Google+ Account'), 'google_analytics_key': fields.char('Google Analytics Key'), 'user_id': fields.many2one('res.users', string='Public User'), - 'public_user': fields.function(_get_public_user, relation='res.users', type='many2one', string='Public User'), + 'partner_id': fields.related('user_id','partner_id', type='many2one', relation='res.partner', string='Public Partner'), 'menu_id': fields.function(_get_menu, relation='website.menu', type='many2one', string='Main Menu', store= { 'website.menu': (_get_menu_website, ['sequence','parent_id','website_id'], 10) }) } + _defaults = { + 'company_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID, 'base.public_user'), + } + # cf. Wizard hack in website_views.xml def noop(self, *args, **kwargs): pass @@ -186,11 +186,6 @@ class website(osv.osv): except: return False - def get_public_user(self, cr, uid, context=None): - uid = openerp.SUPERUSER_ID - res = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'public_user') - return res and res[1] or False - @openerp.tools.ormcache(skiparg=3) def _get_languages(self, cr, uid, id, context=None): website = self.browse(cr, uid, id) @@ -203,9 +198,6 @@ class website(osv.osv): # TODO: Select website, currently hard coded return self.pool['website'].browse(cr, uid, 1, context=context) - def preprocess_request(self, cr, uid, ids, request, context=None): - pass - def is_publisher(self, cr, uid, ids, context=None): Access = self.pool['ir.model.access'] is_website_publisher = Access.check(cr, uid, 'ir.ui.view', 'write', False, context) @@ -342,7 +334,7 @@ class website(osv.osv): """ router = request.httprequest.app.get_db_router(request.db) # Force enumeration to be performed as public user - uid = self.get_public_user(cr, uid, context=context) + uid = request.website.user_id.id url_list = [] for rule in router.iter_rules(): if not self.rule_is_enumerable(rule): diff --git a/addons/website/security/ir.model.access.csv b/addons/website/security/ir.model.access.csv index 1a9ccccba5c..8682a349f70 100644 --- a/addons/website/security/ir.model.access.csv +++ b/addons/website/security/ir.model.access.csv @@ -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 diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index be69c66b615..595df04a088 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1056,6 +1056,7 @@ this.trigger("saved"); }, cancel: function () { + this.trigger("cancel"); }, close: function () { this.$el.modal('hide'); diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 8f49409924d..806b2ab4e0c 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -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 = $(''); + $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")); } diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index 2a661b4cc9b..0544d29df08 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -104,11 +104,11 @@ var T = website.Tour = { if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) { var href = "/"+T.getLang()+tour.path; console.log("Tour Begin from run method (redirection to "+href+")"); - T.saveState(tour.id, mode || tour.mode, -1); + T.saveState(tour.id, mode || tour.mode, -1, 0); window.location.href = href; } else { console.log("Tour Begin from run method"); - T.saveState(tour.id, mode || tour.mode, 0); + T.saveState(tour.id, mode || tour.mode, 0, 0); T.running(); } }, @@ -311,7 +311,7 @@ var T = website.Tour = { }; window.location.hash = ""; console.log("Tour Begin from url hash"); - T.saveState(state.id, state.mode, state.step_id); + T.saveState(state.id, state.mode, state.step_id, 0); } if (!state.id) { return; @@ -341,8 +341,8 @@ var T = website.Tour = { } return tour_ids; }, - saveState: function (tour_id, mode, step_id) { - localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time})); + saveState: function (tour_id, mode, step_id, number) { + localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time, "number": number+1})); }, reset: function () { var state = T.getState(); @@ -402,6 +402,7 @@ var T = website.Tour = { if (T.check(next)) { clearTimeout(T.currentTimer); // use an other timeout for cke dom loading + T.saveState(state.id, state.mode, state.step.id, 0); setTimeout(function () { T.nextStep(next); }, T.defaultDelay); @@ -421,7 +422,13 @@ var T = website.Tour = { } step = step || state.step; - T.saveState(state.id, state.mode, step.id); + var next = state.tour.steps[step.id+1]; + + if (state.number > 3) { + T.error(next, "Cycling. Can't reach the next step"); + } + + T.saveState(state.id, state.mode, step.id, state.number); if (step.id !== state.step_id) { console.log("Tour Step: '" + (step._title || step.title) + "' (" + (new Date().getTime() - this.time) + "ms)"); @@ -433,7 +440,6 @@ var T = website.Tour = { step.onload(); } - var next = state.tour.steps[step.id+1]; if (next) { setTimeout(function () { T.waitNextStep(); diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index aae57e32a93..b00e7038d5c 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -34,6 +34,7 @@ import time from dateutil.relativedelta import relativedelta from openerp import tools import werkzeug.urls +from openerp.addons.website.models.website import slug try: import GeoIP @@ -211,7 +212,8 @@ class website_event(http.Controller): 'date_end': (date_begin + timedelta(days=(1))).strftime('%Y-%m-%d'), } event_id = Event.create(request.cr, request.uid, vals, context=context) - return request.redirect("/event/%s?enable_editor=1" % event_id) + event = Event.browse(request.cr, request.uid, event_id, context=context) + return request.redirect("/event/%s/register?enable_editor=1" % slug(event)) def get_visitors_country(self): GI = GeoIP.open('/usr/share/GeoIP/GeoIP.dat', 0) diff --git a/addons/website_event/security/ir.model.access.csv b/addons/website_event/security/ir.model.access.csv index 2d98213669f..aeb66c3e088 100644 --- a/addons/website_event/security/ir.model.access.csv +++ b/addons/website_event/security/ir.model.access.csv @@ -1,3 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_event_event_public,event.event.public,event.model_event_event,base.group_public,1,0,0,0 +access_event_event_portal,event.event.portal,event.model_event_event,base.group_portal,1,0,0,0 access_event_type_public,event.type.public,event.model_event_type,base.group_public,1,0,0,0 +access_event_type_portal,event.type.portal,event.model_event_type,base.group_portal,1,0,0,0 diff --git a/addons/website_event_sale/controllers/main.py b/addons/website_event_sale/controllers/main.py index 2db874cf5b7..1c39484f8c8 100644 --- a/addons/website_event_sale/controllers/main.py +++ b/addons/website_event_sale/controllers/main.py @@ -27,57 +27,24 @@ from openerp.tools.translate import _ class website_event(website_event): - @http.route(['/event/add_cart'], type='http', auth="public", website=True, multilang=True) - def add_cart(self, event_id, **post): - user_obj = request.registry['res.users'] - order_line_obj = request.registry.get('sale.order.line') + + @http.route(['/event/cart/update'], type='http', auth="public", methods=['POST'], website=True, multilang=True) + def cart_update(self, event_id, **post): + cr, uid, context = request.cr, request.uid, request.context ticket_obj = request.registry.get('event.event.ticket') - order_obj = request.registry.get('sale.order') - website = request.registry['website'] - order = website.ecommerce_get_current_order(request.cr, request.uid, context=request.context) - if not order: - order = website.ecommerce_get_new_order(request.cr, request.uid, context=request.context) - - partner_id = user_obj.browse(request.cr, SUPERUSER_ID, request.uid, - context=request.context).partner_id.id - - fields = [k for k, v in order_line_obj._columns.items()] - values = order_line_obj.default_get(request.cr, SUPERUSER_ID, fields, - context=request.context) - - _values = None + sale = False for key, value in post.items(): - try: - quantity = int(value) - assert quantity > 0 - except: - quantity = None - ticket_id = key.split("-")[0] == 'ticket' and int(key.split("-")[1]) or None - if not ticket_id or not quantity: + quantity = int(value or "0") + if not quantity: continue - ticket = ticket_obj.browse(request.cr, request.uid, ticket_id, - context=request.context) + sale = True + ticket_id = key.split("-")[0] == 'ticket' and int(key.split("-")[1]) or None + ticket = ticket_obj.browse(cr, SUPERUSER_ID, ticket_id, context=context) + request.website.sale_get_order(force_create=1)._cart_update( + product_id=ticket.product_id.id, add_qty=quantity, context=dict(context, event_ticket_id=ticket.id)) - values['product_id'] = ticket.product_id.id - values['event_id'] = ticket.event_id.id - values['event_ticket_id'] = ticket.id - values['product_uom_qty'] = quantity - values['price_unit'] = ticket.price - values['order_id'] = order.id - values['name'] = "%s: %s" % (ticket.event_id.name, ticket.name) - - # change and record value - pricelist_id = order.pricelist_id and order.pricelist_id.id or False - _values = order_line_obj.product_id_change( - request.cr, SUPERUSER_ID, [], pricelist_id, ticket.product_id.id, - partner_id=partner_id, context=request.context)['value'] - _values.update(values) - - order_line_id = order_line_obj.create(request.cr, SUPERUSER_ID, _values, context=request.context) - order_obj.write(request.cr, SUPERUSER_ID, [order.id], {'order_line': [(4, order_line_id)]}, context=request.context) - - if not _values: + if not sale: return request.redirect("/event/%s" % event_id) return request.redirect("/shop/checkout") diff --git a/addons/website_event_sale/models/__init__.py b/addons/website_event_sale/models/__init__.py index b0e3f323f8c..ed23b1cd133 100644 --- a/addons/website_event_sale/models/__init__.py +++ b/addons/website_event_sale/models/__init__.py @@ -1,3 +1,3 @@ import product -import sale_order import website +import sale_order diff --git a/addons/website_event_sale/models/sale_order.py b/addons/website_event_sale/models/sale_order.py index 066fd98fc8a..91f282a1c00 100644 --- a/addons/website_event_sale/models/sale_order.py +++ b/addons/website_event_sale/models/sale_order.py @@ -1,22 +1,49 @@ # -*- coding: utf-8 -*- -from openerp.osv import osv from openerp import SUPERUSER_ID -from openerp.addons.web.http import request +from openerp.osv import osv, fields +from openerp.tools.translate import _ +# defined for access rules +class sale_order(osv.Model): + _inherit = "sale.order" -class sale_order_line(osv.osv): - _inherit = "sale.order.line" + def _cart_find_product_line(self, cr, uid, ids, product_id=None, line_id=None, context=None): + for so in self.browse(cr, uid, ids, context=context): + order_line_id = None + domain = [('order_id', '=', so.id), ('product_id', '=', product_id)] + if line_id: + domain += [('id', '=', line_id)] + elif context.get("event_ticket_id"): + domain += [('event_ticket_id', '=', context.get("event_ticket_id"))] + order_line_ids = self.pool.get('sale.order.line').search(cr, SUPERUSER_ID, domain, context=context) + if order_line_ids: + order_line_id = order_line_ids[0] + return order_line_id - def _recalculate_product_values(self, cr, uid, ids, product_id=0, fiscal_position=False, context=None): - if not ids: - return super(sale_order_line, self)._recalculate_product_values(cr, uid, ids, product_id, fiscal_position=fiscal_position, context=context) + def _website_product_id_change(self, cr, uid, ids, order_id, product_id, line_id=None, context=None): + values = super(sale_order,self)._website_product_id_change(cr, uid, ids, order_id, product_id, line_id=None, context=None) - order_line = self.browse(cr, SUPERUSER_ID, ids[0], context=context) - assert order_line.order_id.website_session_id == request.session['website_session_id'] + event_ticket_id = None + if context.get("event_ticket_id"): + event_ticket_id = context.get("event_ticket_id") + elif line_id: + line = self.pool.get('sale.order.line').browse(cr, SUPERUSER_ID, line_id, context=context) + if line.event_ticket_id: + event_ticket_id = line.event_ticket_id.id + else: + product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) + if product.event_ticket_ids: + event_ticket_id = product.event_ticket_ids[0] - product = product_id and self.pool.get('product.product').browse(cr, uid, product_id, context=context) or order_line.product_id - res = super(sale_order_line, self)._recalculate_product_values(cr, uid, ids, product.id, fiscal_position=fiscal_position, context=context) - if product.event_type_id and order_line.event_ticket_id and order_line.event_ticket_id.price != product.lst_price: - res.update({'price_unit': order_line.event_ticket_id.price}) + if event_ticket_id: + ticket = self.pool.get('event.event.ticket').browse(cr, uid, event_ticket_id, context=context) + if product_id != ticket.product_id.id: + raise osv.except_osv(_('Error!'),_("The ticket doesn't match with this product.")) - return res + values['product_id'] = ticket.product_id.id + values['event_id'] = ticket.event_id.id + values['event_ticket_id'] = ticket.id + values['price_unit'] = ticket.price + values['name'] = "%s: %s" % (ticket.event_id.name, ticket.name) + + return values diff --git a/addons/website_event_sale/models/website.py b/addons/website_event_sale/models/website.py index e41a7092404..83c653a3999 100644 --- a/addons/website_event_sale/models/website.py +++ b/addons/website_event_sale/models/website.py @@ -5,6 +5,6 @@ from openerp.osv import orm class Website(orm.Model): _inherit = 'website' - def ecommerce_get_product_domain(self): + def sale_product_domain(self, cr, uid, ids, context=None): # remove product event from the website content grid and list view (not removed in detail view) - return ['&'] + super(Website, self).ecommerce_get_product_domain() + [('event_ok', '=', False)] + return ['&'] + super(Website, self).sale_product_domain(cr, uid, ids, context=context) + [('event_ok', '=', False)] diff --git a/addons/website_event_sale/views/website_event_sale.xml b/addons/website_event_sale/views/website_event_sale.xml index f8f3436f17e..b2f5d2a78f5 100644 --- a/addons/website_event_sale/views/website_event_sale.xml +++ b/addons/website_event_sale/views/website_event_sale.xml @@ -20,7 +20,7 @@ -