diff --git a/addons/account/__init__.py b/addons/account/__init__.py index 90fbdb83980..bc27e14380c 100644 --- a/addons/account/__init__.py +++ b/addons/account/__init__.py @@ -19,10 +19,10 @@ # ############################################################################## +import partner import account import installer import project -import partner import account_invoice import account_bank_statement import account_bank diff --git a/addons/account/account.py b/addons/account/account.py index cbba0237c78..fa30b20f2ca 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -125,7 +125,7 @@ class account_payment_term_line(osv.osv): return True _constraints = [ - (_check_percent, 'Percentages for Payment Term Line must be between 0 and 1, Example: 0.02 for 2% ', ['value_amount']), + (_check_percent, 'Percentages for Payment Term Line must be between 0 and 1, Example: 0.02 for 2%.', ['value_amount']), ] account_payment_term_line() @@ -136,7 +136,7 @@ class account_account_type(osv.osv): def _get_current_report_type(self, cr, uid, ids, name, arg, context=None): obj_data = self.pool.get('ir.model.data') - obj_financial_report = self.pool.get('account.financial.report') + obj_financial_report = self.pool.get('account.financial.report') res = {} financial_report_ref = { 'asset': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_assets0')[1], context=context), @@ -154,7 +154,7 @@ class account_account_type(osv.osv): def _save_report_type(self, cr, uid, account_type_id, field_name, field_value, arg, context=None): obj_data = self.pool.get('ir.model.data') - obj_financial_report = self.pool.get('account.financial.report') + obj_financial_report = self.pool.get('account.financial.report') #unlink if it exists somewhere in the financial reports related to BS or PL financial_report_ref = { 'asset': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_assets0')[1], context=context), @@ -179,7 +179,7 @@ class account_account_type(osv.osv): 'Balance' will generally be used for cash accounts. 'Detail' will copy each existing journal item of the previous year, even the reconciled ones. 'Unreconciled' will copy only the journal items that were unreconciled on the first day of the new fiscal year."""), - 'report_type': fields.function(_get_current_report_type, fnct_inv=_save_report_type, type='selection', string='P&L / BS Category', + 'report_type': fields.function(_get_current_report_type, fnct_inv=_save_report_type, type='selection', string='P&L / BS Category', selection= [('none','/'), ('income', _('Profit & Loss (Income account)')), ('expense', _('Profit & Loss (Expense account)')), @@ -404,12 +404,12 @@ class account_account(osv.osv): journal_obj = self.pool.get('account.journal') jids = journal_obj.search(cr, uid, [('type','=','situation'),('centralisation','=',1),('company_id','=',account.company_id.id)], context=context) if not jids: - raise osv.except_osv(_('Error!'),_("You need an Opening journal with centralisation checked to set the initial balance!")) + raise osv.except_osv(_('Error!'),_("You need an Opening journal with centralisation checked to set the initial balance.")) period_obj = self.pool.get('account.period') pids = period_obj.search(cr, uid, [('special','=',True),('company_id','=',account.company_id.id)], context=context) if not pids: - raise osv.except_osv(_('Error!'),_("No opening/closing period defined, please create one to set the initial balance!")) + raise osv.except_osv(_('Error!'),_("There is no opening/closing period defined, please create one to set the initial balance.")) move_obj = self.pool.get('account.move.line') move_id = move_obj.search(cr, uid, [ @@ -426,7 +426,7 @@ class account_account(osv.osv): }, context=context) else: if diff<0.0: - raise osv.except_osv(_('Error!'),_("Unable to adapt the initial balance (negative value)!")) + raise osv.except_osv(_('Error!'),_("Unable to adapt the initial balance (negative value).")) nameinv = (name=='credit' and 'debit') or 'credit' move_id = move_obj.create(cr, uid, { 'name': _('Opening Balance'), @@ -541,9 +541,9 @@ class account_account(osv.osv): return True _constraints = [ - (_check_recursion, 'Error ! You can not create recursive accounts.', ['parent_id']), - (_check_type, 'Configuration Error! \nYou can not define children to an account with internal type different of "View"! ', ['type']), - (_check_account_type, 'Configuration Error! \nYou can not select an account type with a deferral method different of "Unreconciled" for accounts with internal type "Payable/Receivable"! ', ['user_type','type']), + (_check_recursion, 'Error!\nYou cannot create recursive accounts.', ['parent_id']), + (_check_type, 'Configuration Error!\nYou cannot define children to an account with internal type different of "View".', ['type']), + (_check_account_type, 'Configuration Error!\nYou cannot select an account type with a deferral method different of "Unreconciled" for accounts with internal type "Payable/Receivable".', ['user_type','type']), ] _sql_constraints = [ ('code_company_uniq', 'unique (code,company_id)', 'The code of the account must be unique per company !') @@ -619,14 +619,14 @@ class account_account(osv.osv): if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]): if method == 'write': - raise osv.except_osv(_('Error !'), _('You can not desactivate an account that contains some journal items.')) + raise osv.except_osv(_('Error!'), _('You cannot deactivate an account that contains journal items.')) elif method == 'unlink': - raise osv.except_osv(_('Error !'), _('You can not remove an account containing journal items.')) + raise osv.except_osv(_('Error!'), _('You cannot remove an account that contains journal items.')) #Checking whether the account is set as a property to any Partner or not value = 'account.account,' + str(ids[0]) partner_prop_acc = self.pool.get('ir.property').search(cr, uid, [('value_reference','=',value)], context=context) if partner_prop_acc: - raise osv.except_osv(_('Warning !'), _('You can not remove/desactivate an account which is set on a customer or supplier.')) + raise osv.except_osv(_('Warning!'), _('You cannot remove/deactivate an account which is set on a customer or supplier.')) return True def _check_allow_type_change(self, cr, uid, ids, new_type, context=None): @@ -639,10 +639,10 @@ class account_account(osv.osv): if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]): #Check for 'Closed' type if old_type == 'closed' and new_type !='closed': - raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type which contains journal items!")) + raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from 'Closed' to any other type which contains journal items!")) #Check for change From group1 to group2 and vice versa if (old_type in group1 and new_type in group2) or (old_type in group2 and new_type in group1): - raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from '%s' to '%s' type as it contains journal items!") % (old_type,new_type,)) + raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from '%s' to '%s' type as it contains journal items!") % (old_type,new_type,)) return True def write(self, cr, uid, ids, vals, context=None): @@ -661,7 +661,7 @@ class account_account(osv.osv): # Allow the write if the value is the same for i in [i['company_id'][0] for i in self.read(cr,uid,ids,['company_id'])]: if vals['company_id']!=i: - raise osv.except_osv(_('Warning !'), _('You cannot change the owner company of an account that already contains journal items.')) + raise osv.except_osv(_('Warning!'), _('You cannot change the owner company of an account that already contains journal items.')) if 'active' in vals and not vals['active']: self._check_moves(cr, uid, ids, "write", context=context) if 'type' in vals.keys(): @@ -730,7 +730,7 @@ class account_journal(osv.osv): 'view_id': fields.many2one('account.journal.view', 'Display Mode', required=True, help="Gives the view used when writing or browsing entries in this journal. The view tells OpenERP which fields should be visible, required or readonly and in which order. You can create your own view for a faster encoding in each journal."), 'default_credit_account_id': fields.many2one('account.account', 'Default Credit Account', domain="[('type','!=','view')]", help="It acts as a default account for credit amount"), 'default_debit_account_id': fields.many2one('account.account', 'Default Debit Account', domain="[('type','!=','view')]", help="It acts as a default account for debit amount"), - 'centralisation': fields.boolean('Centralised counterpart', help="Check this box to determine that each entry of this journal won't create a new counterpart but will share the same counterpart. This is used in fiscal year closing."), + 'centralisation': fields.boolean('Centralised Counterpart', help="Check this box to determine that each entry of this journal won't create a new counterpart but will share the same counterpart. This is used in fiscal year closing."), 'update_posted': fields.boolean('Allow Cancelling Entries', help="Check this box if you want to allow the cancellation the entries related to this journal or of the invoice related to this journal"), 'group_invoice_lines': fields.boolean('Group Invoice Lines', help="If this box is checked, the system will try to group the accounting lines when generating them from invoices."), 'sequence_id': fields.many2one('ir.sequence', 'Entry Sequence', help="This field contains the information related to the numbering of the journal entries of this journal.", required=True), @@ -768,7 +768,7 @@ class account_journal(osv.osv): return True _constraints = [ - (_check_currency, 'Configuration error! The currency chosen should be shared by the default accounts too.', ['currency','default_debit_account_id','default_credit_account_id']), + (_check_currency, 'Configuration error!\nThe currency chosen should be shared by the default accounts too.', ['currency','default_debit_account_id','default_credit_account_id']), ] def copy(self, cr, uid, id, default={}, context=None, done_list=[], local=False): @@ -790,7 +790,7 @@ class account_journal(osv.osv): if 'company_id' in vals and journal.company_id.id != vals['company_id']: move_lines = self.pool.get('account.move.line').search(cr, uid, [('journal_id', 'in', ids)]) if move_lines: - raise osv.except_osv(_('Warning !'), _('You can not modify the company of this journal as its related record exist in journal items')) + raise osv.except_osv(_('Warning!'), _('This journal already contains items, therefore you cannot modify its company field.')) return super(account_journal, self).write(cr, uid, ids, vals, context=context) def create_sequence(self, cr, uid, vals, context=None): @@ -915,7 +915,7 @@ class account_fiscalyear(osv.osv): return True _constraints = [ - (_check_duration, 'Error! The start date of the fiscal year must be before his end date.', ['date_start','date_stop']) + (_check_duration, 'Error!\nThe start date of a fiscal year must precede its end date.', ['date_start','date_stop']) ] def create_period3(self, cr, uid, ids, context=None): @@ -966,7 +966,7 @@ class account_fiscalyear(osv.osv): ids = self.search(cr, uid, args, context=context) if not ids: if exception: - raise osv.except_osv(_('Error !'), _('No fiscal year defined for this date !\nPlease create one from the configuration of the accounting menu.')) + raise osv.except_osv(_('Error!'), _('There is no fiscal year defined for this date.\nPlease create one from the configuration of the accounting menu.')) else: return [] return ids @@ -1032,8 +1032,8 @@ class account_period(osv.osv): return True _constraints = [ - (_check_duration, 'Error ! The duration of the Period(s) is/are invalid. ', ['date_stop']), - (_check_year_limit, 'Invalid period ! Some periods overlap or the date period is not in the scope of the fiscal year. ', ['date_stop']) + (_check_duration, 'Error!\nThe duration of the Period(s) is/are invalid.', ['date_stop']), + (_check_year_limit, 'Error!\nThe period is invalid. Either some periods are overlapping or the period\'s dates are not matching the scope of the fiscal year.', ['date_stop']) ] def next(self, cr, uid, period, step, context=None): @@ -1055,7 +1055,7 @@ class account_period(osv.osv): args.append(('company_id', '=', company_id)) ids = self.search(cr, uid, args, context=context) if not ids: - raise osv.except_osv(_('Error !'), _('No period defined for this date: %s !\nPlease create one.')%dt) + raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt) return ids def action_draft(self, cr, uid, ids, *args): @@ -1080,7 +1080,7 @@ class account_period(osv.osv): if 'company_id' in vals: move_lines = self.pool.get('account.move.line').search(cr, uid, [('period_id', 'in', ids)]) if move_lines: - raise osv.except_osv(_('Warning !'), _('You can not modify company of this period as some journal items exists.')) + raise osv.except_osv(_('Warning!'), _('This journal already contains items for this period, therefore you cannot modify its company field.')) return super(account_period, self).write(cr, uid, ids, vals, context=context) def build_ctx_periods(self, cr, uid, period_from_id, period_to_id): @@ -1093,9 +1093,9 @@ class account_period(osv.osv): period_date_stop = period_to.date_stop company2_id = period_to.company_id.id if company1_id != company2_id: - raise osv.except_osv(_('Error'), _('You should have chosen periods that belongs to the same company')) + raise osv.except_osv(_('Error!'), _('You should choose the periods that belong to the same company.')) if period_date_start > period_date_stop: - raise osv.except_osv(_('Error'), _('Start period should be smaller then End period')) + raise osv.except_osv(_('Error!'), _('Start period should precede then end period.')) #for period from = january, we want to exclude the opening period (but it has same date_from, so we have to check if period_from is special or not to include that clause or not in the search). if period_from.special: return self.search(cr, uid, [('date_start', '>=', period_date_start), ('date_stop', '<=', period_date_stop), ('company_id', '=', company1_id)]) @@ -1134,7 +1134,7 @@ class account_journal_period(osv.osv): cr.execute('select * from account_move_line where journal_id=%s and period_id=%s limit 1', (obj.journal_id.id, obj.period_id.id)) res = cr.fetchall() if res: - raise osv.except_osv(_('Error !'), _('You can not modify/delete a journal with entries for this period !')) + raise osv.except_osv(_('Error!'), _('You cannot modify/delete a journal with entries for this period.')) return True def write(self, cr, uid, ids, vals, context=None): @@ -1303,7 +1303,7 @@ class account_move(osv.osv): _constraints = [ (_check_centralisation, - 'You can not create more than one move per period on centralized journal', + 'You cannot create more than one move per period on a centralized journal.', ['journal_id']), ] @@ -1314,7 +1314,7 @@ class account_move(osv.osv): valid_moves = self.validate(cr, uid, ids, context) if not valid_moves: - raise osv.except_osv(_('Integrity Error !'), _('You can not validate a non-balanced entry !\nMake sure you have configured payment terms properly !\nThe latest payment term line should be of the type "Balance" !')) + raise osv.except_osv(_('Error!'), _('You cannot validate a non-balanced entry.\nMake sure you have configured payment terms properly.\nThe latest payment term line should be of the "Balance" type.')) obj_sequence = self.pool.get('ir.sequence') for move in self.browse(cr, uid, valid_moves, context=context): if move.name =='/': @@ -1328,7 +1328,7 @@ class account_move(osv.osv): c = {'fiscalyear_id': move.period_id.fiscalyear_id.id} new_name = obj_sequence.next_by_id(cr, uid, journal.sequence_id.id, c) else: - raise osv.except_osv(_('Error'), _('No sequence defined on the journal !')) + raise osv.except_osv(_('Error!'), _('Please define a sequence on the journal.')) if new_name: self.write(cr, uid, [move.id], {'name':new_name}) @@ -1351,14 +1351,14 @@ class account_move(osv.osv): if not top_common: top_common = top_account elif top_account.id != top_common.id: - raise osv.except_osv(_('Error !'), - _('You cannot validate this journal entry because account "%s" does not belong to chart of accounts "%s"!') % (account.name, top_common.name)) + raise osv.except_osv(_('Error!'), + _('You cannot validate this journal entry because account "%s" does not belong to chart of accounts "%s".') % (account.name, top_common.name)) return self.post(cursor, user, ids, context=context) def button_cancel(self, cr, uid, ids, context=None): for line in self.browse(cr, uid, ids, context=context): if not line.journal_id.update_posted: - raise osv.except_osv(_('Error !'), _('You can not modify a posted entry of this journal !\nYou should set the journal to allow cancelling entries if you want to do that.')) + raise osv.except_osv(_('Error!'), _('You cannot modify a posted entry of this journal.\nFirst you should set the journal to allow cancelling entries.')) if ids: cr.execute('UPDATE account_move '\ 'SET state=%s '\ @@ -1445,8 +1445,8 @@ class account_move(osv.osv): obj_move_line = self.pool.get('account.move.line') for move in self.browse(cr, uid, ids, context=context): if move['state'] != 'draft': - raise osv.except_osv(_('UserError'), - _('You can not delete a posted journal entry "%s"!') % \ + raise osv.except_osv(_('User Error!'), + _('You cannot delete a posted journal entry "%s".') % \ move['name']) line_ids = map(lambda x: x.id, move.line_id) context['journal_id'] = move.journal_id.id @@ -1474,16 +1474,16 @@ class account_move(osv.osv): account_id = move.journal_id.default_debit_account_id.id mode2 = 'debit' if not account_id: - raise osv.except_osv(_('UserError'), - _('There is no default default debit account defined \n' \ - 'on journal "%s"') % move.journal_id.name) + raise osv.except_osv(_('User Error!'), + _('There is no default debit account defined \n' \ + 'on journal "%s".') % move.journal_id.name) else: account_id = move.journal_id.default_credit_account_id.id mode2 = 'credit' if not account_id: - raise osv.except_osv(_('UserError'), - _('There is no default default credit account defined \n' \ - 'on journal "%s"') % move.journal_id.name) + raise osv.except_osv(_('User Error!'), + _('There is no default credit account defined \n' \ + 'on journal "%s".') % move.journal_id.name) # find the first line of this move with the current mode # or create it if it doesn't exist @@ -1577,11 +1577,11 @@ class account_move(osv.osv): if not company_id: company_id = line.account_id.company_id.id if not company_id == line.account_id.company_id.id: - raise osv.except_osv(_('Error'), _("Couldn't create move between different companies")) + raise osv.except_osv(_('Error!'), _("Cannot create moves for different companies.")) if line.account_id.currency_id and line.currency_id: if line.account_id.currency_id.id != line.currency_id.id and (line.account_id.currency_id.id != line.account_id.company_id.currency_id.id): - raise osv.except_osv(_('Error'), _("""Couldn't create move with currency different from the secondary currency of the account "%s - %s". Clear the secondary currency field of the account definition if you want to accept all currencies.""") % (line.account_id.code, line.account_id.name)) + raise osv.except_osv(_('Error!'), _("""Cannot create move with currency different from ..""") % (line.account_id.code, line.account_id.name)) if abs(amount) < 10 ** -4: # If the move is balanced @@ -1833,7 +1833,7 @@ class account_tax_code(osv.osv): _check_recursion = check_cycle _constraints = [ - (_check_recursion, 'Error ! You can not create recursive accounts.', ['parent_id']) + (_check_recursion, 'Error!\nYou cannot create recursive accounts.', ['parent_id']) ] _order = 'code' @@ -2118,7 +2118,7 @@ class account_tax(osv.osv): } def compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None): - _logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included") + _logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included.") return self._compute(cr, uid, taxes, price_unit, quantity, product, partner) def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, precision=None): @@ -2307,7 +2307,7 @@ class account_model(osv.osv): date_maturity = context.get('date',time.strftime('%Y-%m-%d')) if line.date_maturity == 'partner': if not line.partner_id: - raise osv.except_osv(_('Error !'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \ + raise osv.except_osv(_('Error!'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \ "\nPlease define partner on it!")%(line.name, model.name)) if line.partner_id.property_payment_term: payment_term_id = line.partner_id.property_payment_term.id @@ -2521,8 +2521,8 @@ class account_account_template(osv.osv): _check_recursion = check_cycle _constraints = [ - (_check_recursion, 'Error ! You can not create recursive account templates.', ['parent_id']), - (_check_type, 'Configuration Error!\nYou can not define children to an account with internal type different of "View"! ', ['type']), + (_check_recursion, 'Error!\nYou cannot create recursive account templates.', ['parent_id']), + (_check_type, 'Configuration Error!\nYou cannot define children to an account that has internal type other than "View".', ['type']), ] @@ -2623,7 +2623,7 @@ class account_add_tmpl_wizard(osv.osv_memory): ptids = tmpl_obj.read(cr, uid, [tids[0]['parent_id'][0]], ['code']) res = None if not ptids or not ptids[0]['code']: - raise osv.except_osv(_('Error !'), _('I can not locate a parent code for the template account!')) + raise osv.except_osv(_('Error!'), _('There is no parent code for the template account.')) res = acc_obj.search(cr, uid, [('code','=',ptids[0]['code'])]) return res and res[0] or False @@ -2729,7 +2729,7 @@ class account_tax_code_template(osv.osv): _check_recursion = check_cycle _constraints = [ - (_check_recursion, 'Error ! You can not create recursive Tax Codes.', ['parent_id']) + (_check_recursion, 'Error!\nYou cannot create recursive Tax Codes.', ['parent_id']) ] _order = 'code,name' account_tax_code_template() @@ -2742,7 +2742,7 @@ class account_chart_template(osv.osv): _columns={ 'name': fields.char('Name', size=64, required=True), 'parent_id': fields.many2one('account.chart.template', 'Parent Chart Template'), - 'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"), + 'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"), 'visible': fields.boolean('Can be Visible?', help="Set this to False if you don't want this template to be used actively in the wizard that generate Chart of Accounts from templates, this is useful when you want to generate accounts of this template only when loading its child template."), 'complete_tax_set': fields.boolean('Complete Set of Taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sale and purchase rates or choose from list of taxes. This last choice assumes that the set of tax defined on this template is complete'), 'account_root_id': fields.many2one('account.account.template', 'Root Account', domain=[('parent_id','=',False)]), @@ -3026,7 +3026,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): return res def default_get(self, cr, uid, fields, context=None): - res = super(wizard_multi_charts_accounts, self).default_get(cr, uid, fields, context=context) + res = super(wizard_multi_charts_accounts, self).default_get(cr, uid, fields, context=context) tax_templ_obj = self.pool.get('account.tax.template') if 'bank_accounts_id' in fields: @@ -3102,7 +3102,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): # Get the analytic journal data = False if journal_type in ('sale', 'sale_refund'): - data = obj_data.get_object_reference(cr, uid, 'account', 'analytic_journal_sale') + data = obj_data.get_object_reference(cr, uid, 'account', 'analytic_journal_sale') elif journal_type in ('purchase', 'purchase_refund'): pass elif journal_type == 'general': @@ -3128,7 +3128,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): if journal_type in ('general', 'situation'): data = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_view') elif journal_type in ('sale_refund', 'purchase_refund'): - data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_refund_journal_view') + data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_refund_journal_view') else: data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_journal_view') return data and data[1] or False @@ -3357,7 +3357,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): def _prepare_bank_journal(self, cr, uid, line, current_num, default_account_id, company_id, context=None): ''' - This function prepares the value to use for the creation of a bank journal created through the wizard of + This function prepares the value to use for the creation of a bank journal created through the wizard of generating COA from templates. :param line: dictionary containing the values encoded by the user related to his bank account @@ -3375,9 +3375,9 @@ class wizard_multi_charts_accounts(osv.osv_memory): tmp = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_bank_view') view_id_cash = tmp and tmp[1] or False - # we need to loop again to find next number for journal code + # we need to loop again to find next number for journal code # because we can't rely on the value current_num as, - # its possible that we already have bank journals created (e.g. by the creation of res.partner.bank) + # its possible that we already have bank journals created (e.g. by the creation of res.partner.bank) # and the next number for account code might have been already used before for journal for num in xrange(current_num, 100): # journal_code has a maximal size of 5, hence we can enforce the boundary num < 100 @@ -3386,7 +3386,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): if not ids: break else: - raise osv.except_osv(_('Error'), _('Cannot generate an unused journal code.')) + raise osv.except_osv(_('Error!'), _('Cannot generate an unused journal code.')) vals = { 'name': line['acc_name'], @@ -3464,7 +3464,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): journal_data.append(vals) ref_acc_bank = obj_wizard.chart_template_id.bank_account_view_id if journal_data and not ref_acc_bank.code: - raise osv.except_osv(_('Configuration Error !'), _('The bank account defined on the selected chart of accounts hasn\'t a code.')) + raise osv.except_osv(_('Configuration Error!'), _('You have to set a code for the bank account defined on the selected chart of accounts.')) current_num = 1 for line in journal_data: diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 06de5a3e43e..2117f6e49ea 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -87,18 +87,18 @@ class account_analytic_line(osv.osv): if not a: a = prod.categ_id.property_account_expense_categ.id if not a: - raise osv.except_osv(_('Error !'), + raise osv.except_osv(_('Error!'), _('There is no expense account defined ' \ - 'for this product: "%s" (id:%d)') % \ + 'for this product: "%s" (id:%d).') % \ (prod.name, prod.id,)) else: a = prod.product_tmpl_id.property_account_income.id if not a: a = prod.categ_id.property_account_income_categ.id if not a: - raise osv.except_osv(_('Error !'), + raise osv.except_osv(_('Error!'), _('There is no income account defined ' \ - 'for this product: "%s" (id:%d)') % \ + 'for this product: "%s" (id:%d).') % \ (prod.name, prod_id,)) flag = False diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 11bcf565260..8df291a98d1 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -192,11 +192,11 @@ class account_bank_statement(osv.osv): 'ref': st_line.ref, } - def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, + def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, context=None): """Compute the args to build the dict of values to create the bank move line from a - statement line by calling the _prepare_move_line_vals. This method may be - overridden to implement custom move generation (making sure to call super() to + statement line by calling the _prepare_move_line_vals. This method may be + overridden to implement custom move generation (making sure to call super() to establish a clean extension chain). :param browse_record st_line: account.bank.statement.line record to @@ -219,12 +219,12 @@ class account_bank_statement(osv.osv): res_currency_obj = self.pool.get('res.currency') amt_cur = -res_currency_obj.compute(cr, uid, company_currency_id, cur_id, amount, context=context) - res = self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit, + res = self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit, amount_currency=amt_cur, currency_id=cur_id, analytic_id=anl_id, context=context) return res def _get_counter_part_account(sefl, cr, uid, st_line, context=None): - """Retrieve the account to use in the counterpart move. + """Retrieve the account to use in the counterpart move. This method may be overridden to implement custom move generation (making sure to call super() to establish a clean extension chain). @@ -237,7 +237,7 @@ class account_bank_statement(osv.osv): return st_line.statement_id.journal_id.default_debit_account_id.id def _get_counter_part_partner(sefl, cr, uid, st_line, context=None): - """Retrieve the partner to use in the counterpart move. + """Retrieve the partner to use in the counterpart move. This method may be overridden to implement custom move generation (making sure to call super() to establish a clean extension chain). @@ -247,11 +247,11 @@ class account_bank_statement(osv.osv): """ return st_line.partner_id and st_line.partner_id.id or False - def _prepare_counterpart_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, + def _prepare_counterpart_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, context=None): """Compute the args to build the dict of values to create the counter part move line from a - statement line by calling the _prepare_move_line_vals. This method may be - overridden to implement custom move generation (making sure to call super() to + statement line by calling the _prepare_move_line_vals. This method may be + overridden to implement custom move generation (making sure to call super() to establish a clean extension chain). :param browse_record st_line: account.bank.statement.line record to @@ -271,12 +271,12 @@ class account_bank_statement(osv.osv): if st_line.statement_id.currency.id <> company_currency_id: amt_cur = st_line.amount cur_id = st_line.statement_id.currency.id - return self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit, + return self._prepare_move_line_vals(cr, uid, st_line, move_id, debit, credit, amount_currency = amt_cur, currency_id = cur_id, account_id = account_id, partner_id = partner_id, context=context) def _prepare_move_line_vals(self, cr, uid, st_line, move_id, debit, credit, currency_id = False, - amount_currency= False, account_id = False, analytic_id = False, + amount_currency= False, account_id = False, analytic_id = False, partner_id = False, context=None): """Prepare the dict of values to create the move line from a statement line. All non-mandatory args will replace the default computed one. @@ -350,12 +350,12 @@ class account_bank_statement(osv.osv): amount = res_currency_obj.compute(cr, uid, st.currency.id, company_currency_id, st_line.amount, context=context) - bank_move_vals = self._prepare_bank_move_line(cr, uid, st_line, move_id, amount, + bank_move_vals = self._prepare_bank_move_line(cr, uid, st_line, move_id, amount, company_currency_id, context=context) move_line_id = account_move_line_obj.create(cr, uid, bank_move_vals, context=context) torec.append(move_line_id) - counterpart_move_vals = self._prepare_counterpart_move_line(cr, uid, st_line, move_id, + counterpart_move_vals = self._prepare_counterpart_move_line(cr, uid, st_line, move_id, amount, company_currency_id, context=context) account_move_line_obj.create(cr, uid, counterpart_move_vals, context=context) @@ -364,7 +364,7 @@ class account_bank_statement(osv.osv): context=context).line_id], context=context): if line.state <> 'valid': - raise osv.except_osv(_('Error !'), + raise osv.except_osv(_('Error!'), _('Journal item "%s" is not valid.') % line.name) # Bank statements will not consider boolean on journal entry_posted @@ -377,7 +377,7 @@ class account_bank_statement(osv.osv): def balance_check(self, cr, uid, st_id, journal_type='bank', context=None): st = self.browse(cr, uid, st_id, context=context) if not ((abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001) or (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001)): - raise osv.except_osv(_('Error !'), + raise osv.except_osv(_('Error!'), _('The statement balance is incorrect !\nThe expected balance (%.2f) is different than the computed one. (%.2f)') % (st.balance_end_real, st.balance_end)) return True @@ -401,7 +401,7 @@ class account_bank_statement(osv.osv): self.balance_check(cr, uid, st.id, journal_type=j_type, context=context) if (not st.journal_id.default_credit_account_id) \ or (not st.journal_id.default_debit_account_id): - raise osv.except_osv(_('Configuration Error !'), + raise osv.except_osv(_('Configuration Error!'), _('Please verify that an account is defined in the journal.')) if not st.name == '/': @@ -415,7 +415,7 @@ class account_bank_statement(osv.osv): for line in st.move_line_ids: if line.state <> 'valid': - raise osv.except_osv(_('Error !'), + raise osv.except_osv(_('Error!'), _('The account entries lines are not in valid state.')) for st_line in st.line_ids: if st_line.analytic_account_id: @@ -445,7 +445,7 @@ class account_bank_statement(osv.osv): account_move_obj.unlink(cr, uid, ids, context) done.append(st.id) return self.write(cr, uid, done, {'state':'draft'}, context=context) - + def _compute_balance_end_real(self, cr, uid, journal_id, context=None): cr.execute('SELECT balance_end_real \ FROM account_bank_statement \ @@ -469,7 +469,7 @@ class account_bank_statement(osv.osv): if t['state'] in ('draft'): unlink_ids.append(t['id']) else: - raise osv.except_osv(_('Invalid action !'), _('In order to delete a bank statement, you must first cancel it to delete related journal items.')) + raise osv.except_osv(_('Invalid Action!'), _('In order to delete a bank statement, you must first cancel it to delete related journal items.')) osv.osv.unlink(self, cr, uid, unlink_ids, context=context) return True diff --git a/addons/account/account_bank_view.xml b/addons/account/account_bank_view.xml index 4b3436c8a51..8ceb8a91885 100644 --- a/addons/account/account_bank_view.xml +++ b/addons/account/account_bank_view.xml @@ -9,7 +9,6 @@ Partner Bank Accounts - Journal res.partner.bank - form @@ -26,7 +25,6 @@ Partner Bank Accounts - Add currency on tree res.partner.bank - tree diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index ae225cc60de..9af0dcf60f4 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -169,7 +169,7 @@ class account_cash_statement(osv.osv): return result _columns = { - 'total_entry_encoding': fields.function(_get_sum_entry_encoding, string="Total Cash Transactions", + 'total_entry_encoding': fields.function(_get_sum_entry_encoding, string="Total Transactions", store = { 'account.bank.statement': (lambda self, cr, uid, ids, context=None: ids, ['line_ids','move_line_ids'], 10), 'account.bank.statement.line': (_get_statement_from_line, ['amount'], 10), @@ -238,7 +238,7 @@ class account_cash_statement(osv.osv): for statement in statement_pool.browse(cr, uid, ids, context=context): vals = {} if not self._user_allow(cr, uid, statement.id, context=context): - raise osv.except_osv(_('Error !'), (_('You do not have rights to open this %s journal !') % (statement.journal_id.name, ))) + raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal !') % (statement.journal_id.name, ))) if statement.name and statement.name == '/': c = {'fiscalyear_id': statement.period_id.fiscalyear_id.id} @@ -282,8 +282,8 @@ class account_cash_statement(osv.osv): for item_label, item_account in TALBES: if getattr(obj.journal_id, item_account): - raise osv.except_osv(_('Error !'), - _('There is no %s Account on the Journal %s') % (item_label, obj.journal_id.name,)) + raise osv.except_osv(_('Error!'), + _('There is no %s Account on the journal %s.') % (item_label, obj.journal_id.name,)) is_profit = obj.difference < 0.0 diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml index d2661674bae..c92d4eda602 100644 --- a/addons/account/account_installer.xml +++ b/addons/account/account_installer.xml @@ -3,7 +3,6 @@ account.installer.form account.installer - form
diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index b1c5db23df6..012bde42eff 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -319,7 +319,7 @@ class account_invoice(osv.osv): res['fields'][field]['selection'] = journal_select doc = etree.XML(res['arch']) - + if context.get('type', False): for node in doc.xpath("//field[@name='partner_bank_id']"): if context['type'] == 'in_refund': @@ -327,7 +327,7 @@ class account_invoice(osv.osv): elif context['type'] == 'out_refund': node.set('domain', "[('partner_id', '=', partner_id)]") res['arch'] = etree.tostring(doc) - + if view_type == 'search': if context.get('type', 'in_invoice') in ('out_invoice', 'out_refund'): for node in doc.xpath("//group[@name='extended filter']"): @@ -364,15 +364,15 @@ class account_invoice(osv.osv): except Exception, e: if '"journal_id" viol' in e.args[0]: raise orm.except_orm(_('Configuration Error!'), - _('There is no Accounting Journal of type Sale/Purchase defined!')) + _('There is no Sale/Purchase Journal(s) defined.')) else: - raise orm.except_orm(_('Unknown Error'), str(e)) + raise orm.except_orm(_('Unknown Error!'), str(e)) def invoice_print(self, cr, uid, ids, context=None): ''' This function prints the invoice and mark it as sent, so that we can see more easily the next step of the workflow ''' - assert len(ids) == 1, 'This option should only be used for a single id at a time' + assert len(ids) == 1, 'This option should only be used for a single id at a time.' self.write(cr, uid, ids, {'sent': True}, context=context) datas = { 'ids': ids, @@ -425,7 +425,7 @@ class account_invoice(osv.osv): if t['state'] in ('draft', 'cancel') and t['internal_number']== False: unlink_ids.append(t['id']) else: - raise osv.except_osv(_('Invalid action !'), _('You can not delete an invoice which is open or paid. We suggest you to refund it instead.')) + raise osv.except_osv(_('Invalid Action!'), _('You cannot delete an invoice which is open or paid. You should refund it instead.')) osv.osv.unlink(self, cr, uid, unlink_ids, context=context) return True @@ -458,8 +458,8 @@ class account_invoice(osv.osv): rec_res_id = rec_line_data and rec_line_data[0].get('value_reference',False) and int(rec_line_data[0]['value_reference'].split(',')[1]) or False pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False if not rec_res_id and not pay_res_id: - raise osv.except_osv(_('Configuration Error !'), - _('Can not find a chart of accounts for this company, you should create one.')) + raise osv.except_osv(_('Configuration Error!'), + _('Cannot find a chart of accounts for this company, you should create one.')) account_obj = self.pool.get('account.account') rec_obj_acc = account_obj.browse(cr, uid, [rec_res_id]) pay_obj_acc = account_obj.browse(cr, uid, [pay_res_id]) @@ -521,7 +521,7 @@ class account_invoice(osv.osv): pterm_list.sort() res = {'value':{'date_due': pterm_list[-1]}} else: - raise osv.except_osv(_('Data Insufficient !'), _('The payment term of supplier does not have a payment term line!')) + raise osv.except_osv(_('Insufficient Data!'), _('The payment term of supplier does not have a payment term line.')) return res def onchange_invoice_line(self, cr, uid, ids, lines): @@ -553,8 +553,8 @@ class account_invoice(osv.osv): rec_res_id = rec_line_data and rec_line_data[0].get('value_reference',False) and int(rec_line_data[0]['value_reference'].split(',')[1]) or False pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False if not rec_res_id and not pay_res_id: - raise osv.except_osv(_('Configuration Error !'), - _('Can not find a chart of account, you should create one from the configuration of the accounting menu.')) + raise osv.except_osv(_('Configuration Error!'), + _('Cannot find a chart of account, you should create one from Settings\Configuration\Accounting menu.')) if type in ('out_invoice', 'out_refund'): acc_id = rec_res_id else: @@ -568,16 +568,16 @@ class account_invoice(osv.osv): if line.account_id.company_id.id != company_id: result_id = account_obj.search(cr, uid, [('name','=',line.account_id.name),('company_id','=',company_id)]) if not result_id: - raise osv.except_osv(_('Configuration Error !'), - _('Can not find a chart of account, you should create one from the configuration of the accounting menu.')) + raise osv.except_osv(_('Configuration Error!'), + _('Cannot find a chart of account, you should create one from Settings\Configuration\Accounting menu.')) inv_line_obj.write(cr, uid, [line.id], {'account_id': result_id[-1]}) else: if invoice_line: for inv_line in invoice_line: obj_l = account_obj.browse(cr, uid, inv_line[2]['account_id']) if obj_l.company_id.id != company_id: - raise osv.except_osv(_('Configuration Error !'), - _('Invoice line account company does not match with invoice company.')) + raise osv.except_osv(_('Configuration Error!'), + _('Invoice line account\'s company and invoice\'s compnay does not match.')) else: continue if company_id and type: @@ -598,7 +598,7 @@ class account_invoice(osv.osv): if r[1] == 'journal_id' and r[2] in journal_ids: val['journal_id'] = r[2] if not val.get('journal_id', False): - raise osv.except_osv(_('Configuration Error !'), (_('Can\'t find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Financial Accounting\Accounts\Journals.') % (journal_type))) + raise osv.except_osv(_('Configuration Error!'), (_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % (journal_type))) dom = {'journal_id': [('id', 'in', journal_ids)]} else: journal_ids = obj_journal.search(cr, uid, []) @@ -759,13 +759,13 @@ class account_invoice(osv.osv): key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id, tax.account_analytic_id.id) tax_key.append(key) if not key in compute_taxes: - raise osv.except_osv(_('Warning !'), _('Global taxes defined, but they are not in invoice lines !')) + raise osv.except_osv(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !')) base = compute_taxes[key]['base'] if abs(base - tax.base) > inv.company_id.currency_id.rounding: - raise osv.except_osv(_('Warning !'), _('Tax base different!\nClick on compute to update the tax base.')) + raise osv.except_osv(_('Warning!'), _('Tax base different!\nClick on compute to update the tax base.')) for key in compute_taxes: if not key in tax_key: - raise osv.except_osv(_('Warning !'), _('Taxes are missing!\nClick on compute button.')) + raise osv.except_osv(_('Warning!'), _('Taxes are missing!\nClick on compute button.')) def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines): total = 0 @@ -835,12 +835,12 @@ class account_invoice(osv.osv): context = {} for inv in self.browse(cr, uid, ids, context=context): if not inv.journal_id.sequence_id: - raise osv.except_osv(_('Error !'), _('Please define sequence on the journal related to this invoice.')) + raise osv.except_osv(_('Error!'), _('Please define sequence on the journal related to this invoice.')) if not inv.invoice_line: raise osv.except_osv(_('No Invoice Lines !'), _('Please create some invoice lines.')) if inv.move_id: continue - + ctx = context.copy() ctx.update({'lang': inv.partner_id.lang}) if not inv.date_invoice: @@ -866,7 +866,7 @@ class account_invoice(osv.osv): total_percent += line.value_amount total_fixed = (total_fixed * 100) / (inv.amount_total or 1.0) if (total_fixed + total_percent) > 100: - raise osv.except_osv(_('Error !'), _("Can not create the invoice !\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount. The latest line of your payment term must be of type 'balance' to avoid rounding issues.")) + raise osv.except_osv(_('Error!'), _("Cannot create the invoice.\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount. In order to avoid rounding issues, the latest line of your payment term must be of type 'balance'.")) # one move line per tax line iml += ait_obj.move_line_get(cr, uid, inv.id) @@ -947,8 +947,8 @@ class account_invoice(osv.osv): journal_id = inv.journal_id.id journal = journal_obj.browse(cr, uid, journal_id, context=ctx) if journal.centralisation: - raise osv.except_osv(_('UserError'), - _('You cannot create an invoice on a centralised journal. Uncheck the centralised counterpart box in the related journal from the configuration menu.')) + raise osv.except_osv(_('User Error!'), + _('You cannot create an invoice on a centralized journal. Uncheck the centralized counterpart box in the related journal from the configuration menu.')) line = self.finalize_invoice_move_lines(cr, uid, inv, line) @@ -979,7 +979,7 @@ class account_invoice(osv.osv): move_obj.post(cr, uid, [move_id], context=ctx) self._log_event(cr, uid, ids) return True - + def invoice_validate(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state':'open'}, context=context) return True @@ -1061,7 +1061,7 @@ class account_invoice(osv.osv): pay_ids = account_move_line_obj.browse(cr, uid, i['payment_ids']) for move_line in pay_ids: if move_line.reconcile_partial_id and move_line.reconcile_partial_id.line_partial_ids: - raise osv.except_osv(_('Error !'), _('You can not cancel an invoice which is partially paid! You need to unreconcile related payment entries first!')) + raise osv.except_osv(_('Error!'), _('You cannot cancel an invoice which is partially paid. You need to unreconcile related payment entries first.')) # First, set the invoices as cancelled and detach the move ids self.write(cr, uid, ids, {'state':'cancel', 'move_id':False}) @@ -1187,7 +1187,7 @@ class account_invoice(osv.osv): if context is None: context = {} #TODO check if we can use different period for payment and the writeoff line - assert len(ids)==1, "Can only pay one invoice at a time" + assert len(ids)==1, "Can only pay one invoice at a time." invoice = self.browse(cr, uid, ids[0], context=context) src_account_id = invoice.account_id.id # Take the seq as name for move @@ -1273,7 +1273,7 @@ class account_invoice(osv.osv): else: code = invoice.currency_id.symbol # TODO: use currency's formatting function - msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining)") % \ + msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining).") % \ (name, pay_amount, code, invoice.amount_total, code, total, code) self.message_append_note(cr, uid, [inv_id], body=msg, context=context) self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context) @@ -1281,11 +1281,11 @@ class account_invoice(osv.osv): # Update the stored value (fields.function), so we write to trigger recompute self.pool.get('account.invoice').write(cr, uid, ids, {}, context=context) return True - + # ----------------------------------------- # OpenChatter notifications and need_action # ----------------------------------------- - + def _get_document_type(self, type): type_dict = { 'out_invoice': 'Customer invoice', @@ -1294,19 +1294,19 @@ class account_invoice(osv.osv): 'in_refund': 'Supplier Refund', } return type_dict.get(type, 'Invoice') - + def create_send_note(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): self.message_append_note(cr, uid, [obj.id],body=_("%s created.") % (self._get_document_type(obj.type)), context=context) - + def confirm_paid_send_note(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): self.message_append_note(cr, uid, [obj.id], body=_("%s paid.") % (self._get_document_type(obj.type)), context=context) - + def invoice_cancel_send_note(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): self.message_append_note(cr, uid, [obj.id], body=_("%s cancelled.") % (self._get_document_type(obj.type)), context=context) - + account_invoice() class account_invoice_line(osv.osv): @@ -1351,11 +1351,11 @@ class account_invoice_line(osv.osv): 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null'), 'product_id': fields.many2one('product.product', 'Product', ondelete='set null'), 'account_id': fields.many2one('account.account', 'Account', required=True, domain=[('type','<>','view'), ('type', '<>', 'closed')], help="The income or expense account related to the selected product."), - 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Account')), + 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Subtotal', type="float", digits_compute= dp.get_precision('Account'), store=True), - 'quantity': fields.float('Quantity', required=True), - 'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Account')), + 'quantity': fields.float('Quantity', digits_compute= dp.get_precision('Product Unit of Measure'), required=True), + 'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount')), 'invoice_line_tax_id': fields.many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id','=',False)]), 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'), 'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True), @@ -1475,7 +1475,7 @@ class account_invoice_line(osv.osv): if prod.uom_id.category_id.id != prod_uom.category_id.id: warning = { 'title': _('Warning!'), - 'message': _('You selected an Unit of Measure which is not compatible with the product.') + 'message': _('The selected unit of measure is not compatible with the unit of measure of the product.') } return {'value': res['value'], 'warning': warning} return res diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 501a50b96c2..143c5514141 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -6,7 +6,6 @@ account.invoice.calendar account.invoice - calendar @@ -18,7 +17,6 @@ account.invoice.graph account.invoice - graph @@ -30,7 +28,6 @@ account.invoice.line.tree account.invoice.line - tree @@ -47,7 +44,6 @@ account.invoice.line.form account.invoice.line - form @@ -78,7 +74,6 @@ account.invoice.tax.tree account.invoice.tax - tree @@ -94,7 +89,6 @@ account.invoice.tax.form account.invoice.tax - form @@ -120,7 +114,6 @@ account.invoice.tree account.invoice - tree @@ -146,10 +139,9 @@ account.invoice.supplier.form account.invoice - form 2 - +

-

@@ -347,7 +343,7 @@ - +
+
@@ -439,7 +436,6 @@ account.invoice.select account.invoice - search diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 5eb56bfa645..18ab1a779a3 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -95,7 +95,7 @@ class account_move_line(osv.osv): if initial_bal and not context.get('periods', False) and not where_move_lines_by_date: #we didn't pass any filter in the context, and the initial balance can't be computed using only the fiscalyear otherwise entries will be summed twice #so we have to invalidate this query - raise osv.except_osv(_('Warning !'),_("You haven't supplied enough argument to compute the initial balance, please select a period and journal in the context.")) + raise osv.except_osv(_('Warning!'),_("You have not supplied enough arguments to compute the initial balance, please select a period and a journal in the context.")) if context.get('journal_ids', False): @@ -577,14 +577,14 @@ class account_move_line(osv.osv): lines = self.browse(cr, uid, ids, context=context) for l in lines: if l.account_id.type == 'view': - raise osv.except_osv(_('Error :'), _('You can not create journal items on a "view" account %s %s') % (l.account_id.code, l.account_id.name)) + raise osv.except_osv(_('Error!'), _('You cannot create journal items on “View” type account %s %s.') % (l.account_id.code, l.account_id.name)) return True def _check_no_closed(self, cr, uid, ids, context=None): lines = self.browse(cr, uid, ids, context=context) for l in lines: if l.account_id.type == 'closed': - raise osv.except_osv(_('Error :'), _('You can not create journal items on a closed account %s %s') % (l.account_id.code, l.account_id.name)) + raise osv.except_osv(_('Error!'), _('You cannot create journal items on a closed account %s %s.') % (l.account_id.code, l.account_id.name)) return True def _check_company_id(self, cr, uid, ids, context=None): @@ -609,9 +609,9 @@ class account_move_line(osv.osv): return True _constraints = [ - (_check_no_view, 'You can not create journal items on an account of type view.', ['account_id']), - (_check_no_closed, 'You can not create journal items on closed account.', ['account_id']), - (_check_company_id, 'Company must be the same for its related account and period.', ['company_id']), + (_check_no_view, 'You cannot create journal items on an account of type view.', ['account_id']), + (_check_no_closed, 'You cannot create journal items on closed account.', ['account_id']), + (_check_company_id, 'Account and Period must belong to the same company.', ['company_id']), (_check_date, 'The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal.', ['date']), (_check_currency, 'The selected account of your Journal Entry forces to provide a secondary currency. You should remove the secondary currency on the account or select a multi-currency view on the journal.', ['currency_id']), ] @@ -743,7 +743,7 @@ class account_move_line(osv.osv): context = {} for line in self.browse(cr, uid, ids, context=context): if company_list and not line.company_id.id in company_list: - raise osv.except_osv(_('Warning !'), _('To reconcile the entries company should be the same for all entries')) + raise osv.except_osv(_('Warning!'), _('To reconcile the entries company should be the same for all entries.')) company_list.append(line.company_id.id) for line in self.browse(cr, uid, ids, context=context): @@ -752,7 +752,7 @@ class account_move_line(osv.osv): else: currency_id = line.company_id.currency_id if line.reconcile_id: - raise osv.except_osv(_('Warning'), _('Already Reconciled!')) + raise osv.except_osv(_('Warning!'), _('Already reconciled.')) if line.reconcile_partial_id: for line2 in line.reconcile_partial_id.line_partial_ids: if not line2.reconcile_id: @@ -796,11 +796,11 @@ class account_move_line(osv.osv): company_list = [] for line in self.browse(cr, uid, ids, context=context): if company_list and not line.company_id.id in company_list: - raise osv.except_osv(_('Warning !'), _('To reconcile the entries company should be the same for all entries')) + raise osv.except_osv(_('Warning!'), _('To reconcile the entries company should be the same for all entries.')) company_list.append(line.company_id.id) for line in unrec_lines: if line.state <> 'valid': - raise osv.except_osv(_('Error'), + raise osv.except_osv(_('Error!'), _('Entry "%s" is not valid !') % line.name) credit += line['credit'] debit += line['debit'] @@ -823,15 +823,15 @@ class account_move_line(osv.osv): r = cr.fetchall() #TODO: move this check to a constraint in the account_move_reconcile object if not unrec_lines: - raise osv.except_osv(_('Error'), _('Entry is already reconciled')) + raise osv.except_osv(_('Error!'), _('Entry is already reconciled.')) account = account_obj.browse(cr, uid, account_id, context=context) if r[0][1] != None: - raise osv.except_osv(_('Error'), _('Some entries are already reconciled !')) + raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.')) if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ (account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))): if not writeoff_acc_id: - raise osv.except_osv(_('Warning'), _('You have to provide an account for the write off/exchange difference entry !')) + raise osv.except_osv(_('Warning!'), _('You have to provide an account for the write off/exchange difference entry.')) if writeoff > 0: debit = writeoff credit = 0.0 @@ -1090,9 +1090,9 @@ class account_move_line(osv.osv): res = cr.fetchone() if res: if res[1] != 'draft': - raise osv.except_osv(_('UserError'), + raise osv.except_osv(_('User Error!'), _('The account move (%s) for centralisation ' \ - 'has been confirmed!') % res[2]) + 'has been confirmed.') % res[2]) return res def _remove_move_reconcile(self, cr, uid, move_ids=[], context=None): @@ -1139,9 +1139,9 @@ class account_move_line(osv.osv): if isinstance(ids, (int, long)): ids = [ids] if vals.get('account_tax_id', False): - raise osv.except_osv(_('Unable to change tax !'), _('You can not change the tax, you should remove and recreate lines !')) + raise osv.except_osv(_('Unable to change tax!'), _('You cannot change the tax, you should remove and recreate lines.')) if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']: - raise osv.except_osv(_('Bad account!'), _('You can not use an inactive account!')) + raise osv.except_osv(_('Bad Account!'), _('You cannot use an inactive account.')) if update_check: if ('account_id' in vals) or ('journal_id' in vals) or ('period_id' in vals) or ('move_id' in vals) or ('debit' in vals) or ('credit' in vals) or ('date' in vals): self._update_check(cr, uid, ids, context) @@ -1186,7 +1186,7 @@ class account_move_line(osv.osv): result = cr.fetchall() for (state,) in result: if state == 'done': - raise osv.except_osv(_('Error !'), _('You can not add/modify entries in a closed journal.')) + raise osv.except_osv(_('Error!'), _('You cannot add/modify entries in a closed journal.')) if not result: journal = journal_obj.browse(cr, uid, journal_id, context=context) period = period_obj.browse(cr, uid, period_id, context=context) @@ -1202,9 +1202,9 @@ class account_move_line(osv.osv): for line in self.browse(cr, uid, ids, context=context): err_msg = _('Move name (id): %s (%s)') % (line.move_id.name, str(line.move_id.id)) if line.move_id.state <> 'draft' and (not line.journal_id.entry_posted): - raise osv.except_osv(_('Error !'), _('You can not do this modification on a confirmed entry! You can just change some non legal fields or you must unconfirm the journal entry first! \n%s') % err_msg) + raise osv.except_osv(_('Error!'), _('You cannot do this modification on a confirmed entry. You can just change some non legal fields or you must unconfirm the journal entry first.\n%s.') % err_msg) if line.reconcile_id: - raise osv.except_osv(_('Error !'), _('You can not do this modification on a reconciled entry! You can just change some non legal fields or you must unreconcile first!\n%s') % err_msg) + raise osv.except_osv(_('Error!'), _('You cannot do this modification on a reconciled entry. You can just change some non legal fields or you must unreconcile first.\n%s.') % err_msg) t = (line.journal_id.id, line.period_id.id) if t not in done: self._update_journal_check(cr, uid, line.journal_id.id, line.period_id.id, context) @@ -1224,7 +1224,7 @@ class account_move_line(osv.osv): if company_id: vals['company_id'] = company_id[0] if ('account_id' in vals) and not account_obj.read(cr, uid, vals['account_id'], ['active'])['active']: - raise osv.except_osv(_('Bad account!'), _('You can not use an inactive account!')) + raise osv.except_osv(_('Bad Account!'), _('You cannot use an inactive account.')) if 'journal_id' in vals: context['journal_id'] = vals['journal_id'] if 'period_id' in vals: @@ -1237,10 +1237,10 @@ class account_move_line(osv.osv): if 'period_id' not in context or not isinstance(context.get('period_id', ''), (int, long)): period_candidate_ids = self.pool.get('account.period').name_search(cr, uid, name=context.get('period_id','')) if len(period_candidate_ids) != 1: - raise osv.except_osv(_('Encoding error'), _('No period found or more than one period found for the given date.')) + raise osv.except_osv(_('Error!'), _('No period found or more than one period found for the given date.')) context['period_id'] = period_candidate_ids[0][0] if not context.get('journal_id', False) and context.get('search_default_journal_id', False): - context['journal_id'] = context.get('search_default_journal_id') + context['journal_id'] = context.get('search_default_journal_id') self._update_journal_check(cr, uid, context['journal_id'], context['period_id'], context) move_id = vals.get('move_id', False) journal = journal_obj.browse(cr, uid, context['journal_id'], context=context) @@ -1263,7 +1263,7 @@ class account_move_line(osv.osv): move_id = move_obj.create(cr, uid, v, context) vals['move_id'] = move_id else: - raise osv.except_osv(_('No piece number !'), _('Can not create an automatic sequence for this piece!\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.')) + raise osv.except_osv(_('No piece number !'), _('Cannot create an automatic sequence for this piece.\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.')) ok = not (journal.type_control_ids or journal.account_control_ids) if ('account_id' in vals): account = account_obj.browse(cr, uid, vals['account_id'], context=context) @@ -1288,7 +1288,7 @@ class account_move_line(osv.osv): vals['amount_currency'] = cur_obj.compute(cr, uid, account.company_id.currency_id.id, account.currency_id.id, vals.get('debit', 0.0)-vals.get('credit', 0.0), context=ctx) if not ok: - raise osv.except_osv(_('Bad account !'), _('You can not use this general account in this journal, check the tab \'Entry Controls\' on the related journal !')) + raise osv.except_osv(_('Bad Account!'), _('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.')) if vals.get('analytic_account_id',False): if journal.analytic_journal_id: diff --git a/addons/account/account_report.xml b/addons/account/account_report.xml index 7b574c8960e..d258bb0b140 100644 --- a/addons/account/account_report.xml +++ b/addons/account/account_report.xml @@ -20,6 +20,7 @@ rml="account/report/account_print_invoice.rml" string="Invoices" attachment="(object.state in ('open','paid')) and ('INV'+(object.number or '').replace('/','')+'.pdf')" + attachment_use="True" usage="default" /> diff --git a/addons/account/account_unit_test.xml b/addons/account/account_unit_test.xml index ad4540b9806..7795c2700cc 100644 --- a/addons/account/account_unit_test.xml +++ b/addons/account/account_unit_test.xml @@ -5,7 +5,7 @@ - + draft out_invoice diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 24d21cff3e8..5bf45aab487 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -9,9 +9,8 @@ account.fiscalyear.form account.fiscalyear - form -
+
+ +or + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf new file mode 100755 index 00000000000..94809d3a57f Binary files /dev/null and b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.ttf differ diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff new file mode 100755 index 00000000000..1d6c4abc9d9 Binary files /dev/null and b/addons/auth_oauth/static/lib/zocial/css/zocial-regular-webfont.woff differ diff --git a/addons/auth_oauth/static/lib/zocial/css/zocial.css b/addons/auth_oauth/static/lib/zocial/css/zocial.css new file mode 100644 index 00000000000..89fc7450631 --- /dev/null +++ b/addons/auth_oauth/static/lib/zocial/css/zocial.css @@ -0,0 +1,420 @@ +@charset "UTF-8"; + +/*! +Code written by Sam Collins (@smcllns) of www.eventasaur.us +You are free to use this work commercially +You are free to extend this work without permissions from the author (just do so tastefully eh?) +Enjoy +*/ + +/* Reference icons from font-files */ + +@font-face { + font-family: 'zocial'; + font-style: normal; + font-weight: normal; + src: url('zocial-regular-webfont.eot'); + src: url('zocial-regular-webfont.eot?#iefix') format('embedded-opentype'), + url('zocial-regular-webfont.woff') format('woff'), + url('zocial-regular-webfont.ttf') format('truetype'), + url('zocial-regular-webfont.svg#ZocialRegular') format('svg'); + unicode-range: U+0-U+10FFFF; +} + +/* Button structure */ + +.zocial, +a.zocial { + border: 1px solid #777; + border-color: rgba(0,0,0,0.2); + border-bottom-color: #333; + border-bottom-color: rgba(0,0,0,0.4); + color: #fff; + -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.4), inset 0 0 0.1em rgba(255,255,255,0.9); + cursor: pointer; + display: inline-block; + font: bold 100%/2.1 "Lucida Grande", Tahoma, sans-serif; + padding: 0 .95em 0 0; + text-align: center; + text-decoration: none; + text-shadow: 0 1px 0 rgba(0,0,0,0.5); + white-space: nowrap; + + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + + position: relative; + + -moz-border-radius: .3em; + -webkit-border-radius: .3em; + border-radius: .3em; +} + +.zocial:before { + content: ""; + border-right: 0.075em solid rgba(0,0,0,0.1); + float: left; + font: 120%/1.65 zocial; + font-style: normal; + font-weight: normal; + margin: 0 0.5em 0 0; + padding: 0 0.5em; + text-align: center; + text-decoration: none; + text-transform: none; + + -moz-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + -webkit-box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + box-shadow: 0.075em 0 0 rgba(255,255,255,0.25); + + -webkit-font-smoothing: antialiased; +} + +.zocial:active { + outline: none; /* outline is visible on :focus */ +} + +/* Buttons can be displayed as standalone icons by adding a class of "icon" */ + +.zocial.icon { + overflow: hidden; + max-width: 2.4em; + padding-left: 0; + padding-right: 0; + max-height: 2.15em; + white-space: nowrap; +} +.zocial.icon:before { + padding: 0; + width: 2em; + height: 2em; + + box-shadow: none; + border: none; +} + +/* Gradients */ + +.zocial { + background-image: -moz-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -ms-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -o-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(49%, rgba(255,255,255,.05)), color-stop(51%, rgba(0,0,0,.05)), to(rgba(0,0,0,.1))); + background-image: -webkit-linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); + background-image: linear-gradient(rgba(255,255,255,.1), rgba(255,255,255,.05) 49%, rgba(0,0,0,.05) 51%, rgba(0,0,0,.1)); +} + +.zocial:hover, .zocial:focus { + background-image: -moz-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -ms-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -o-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.15)), color-stop(49%, rgba(255,255,255,.15)), color-stop(51%, rgba(0,0,0,.1)), to(rgba(0,0,0,.15))); + background-image: -webkit-linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); + background-image: linear-gradient(rgba(255,255,255,.15) 49%, rgba(0,0,0,.1) 51%, rgba(0,0,0,.15)); +} + +.zocial:active { + background-image: -moz-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -ms-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -o-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,.1)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, transparent), to(rgba(0,0,0,.1))); + background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); + background-image: linear-gradient(bottom, rgba(255,255,255,.1), rgba(255,255,255,0) 30%, transparent 50%, rgba(0,0,0,.1)); +} + +/* Adjustments for light background buttons */ + +.zocial.bitcoin, +.zocial.cloudapp, +.zocial.dropbox, +.zocial.email, +.zocial.eventful, +.zocial.github, +.zocial.gmail, +.zocial.instapaper, +.zocial.itunes, +.zocial.ninetyninedesigns, +.zocial.openid, +.zocial.plancast, +.zocial.posterous, +.zocial.reddit, +.zocial.secondary, +.zocial.viadeo, +.zocial.weibo, +.zocial.wikipedia { + border: 1px solid #aaa; + border-color: rgba(0,0,0,0.3); + border-bottom-color: #777; + border-bottom-color: rgba(0,0,0,0.5); + -moz-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + -webkit-box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + box-shadow: inset 0 0.08em 0 rgba(255,255,255,0.7), inset 0 0 0.08em rgba(255,255,255,0.5); + text-shadow: 0 1px 0 rgba(255,255,255,0.8); +} + +/* :hover adjustments for light background buttons */ + +.zocial.bitcoin:focus, +.zocial.bitcoin:hover, +.zocial.dropbox:focus, +.zocial.dropbox:hover, +.zocial.email:focus, +.zocial.email:hover, +.zocial.eventful:focus, +.zocial.eventful:hover, +.zocial.github:focus, +.zocial.github:hover, +.zocial.gmail:focus, +.zocial.gmail:hover, +.zocial.instapaper:focus, +.zocial.instapaper:hover, +.zocial.itunes:focus, +.zocial.itunes:hover, +.zocial.ninetyninedesigns:focus, +.zocial.ninetyninedesigns:hover, +.zocial.openid:focus, +.zocial.openid:hover, +.zocial.plancast:focus, +.zocial.plancast:hover, +.zocial.posterous:focus, +.zocial.posterous:hover, +.zocial.reddit:focus, +.zocial.reddit:hover, +.zocial.secondary:focus, +.zocial.secondary:hover, +.zocial.twitter:focus, +.zocial.viadeo:focus, +.zocial.viadeo:hover, +.zocial.weibo:focus, +.zocial.weibo:hover, +.zocial.wikipedia:focus, +.zocial.wikipedia:hover { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0.5)), color-stop(49%, rgba(255,255,255,0.2)), color-stop(51%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.15))); + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); + background-image: linear-gradient(top, rgba(255,255,255,0.5), rgba(255,255,255,0.2) 49%, rgba(0,0,0,0.05) 51%, rgba(0,0,0,0.15)); +} + +/* :active adjustments for light background buttons */ + +.zocial.bitcoin:active, +.zocial.dropbox:active, +.zocial.email:active, +.zocial.eventful:active, +.zocial.github:active, +.zocial.gmail:active, +.zocial.instapaper:active, +.zocial.itunes:active, +.zocial.ninetyninedesigns:active, +.zocial.openid:active, +.zocial.plancast:active, +.zocial.posterous:active, +.zocial.reddit:active, +.zocial.secondary:active, +.zocial.viadeo:active, +.zocial.weibo:active, +.zocial.wikipedia:active { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255,255,255,0)), color-stop(30%, rgba(255,255,255,0)), color-stop(50%, rgba(0,0,0,0)), to(rgba(0,0,0,0.1))); + background-image: -moz-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -o-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: -ms-linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); + background-image: linear-gradient(bottom, rgba(255,255,255,0), rgba(255,255,255,0) 30%, rgba(0,0,0,0) 50%, rgba(0,0,0,0.1)); +} + +/* Button icon and color */ +/* Icon characters are stored in unicode private area */ +.zocial.amazon:before {content: "\E040";} +.zocial.android:before {content: "\E005";} +.zocial.angellist:before {content: "\E06C";} +.zocial.aol:before {content: "\E001";} +.zocial.appstore:before {content: "\E020";} +.zocial.bitcoin:before {content: "\E011"; color: #f7931a;} +.zocial.blogger:before {content: "\E021";} +.zocial.call:before {content: "\E016";} +.zocial.cal:before {content: "\E00D";} +.zocial.cart:before {content: "\E06A";} +.zocial.chrome:before {content: "\E03A";} +.zocial.cloudapp:before {content: "\E042";} +.zocial.creativecommons:before {content: "\E022";} +.zocial.delicious:before {content: "\E002";} +.zocial.digg:before {content: "\E01A";} +.zocial.disqus:before {content: "\E030";} +.zocial.dribbble:before {content: "\E023";} +.zocial.dropbox:before {content: "\E043"; color: #1f75cc;} +.zocial.email:before {content: "\E03C"; color: #312c2a;} +.zocial.eventasaurus:before {content: "\E055"; color: #9de428;} +.zocial.eventbrite:before {content: "\E05B";} +.zocial.eventful:before {content: "\E006"; color: #0066CC;} +.zocial.evernote:before {content: "\E024";} +.zocial.facebook:before {content: "\E045";} +.zocial.fivehundredpx:before {content: "\E00F"; color: #29b6ff;} +.zocial.flattr:before {content: "\E004";} +.zocial.flickr:before {content: "\E025";} +.zocial.forrst:before {content: "\E019"; color: #50894f;} +.zocial.foursquare:before {content: "\E013";} +.zocial.github:before {content: "\E046";} +.zocial.gmail:before {content: "\E04C"; color: #f00;} +.zocial.google:before {content: "\E026";} +.zocial.googleplay:before {content: "\E05E";} +.zocial.googleplus:before {content: "\E00A";} +.zocial.gowalla:before {content: "\E01F";} +.zocial.grooveshark:before {content: "\E017";} +.zocial.guest:before {content: "\E01E";} +.zocial.html5:before {content: "\E014";} +.zocial.ie:before {content: "\E015";} +.zocial.instagram:before {content: "\E06D";} +.zocial.instapaper:before {content: "\E028";} +.zocial.intensedebate:before {content: "\E05A";} +.zocial.itunes:before {content: "\E048"; color: #1a6dd2;} +.zocial.klout:before {content: "\E02A"; } +.zocial.lanyrd:before {content: "\E00C";} +.zocial.lastfm:before {content: "\E04B";} +.zocial.linkedin:before {content: "\E02B";} +.zocial.macstore:before {content: "\E03D";} +.zocial.meetup:before {content: "\E02C";} +.zocial.myspace:before {content: "\E03E";} +.zocial.ninetyninedesigns:before {content: "\E018"; color: #f50;} +.zocial.openid:before {content: "\E04E"; color: #ff921d;} +.zocial.opentable:before {content: "\E05F";} +.zocial.paypal:before {content: "\E003";} +.zocial.pinboard:before {content: "\E04D";} +.zocial.pinterest:before {content: "\E010";} +.zocial.plancast:before {content: "\E02F";} +.zocial.plurk:before {content: "\E049";} +.zocial.podcast:before {content: "\E03F";} +.zocial.posterous:before {content: "\E05D";} +.zocial.print:before {content: "\E06B";} +.zocial.quora:before {content: "\E050";} +.zocial.reddit:before {content: "\E01D"; color: red;} +.zocial.rss:before {content: "\E031";} +.zocial.scribd:before {content: "\E05C"; color: #00d5ea;} +.zocial.skype:before {content: "\E032";} +.zocial.smashing:before {content: "\E009";} +.zocial.songkick:before {content: "\E04A";} +.zocial.soundcloud:before {content: "\E052";} +.zocial.spotify:before {content: "\E01C";} +.zocial.stumbleupon:before {content: "\E00E";} +.zocial.tumblr:before {content: "\E053";} +.zocial.twitter:before {content: "\E033";} +.zocial.viadeo:before {content: "\E027"; color: #f59b20;} +.zocial.vimeo:before {content: "\E035";} +.zocial.weibo:before {content: "\E029"; color: #e6162d;} +.zocial.wikipedia:before {content: "\E00B";} +.zocial.windows:before {content: "\E036";} +.zocial.xing:before {content: "\E037"} +.zocial.wordpress:before {content: "\E056";} +.zocial.yahoo:before {content: "\E038";} +.zocial.yelp:before {content: "\E058";} +.zocial.youtube:before {content: "\E034";} + +/* Button background and text color */ + +.zocial.amazon {background-color: #ffad1d; color: #030037; text-shadow: 0 1px 0 rgba(255,255,255,0.5);} +.zocial.android {background-color: #a4c639;} +.zocial.angellist {background-color: #000;} +.zocial.aol {background-color: #f00;} +.zocial.appstore {background-color: #000;} +.zocial.bitcoin {background-color: #efefef; color: #4d4d4d;} +.zocial.blogger {background-color: #ee5a22;} +.zocial.call {background-color: #008000;} +.zocial.cal {background-color: #d63538;} +.zocial.cart {background-color: #333;} +.zocial.chrome {background-color: #006cd4;} +.zocial.cloudapp {background-color: #fff; color: #312c2a;} +.zocial.creativecommons {background-color: #000;} +.zocial.delicious {background-color: #3271cb;} +.zocial.digg {background-color: #164673;} +.zocial.disqus {background-color: #5d8aad;} +.zocial.dribbble {background-color: #ea4c89;} +.zocial.dropbox {background-color: #fff; color: #312c2a;} +.zocial.email {background-color: #f0f0eb; color: #312c2a;} +.zocial.eventasaurus {background-color: #192931; color: #fff;} +.zocial.eventbrite {background-color: #ff5616;} +.zocial.eventful {background-color: #fff; color: #47ab15;} +.zocial.evernote {background-color: #6bb130; color: #fff;} +.zocial.facebook {background-color: #4863ae;} +.zocial.fivehundredpx {background-color: #333;} +.zocial.flattr {background-color: #8aba42;} +.zocial.flickr {background-color: #ff0084;} +.zocial.forrst {background-color: #1e360d;} +.zocial.foursquare {background-color: #44a8e0;} +.zocial.github {background-color: #fbfbfb; color: #050505;} +.zocial.gmail {background-color: #efefef; color: #222;} +.zocial.google {background-color: #4e6cf7;} +.zocial.googleplay {background-color: #000;} +.zocial.googleplus {background-color: #dd4b39;} +.zocial.gowalla {background-color: #ff720a;} +.zocial.grooveshark {background-color: #111; color:#eee;} +.zocial.guest {background-color: #1b4d6d;} +.zocial.html5 {background-color: #ff3617;} +.zocial.ie {background-color: #00a1d9;} +.zocial.instapaper {background-color: #eee; color: #222;} +.zocial.instagram {background-color: #3f729b;} +.zocial.intensedebate {background-color: #0099e1;} +.zocial.klout {background-color: #e34a25;} +.zocial.itunes {background-color: #efefeb; color: #312c2a;} +.zocial.lanyrd {background-color: #2e6ac2;} +.zocial.lastfm {background-color: #dc1a23;} +.zocial.linkedin {background-color: #0083a8;} +.zocial.macstore {background-color: #007dcb} +.zocial.meetup {background-color: #ff0026;} +.zocial.myspace {background-color: #000;} +.zocial.ninetyninedesigns {background-color: #fff; color: #072243;} +.zocial.openid {background-color: #f5f5f5; color: #333;} +.zocial.opentable {background-color: #990000;} +.zocial.paypal {background-color: #fff; color: #32689a; text-shadow: 0 1px 0 rgba(255,255,255,0.5);} +.zocial.pinboard {background-color: blue;} +.zocial.pinterest {background-color: #c91618;} +.zocial.plancast {background-color: #e7ebed; color: #333;} +.zocial.plurk {background-color: #cf682f;} +.zocial.podcast {background-color: #9365ce;} +.zocial.posterous {background-color: #ffd959; color: #bc7134;} +.zocial.print {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);} +.zocial.quora {background-color: #a82400;} +.zocial.reddit {background-color: #fff; color: #222;} +.zocial.rss {background-color: #ff7f25;} +.zocial.scribd {background-color: #231c1a;} +.zocial.skype {background-color: #00a2ed;} +.zocial.smashing {background-color: #ff4f27;} +.zocial.songkick {background-color: #ff0050;} +.zocial.soundcloud {background-color: #ff4500;} +.zocial.spotify {background-color: #60af00;} +.zocial.stumbleupon {background-color: #eb4924;} +.zocial.tumblr {background-color: #374a61;} +.zocial.twitter {background-color: #46c0fb;} +.zocial.viadeo {background-color: #fff; color: #000;} +.zocial.vimeo {background-color: #00a2cd;} +.zocial.weibo {background-color: #faf6f1; color: #000;} +.zocial.wikipedia {background-color: #fff; color: #000;} +.zocial.windows {background-color: #0052a4; color: #fff;} +.zocial.wordpress {background-color: #464646;} +.zocial.xing {background-color: #0A5D5E;} +.zocial.yahoo {background-color: #a200c2;} +.zocial.yelp {background-color: #e60010;} +.zocial.youtube {background-color: #f00;} + +/* +The Miscellaneous Buttons +These button have no icons and can be general purpose buttons while ensuring consistent button style +Credit to @guillermovs for suggesting +*/ + +.zocial.primary, .zocial.secondary {margin: 0.1em 0; padding: 0 1em;} +.zocial.primary:before, .zocial.secondary:before {display: none;} +.zocial.primary {background-color: #333;} +.zocial.secondary {background-color: #f0f0eb; color: #222; text-shadow: 0 1px 0 rgba(255,255,255,0.8);} + +/* Any browser-specific adjustments */ + +button:-moz-focus-inner { + border: 0; + padding: 0; +} + + diff --git a/addons/auth_oauth/static/lib/zocial/sample.html b/addons/auth_oauth/static/lib/zocial/sample.html new file mode 100644 index 00000000000..98dec554ff1 --- /dev/null +++ b/addons/auth_oauth/static/lib/zocial/sample.html @@ -0,0 +1,265 @@ + + + + + Zocial CSS3 Buttons + + + + + + + + + + + + + Sign in with Google+ + + Sign in with LinkedIn + +

The Cool Kids

+ Sync with Dropbox + Clip to Evernote + Follow me on Forrst + Sign in with Dribbble + Sign in to CloudApp + Fork me on Github + Play on Spotify + Read It Later + Follow me on Soundcloud + Follow me on Tumblr + Read on Smashing Magazine + Available on iTunes + Available on the App Store + Available on the Mac App Store + Available on Android Market + Follow me on Pinterest + Follow me on Quora + Attend on Lanyrd + +

The Not-So-Cool But Have-To-Be-Invited Kids

+ Pay with Paypal + Sign in with Amazon + Call me on Skype + Sign in with Last.fm + Write a review on Yelp + Check in with foursquare + Influence with Klout + +

The Older (but Solid) Kids

+ View on Wikipedia + Sign in with Disqus + Sign in with IntenseDebate + Sign in with Google + Sign in with Gmail + Upload to Vimeo + Read more on Scribd + Subscribe on YouTube + Sign in with WordPress + Sign in with Songkick + Sign in with Posterous + Sign in with Eventbrite + Tip with Flattr + Follow me on Plancast + + +

The Kids That Kinda Smell but Some People Don't Mind

+ Submit resume for CEO + Download Internet Explorer 5 + Report bugs with Meetup.com + Learn how-to-use OpenID + Register now for HTML6 + Chat with your parents + +

The Kids That Nobody Normally Notices

+ Sign in as guest + View Creative Commons Licence + Subscribe to RSS + Add to Chrome + +

The He's-My-Son-So-Of-Course-He's-Here Kid

+ Sign up for Eventasaurus + +

Kids By Request

+ Join me on Weibo + Sign in with Plurk + Play on Grooveshark + Post on Blogger + Sign in with Viadeo + Subscribe to this Podcast + View Portfolio on 500px + Bitcoin accepted here + View Portfolio on 99Designs + Bookmark with Pinboard + Stumble! + Find me on Myspace + Sign in with Windows Live + Find Events with Eventful + Sign in with Xing + Upload to Flickr + Sign in with Del.icio.us + Download from Google Play + Reserve with OpenTable + Digg this + Share on Reddit + Fund us on AngelList + Sign-in with Instagram + +

The Multi-Purpose Kids (Credit: Pictos Icons)

+ + Call a phone + + Add to calendar + Add to cart + Print this page + Primary action + Secondary action + + +

Icon versions of the above

+ + Sign in with Google+ + + Sign in with Google + Sign in with LinkedIn + Pay with Paypal + Sign in with Amazon + Sync with Dropbox + Clip to Evernote + Call me on Skype + Sign in as guest + Play on Spotify + Sign in with Last.fm + Sign in with Songkick + Follow me on Forrst + Sign in with Dribbble + Sign in to CloudApp + Fork me on Github + Follow me on Pinterest + Follow me on Quora + Bookmark with Pinboard + Attend on Lanyrd + Download on iTunes + Download on Android + Sign in with Disqus + Sign in with Yahoo + Upload to Vimeo + Add to Chrome + Get a new browser + Made from HTML5 + Read It Later + Read more on Scribd + View on Wikipedia + Tip with Flattr + Follow me on Tumblr + Subscribe to my Posterous + Check in with Gowalla + Check in with foursquare + Write a review on Yelp + Follow me on Soundcloud + Read on Smashing Magazine + Sign in with WordPress + Sign in with IntenseDebate + Sign in with OpenID + Sign in with Gmail + Sign in with Eventbrite + Sign in with Eventasaurus + Sign in with Meetup.com + Sign in with AIM + Follow me on Plancast + Subscribe on YouTube + Available on the Mac App Store + View Creative Commons Licence + Subscribe to RSS + Follow me on Weibo + Follow me on Plurk + Follow me on Grooveshark + Post on Blogger + Sign in with Viadeo + Subscribe to this Podcast + View Portfolio on 500px + Bitcoin accepted here + View Portfolio on 99Designs + Stumble! + Download on iTunes + Find me on Myspace + Sign in with Windows Live + Find Events with Eventful + Influence with Klout + Sign in with Xing + Upload to Flickr + Sign in with Del.icio.us + Download from Google Play + Reserve with OpenTable + Digg this + Share on Reddit + Fund us on AngelList + Sign-in with Instagram + Call a phone + + Add to calendar + Print this page + Add to cart + + + +

Thanks to @guillermovs, @kamens, @vizualover, and @leaverou for code refinements and suggestions.

+ +

Massive thanks to @drewwilson for making the multi-purpose buttons possible with his incredible Pictos icons.

+ +

See code samples at zocial.smcllns.com — ask questions to @smcllns

+ + + + + + + + diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js new file mode 100644 index 00000000000..d63631c262d --- /dev/null +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -0,0 +1,62 @@ +openerp.auth_oauth = function(instance) { + var QWeb = instance.web.qweb; + + instance.web.Login = instance.web.Login.extend({ + start: function(parent, params) { + var d = this._super.apply(this, arguments); + this.$element.on('click', 'a.zocial', this.on_oauth_sign_in); + this.oauth_providers = []; + if(this.params.oauth_error === 1) { + this.do_warn("Sign up error.","Sign up is not allowed on this database."); + } else if(this.params.oauth_error === 2) { + this.do_warn("Authentication error",""); + } + return d.then(this.do_oauth_load); + }, + do_oauth_load: function() { + var db = this.$("form [name=db]").val(); + if (db) { + this.rpc("/auth_oauth/list_providers", { dbname: db }).then(this.on_oauth_loaded); + } + }, + on_oauth_loaded: function(result) { + this.oauth_providers = result; + var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this}); + this.$(".oe_login_pane form ul").after(buttons); + }, + on_oauth_sign_in: function(ev) { + ev.preventDefault(); + var index = $(ev.target).data('index'); + var p = this.oauth_providers[index]; + var ret = location.protocol+"//"+location.host+"/"; + var dbname = self.$("form [name=db]").val(); + var state_object = { + d: dbname, + p: p.id + } + var state = JSON.stringify(state_object); + var params = { + response_type: 'token', + client_id: p.client_id, + redirect_uri: ret, + scope: p.scope, + state: state, + }; + var url = p.auth_endpoint + '?' + $.param(params); + window.location = url; + }, + }); + + instance.web.WebClient = instance.web.WebClient.extend({ + start: function() { + this._super.apply(this, arguments); + var params = $.deparam(window.location.hash.substring(1)); + // alert(JSON.stringify(params)); + if (params.hasOwnProperty('access_token')) { + var url = "/auth_oauth/signin" + '?' + $.param(params); + window.location = url; + } + }, + }); + +}; diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml new file mode 100644 index 00000000000..c2693804e59 --- /dev/null +++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml @@ -0,0 +1,9 @@ + + + + + +
+
+
+
diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py index 0ee7f98a020..eba711dae7a 100644 --- a/addons/auth_openid/controllers/main.py +++ b/addons/auth_openid/controllers/main.py @@ -21,63 +21,62 @@ import logging import os -import sys +import tempfile import urllib import werkzeug.urls import werkzeug.exceptions from openerp.modules.registry import RegistryManager +from openerp.addons.web.controllers.main import login_and_redirect, set_cookie_and_redirect try: import openerp.addons.web.common.http as openerpweb except ImportError: - import web.common.http as openerpweb + import web.common.http as openerpweb # noqa from openid import oidutil -from openid.store import memstore -#from openid.store import filestore +from openid.store import filestore from openid.consumer import consumer from openid.cryptutil import randomString from openid.extensions import ax, sreg from .. import utils - - _logger = logging.getLogger(__name__) oidutil.log = _logger.debug +_storedir = os.path.join(tempfile.gettempdir(), 'openerp-auth_openid-store') class GoogleAppsAwareConsumer(consumer.GenericConsumer): def complete(self, message, endpoint, return_to): if message.getOpenIDNamespace() == consumer.OPENID2_NS: - server_url = message.getArg(consumer.OPENID2_NS, 'op_endpoint', consumer.no_default) + server_url = message.getArg(consumer.OPENID2_NS, 'op_endpoint', '') if server_url.startswith('https://www.google.com/a/'): - # update fields - for attr in ['claimed_id', 'identity']: - value = message.getArg(consumer.OPENID2_NS, attr) - value = 'https://www.google.com/accounts/o8/user-xrds?uri=%s' % urllib.quote_plus(value) - message.setArg(consumer.OPENID2_NS, attr, value) - - # now, resign the message assoc_handle = message.getArg(consumer.OPENID_NS, 'assoc_handle') assoc = self.store.getAssociation(server_url, assoc_handle) - message.delArg(consumer.OPENID2_NS, 'sig') - message.delArg(consumer.OPENID2_NS, 'signed') - message = assoc.signMessage(message) + if assoc: + # update fields + for attr in ['claimed_id', 'identity']: + value = message.getArg(consumer.OPENID2_NS, attr, '') + value = 'https://www.google.com/accounts/o8/user-xrds?uri=%s' % urllib.quote_plus(value) + message.setArg(consumer.OPENID2_NS, attr, value) - return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to) + # now, resign the message + message.delArg(consumer.OPENID2_NS, 'sig') + message.delArg(consumer.OPENID2_NS, 'signed') + message = assoc.signMessage(message) + + return super(GoogleAppsAwareConsumer, self).complete(message, endpoint, return_to) class OpenIDController(openerpweb.Controller): _cp_path = '/auth_openid/login' - _store = memstore.MemoryStore() # TODO use a filestore + _store = filestore.FileOpenIDStore(_storedir) _REQUIRED_ATTRIBUTES = ['email'] _OPTIONAL_ATTRIBUTES = 'nickname fullname postcode country language timezone'.split() - def _add_extensions(self, request): """Add extensions to the request""" @@ -118,8 +117,20 @@ class OpenIDController(openerpweb.Controller): def _get_realm(self, req): return req.httprequest.host_url + @openerpweb.httprequest + def verify_direct(self, req, db, url): + result = self._verify(req, db, url) + if 'error' in result: + return werkzeug.exceptions.BadRequest(result['error']) + if result['action'] == 'redirect': + return werkzeug.utils.redirect(result['value']) + return result['value'] + @openerpweb.jsonrequest def verify(self, req, db, url): + return self._verify(req, db, url) + + def _verify(self, req, db, url): redirect_to = werkzeug.urls.Href(req.httprequest.host_url + 'auth_openid/login/process')(session_id=req.session_id) realm = self._get_realm(req) @@ -145,12 +156,11 @@ class OpenIDController(openerpweb.Controller): form_html = request.htmlMarkup(realm, redirect_to) return {'action': 'post', 'value': form_html, 'session_id': req.session_id} - @openerpweb.httprequest def process(self, req, **kw): session = getattr(req.session, 'openid_session', None) if not session: - return werkzeug.utils.redirect('/') + return set_cookie_and_redirect(req, '/') oidconsumer = consumer.Consumer(session, self._store, consumer_class=GoogleAppsAwareConsumer) @@ -159,12 +169,11 @@ class OpenIDController(openerpweb.Controller): display_identifier = info.getDisplayIdentifier() session['status'] = info.status - user_id = None if info.status == consumer.SUCCESS: dbname = session['dbname'] - with utils.cursor(dbname) as cr: - registry = RegistryManager.get(dbname) + registry = RegistryManager.get(dbname) + with registry.cursor() as cr: Modules = registry.get('ir.module.module') installed = Modules.search_count(cr, 1, ['&', ('name', '=', 'auth_openid'), ('state', '=', 'installed')]) == 1 @@ -185,10 +194,8 @@ class OpenIDController(openerpweb.Controller): domain += ['|', ('openid_email', '=', False)] domain += [('openid_email', '=', openid_email)] - domain += [ - ('openid_url', '=', openid_url), - ('active', '=', True), - ] + domain += [('openid_url', '=', openid_url), ('active', '=', True)] + ids = Users.search(cr, 1, domain) assert len(ids) < 2 if ids: @@ -199,12 +206,10 @@ class OpenIDController(openerpweb.Controller): # TODO fill empty fields with the ones from sreg/ax cr.commit() - u = req.session.login(dbname, login, key) + return login_and_redirect(req, dbname, login, key) - if not user_id: - session['message'] = 'This OpenID identifier is not associated to any active users' + session['message'] = 'This OpenID identifier is not associated to any active users' - elif info.status == consumer.SETUP_NEEDED: session['message'] = info.setup_url elif info.status == consumer.FAILURE and display_identifier: @@ -217,9 +222,7 @@ class OpenIDController(openerpweb.Controller): # information in a log. session['message'] = 'Verification failed.' - - fragment = '#loginerror' if not user_id else '' - return werkzeug.utils.redirect('/'+fragment) + return set_cookie_and_redirect(req, '/#action=login&loginerror=1') @openerpweb.jsonrequest def status(self, req): diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index 3fb8cefcbd4..9b02ce42991 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -18,6 +18,7 @@ # along with this program. If not, see . # ############################################################################## +from openerp.modules.registry import RegistryManager from openerp.osv import osv, fields import openerp.exceptions import tools @@ -64,23 +65,22 @@ class res_users(osv.osv): if result: return result else: - with utils.cursor(db) as cr: + with RegistryManager.get(db).cursor() as cr: cr.execute("""UPDATE res_users - SET date=now() AT TIME ZONE 'UTC' + SET login_date=now() AT TIME ZONE 'UTC' WHERE login=%s AND openid_key=%s AND active=%s RETURNING id""", (tools.ustr(login), tools.ustr(password), True)) res = cr.fetchone() cr.commit() return res[0] if res else False - def check(self, db, uid, passwd): try: return super(res_users, self).check(db, uid, passwd) except openerp.exceptions.AccessDenied: if not passwd: raise - with utils.cursor(db) as cr: + with RegistryManager.get(db).cursor() as cr: cr.execute('''SELECT COUNT(1) FROM res_users WHERE id=%s diff --git a/addons/auth_openid/res_users.xml b/addons/auth_openid/res_users.xml index df0c31856e2..be4fbdf294b 100644 --- a/addons/auth_openid/res_users.xml +++ b/addons/auth_openid/res_users.xml @@ -4,7 +4,6 @@ res.users.form res.users - form diff --git a/addons/auth_openid/static/src/js/auth_openid.js b/addons/auth_openid/static/src/js/auth_openid.js index fd6ec01cc0f..1417bc471ce 100644 --- a/addons/auth_openid/static/src/js/auth_openid.js +++ b/addons/auth_openid/static/src/js/auth_openid.js @@ -8,7 +8,7 @@ instance.web.Login = instance.web.Login.extend({ this._super.apply(this, arguments); var self = this; - this._default_error_message = this.$element.find('.login_error_message').text(); + this._default_error_message = this.$element.find('.oe_login_error_message').text(); this.$openid_selected_button = $(); this.$openid_selected_input = $(); @@ -40,8 +40,7 @@ instance.web.Login = instance.web.Login.extend({ } }); - this._check_fragment(); - + this._check_error(); }, @@ -67,11 +66,9 @@ instance.web.Login = instance.web.Login.extend({ }, - _check_fragment: function() { + _check_error: function() { var self = this; - var fragment = jQuery.deparam.fragment(); - console.log(fragment); - if (fragment.loginerror !== undefined) { + if (this.params.loginerror !== undefined) { this.rpc('/auth_openid/login/status', {}, function(result) { if (_.contains(['success', 'failure'], result.status) && result.message) { self.do_warn('Invalid OpenID Login', result.message); @@ -132,11 +129,12 @@ instance.web.Login = instance.web.Login.extend({ do_warn: function(title, msg) { //console.warn(title, msg); - this.$element.find('.login_error_message').text(msg).show(); + this.$element.find('.oe_login_error_message').text(msg).show(); + this._super(title, msg); }, reset_error_message: function() { - this.$element.find('.login_error_message').text(this._default_error_message); + this.$element.find('.oe_login_error_message').text(this._default_error_message); } }); diff --git a/addons/auth_openid/static/src/xml/auth_openid.xml b/addons/auth_openid/static/src/xml/auth_openid.xml index 34894555668..aa61d161657 100644 --- a/addons/auth_openid/static/src/xml/auth_openid.xml +++ b/addons/auth_openid/static/src/xml/auth_openid.xml @@ -3,7 +3,7 @@ - + - - - - - - - - - - - - - - - - - - +
  • Google Apps Domain
  • @@ -54,7 +37,7 @@
    - + this.each(function() { var $i = $(this), dp = $i.find('input').attr('name'); diff --git a/addons/auth_openid/utils.py b/addons/auth_openid/utils.py index 444b5eeaa05..806198f99c2 100644 --- a/addons/auth_openid/utils.py +++ b/addons/auth_openid/utils.py @@ -1,8 +1,8 @@ #!/usr/bin/env python ############################################################################## -# +# # OpenERP, Open Source Management Solution -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -15,11 +15,9 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## -from contextlib import contextmanager -from openerp.modules.registry import RegistryManager KEY_LENGTH = 16 @@ -35,14 +33,4 @@ SREG2AX = { # from http://www.axschema.org/types/#sreg 'timezone': 'http://axschema.org/pref/timezone', } - -@contextmanager -def cursor(db): - cr = RegistryManager.get(db).db.cursor() - try: - yield cr - finally: - cr.close() - - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_reset_password/__init__.py b/addons/auth_reset_password/__init__.py new file mode 100644 index 00000000000..28bbdd18161 --- /dev/null +++ b/addons/auth_reset_password/__init__.py @@ -0,0 +1 @@ +import auth_reset_password diff --git a/addons/auth_reset_password/__openerp__.py b/addons/auth_reset_password/__openerp__.py new file mode 100644 index 00000000000..76528bbfeb8 --- /dev/null +++ b/addons/auth_reset_password/__openerp__.py @@ -0,0 +1,22 @@ +{ + 'name': 'Reset Password', + 'description': 'Allow users to reset their password from the login page', + 'author': 'OpenERP SA', + 'version': '1.0', + 'category': 'Authentication', + 'website': 'http://www.openerp.com', + 'installable': True, + 'depends': ['auth_anonymous', 'email_template'], + 'data': [ + 'auth_reset_password.xml', + ], + 'js': [ + 'static/src/js/reset_password.js', + ], + 'css': [ + 'static/src/css/reset_password.css', + ], + 'qweb': [ + 'static/src/xml/reset_password.xml', + ], +} diff --git a/addons/auth_reset_password/auth_reset_password.py b/addons/auth_reset_password/auth_reset_password.py new file mode 100644 index 00000000000..3d1bcbbfa7b --- /dev/null +++ b/addons/auth_reset_password/auth_reset_password.py @@ -0,0 +1,132 @@ +import base64 +import hashlib +import simplejson +import time +import urlparse + +from openerp.tools import config +from openerp.osv import osv, fields + +TWENTY_FOUR_HOURS = 24 * 60 * 60 + +def message_sign(data, secret): + src = simplejson.dumps([data, secret], indent=None, separators=(',', ':'), sort_keys=True) + sign = hashlib.sha1(src).hexdigest() + msg = simplejson.dumps([data, sign], indent=None, separators=(',', ':'), sort_keys=True) + # pad message to avoid '=' + pad = (3 - len(msg) % 3) % 3 + msg = msg + " " * pad + msg = base64.urlsafe_b64encode(msg) + return msg, sign + +def message_check(msg, secret): + msg = base64.urlsafe_b64decode(msg) + l = simplejson.loads(msg) + msg_data = l[0] + msg_sign = l[1] + tmp, sign = message_sign(msg_data, secret) + if msg_sign == sign: + return msg_data + +class res_users(osv.osv): + _inherit = 'res.users' + + _sql_constraints = [ + ('email_uniq', 'UNIQUE (user_email)', 'You can not have two users with the same email!') + ] + + def _auth_reset_password_secret(self, cr, uid, context=None): + uuid = self.pool.get('ir.config_parameter').get_param(cr, uid, 'database.uuid') + res = { + 'dbname': cr.dbname, + 'uuid': uuid, + 'admin_passwd': config['admin_passwd'] + } + return res + + def _auth_reset_password_host(self, cr, uid, context=None): + return self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', '') + + def _auth_reset_password_link(self, cr, uid, ids, context=None): + assert len(ids) == 1 + host = self._auth_reset_password_host(cr, uid, context) + secret = self._auth_reset_password_secret(cr, uid, context) + msg_src = { + 'time': time.time(), + 'uid': ids[0], + } + msg, sign = message_sign(msg_src, secret) + link = urlparse.urljoin(host, '/login?db=%s&login=anonymous&key=anonymous#action=reset_password&token=%s' % (cr.dbname, msg)) + return link + + def _auth_reset_password_check_token(self, cr, uid, token, context=None): + secret = self._auth_reset_password_secret(cr, uid, context) + data = message_check(token, secret) + if data and (time.time() - data['time'] < TWENTY_FOUR_HOURS): + return data + return None + + def _auth_reset_password_send_email(self, cr, uid, email_to, tpl_name, res_id, context=None): + model, tpl_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'auth_reset_password', tpl_name) + assert model == 'email.template' + + msg_id = self.pool.get(model).send_mail(cr, uid, tpl_id, res_id, force_send=False, context=context) + MailMessage = self.pool.get('mail.message') + MailMessage.write(cr, uid, [msg_id], {'email_to': email_to}, context=context) + MailMessage.send(cr, uid, [msg_id], context=context) + + def send_reset_password_request(self, cr, uid, email, context=None): + ids = self.pool.get('res.users').search(cr, 1, [('user_email', '=', email)], context=context) + if ids: + self._auth_reset_password_send_email(cr, 1, email, 'reset_password_email', ids[0], context=context) + return True + #else: + # _m, company_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'main_company') + # self._auth_reset_password_send_email(cr, uid, email, 'email_no_user', company_id, context=context) + return False + +class auth_reset_password(osv.TransientModel): + _name = 'auth.reset_password' + _rec_name = 'password' + _columns = { + 'password': fields.char('Password', size=64), + 'password_confirmation': fields.char('Confirm Password', size=64), + 'token': fields.char('Token', size=128), + 'state': fields.selection([(x, x) for x in 'draft done missmatch error'.split()], required=True), + } + _defaults = { + 'state': 'draft', + } + + def create(self, cr, uid, values, context=None): + # NOTE here, invalid values raises exceptions to avoid storing + # sensitive data into the database (which then are available to anyone) + + pw = values.get('password') + if not pw or pw != values.get('password_confirmation'): + raise osv.except_osv('Error', 'Passwords missmatch') + + Users = self.pool.get('res.users') + data = Users._auth_reset_password_check_token(cr, uid, values.get('token', '')) + if data: + Users.write(cr, 1, data['uid'], {'password': pw}, context=context) + else: + raise osv.except_osv('Error', 'Invalid token') + + # Dont store password + values = {'state': 'done'} + return super(auth_reset_password, self).create(cr, uid, values, context) + + def change(self, cr, uid, ids, context=None): + return True + + def onchange_pw(self, cr, uid, ids, password, password_confirmation, context=None): + if password != password_confirmation: + return {'value': {'state': 'missmatch'}} + return {'value': {'state': 'draft'}} + + def onchange_token(self, cr, uid, ids, token, context=None): + Users = self.pool.get('res.users') + if not Users._auth_reset_password_check_token(cr, uid, token, context=context): + return {'value': {'state': 'error'}} + return {} diff --git a/addons/auth_reset_password/auth_reset_password.xml b/addons/auth_reset_password/auth_reset_password.xml new file mode 100644 index 00000000000..26ea8878c45 --- /dev/null +++ b/addons/auth_reset_password/auth_reset_password.xml @@ -0,0 +1,66 @@ + + + + + + + Reset Password + + ]]> + + Password reset + + + + + + auth.reset_password.form + auth.reset_password + form + +
    + + + + + + +
    Passwords missmatch
    +
    + + +
  • + +
    +
    +
    diff --git a/addons/portal_hr_recruitment/__init__.py b/addons/auth_signup/__init__.py similarity index 76% rename from addons/portal_hr_recruitment/__init__.py rename to addons/auth_signup/__init__.py index 26c654db9dd..2331ae629a8 100644 --- a/addons/portal_hr_recruitment/__init__.py +++ b/addons/auth_signup/__init__.py @@ -2,20 +2,23 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). +# Copyright (C) 2012-today OpenERP SA () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. +# License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU Affero General Public License for more details # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see # ############################################################################## +import controllers +import res_config +import res_users diff --git a/addons/portal_hr_recruitment/__openerp__.py b/addons/auth_signup/__openerp__.py similarity index 58% rename from addons/portal_hr_recruitment/__openerp__.py rename to addons/auth_signup/__openerp__.py index 0b7fb78b7f0..765a36ef252 100644 --- a/addons/portal_hr_recruitment/__openerp__.py +++ b/addons/auth_signup/__openerp__.py @@ -2,40 +2,39 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). +# Copyright (C) 2009-today OpenERP SA () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. +# License, or (at your option) any later version # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. +# GNU Affero General Public License for more details # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see # ############################################################################## - { - 'name': 'Portal HR recruitment', - 'version': '0.1', - 'category': 'Tools', - 'complexity': "easy", - 'description': """ -This module adds a jobs page to your portal if hr and portal are installed. - """, + 'name': 'Signup', + 'description': 'Allow users to sign up', 'author': 'OpenERP SA', - 'depends': ['hr','portal'], - 'data': [ - 'portal_jobs_view.xml', - 'security/ir.model.access.csv', - ], + 'version': '1.0', + 'category': 'Authentication', + 'website': 'http://www.openerp.com', 'installable': True, - 'auto_install':True, - 'category':'Hidden', + 'depends': ['base_setup'], + 'data': [ + 'res_config.xml', + ], + 'js': [ + 'static/src/js/auth_signup.js', + ], + 'qweb': [ + 'static/src/xml/auth_signup.xml', + ], } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/controllers/__init__.py b/addons/auth_signup/controllers/__init__.py new file mode 100644 index 00000000000..e11f9ba81bb --- /dev/null +++ b/addons/auth_signup/controllers/__init__.py @@ -0,0 +1,3 @@ +import main + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py new file mode 100644 index 00000000000..0ed2151d12b --- /dev/null +++ b/addons/auth_signup/controllers/main.py @@ -0,0 +1,34 @@ +import logging + +import werkzeug.urls + +from openerp.modules.registry import RegistryManager +from openerp.addons.web.controllers.main import login_and_redirect +import openerp.addons.web.common.http as openerpweb + +_logger = logging.getLogger(__name__) + +class OpenIDController(openerpweb.Controller): + _cp_path = '/auth_signup' + + @openerpweb.httprequest + def signup(self, req, dbname, name, login, password): + url = '/' + registry = RegistryManager.get(dbname) + with registry.cursor() as cr: + try: + Users = registry.get('res.users') + credentials = Users.auth_signup(cr, 1, name, login, password) + cr.commit() + return login_and_redirect(req, *credentials) + except AttributeError: + # auth_signup is not installed + _logger.exception('attribute error when signup') + url = "/#action=auth_signup&error=NA" # Not Available + except Exception: + # signup error + _logger.exception('error when signup') + url = "/#action=auth_signup&error=UE" # Unexcpected Error + return werkzeug.utils.redirect(url) + +# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/auth_signup/res_config.py b/addons/auth_signup/res_config.py new file mode 100644 index 00000000000..6afd1c5b581 --- /dev/null +++ b/addons/auth_signup/res_config.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2012-today OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## + +from openerp.osv import osv, fields + +class base_config_settings(osv.TransientModel): + _inherit = 'base.config.settings' + + _columns = { + 'auth_signup_uninvited': fields.boolean('allow public users to sign up', help="If unchecked only invited users may sign up"), + 'auth_signup_template_user_id': fields.many2one('res.users', 'Template user for new users created through signup'), + } + + def get_default_signup(self, cr, uid, fields, context=None): + icp = self.pool.get('ir.config_parameter') + return { + 'auth_signup_template_user_id': icp.get_param(cr, uid, 'auth.signup_template_user_id', 0) or False + } + + def set_signup(self, cr, uid, ids, context=None): + config = self.browse(cr, uid, ids[0], context=context) + icp = self.pool.get('ir.config_parameter') + icp.set_param(cr, uid, 'auth.signup_template_user_id', config.auth_signup_template_user_id.id) diff --git a/addons/auth_signup/res_config.xml b/addons/auth_signup/res_config.xml new file mode 100644 index 00000000000..49669d36618 --- /dev/null +++ b/addons/auth_signup/res_config.xml @@ -0,0 +1,24 @@ + + + + + + base.config.settings.signup + base.config.settings + + + +
    + +
    +
    +
    +
    +
    +
    + +
    +
    diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py new file mode 100644 index 00000000000..1d77a3f9473 --- /dev/null +++ b/addons/auth_signup/res_users.py @@ -0,0 +1,46 @@ +import openerp +from openerp.osv import osv + +class res_users(osv.Model): + _inherit = 'res.users' + + def auth_signup_create(self, cr, uid, new_user, context=None): + # new_user: + # login + # email + # name (optional) + # partner_id (optional) + # groups (optional) + # sign (for partner_id and groups) + # + user_template_id = self.pool.get('ir.config_parameter').get_param(cr, uid, 'auth.signup_template_user_id', 0) + if user_template_id: + self.pool.get('res.users').copy(cr, 1, user_template_id, new_user, context=context) + else: + self.pool.get('res.users').create(cr, 1, new_user, context=context) + + def auth_signup(self, cr, uid, name, login, password, context=None): + r = (cr.dbname, login, password) + res = self.search(cr, uid, [("login", "=", login)]) + if res: + # Existing user + user_id = res[0] + try: + self.check(cr.dbname, user_id, password) + # Same password + except openerp.exceptions.AccessDenied: + # Different password + raise + else: + # New user + new_user = { + 'name': name, + 'login': login, + 'user_email': login, + 'password': password, + 'active': True, + } + self.auth_signup_create(cr, uid, new_user) + return r + +# diff --git a/addons/signup/signup.py b/addons/auth_signup/signup.py similarity index 100% rename from addons/signup/signup.py rename to addons/auth_signup/signup.py diff --git a/addons/signup/signup.xml b/addons/auth_signup/signup.xml similarity index 100% rename from addons/signup/signup.xml rename to addons/auth_signup/signup.xml diff --git a/addons/auth_signup/static/src/js/auth_signup.js b/addons/auth_signup/static/src/js/auth_signup.js new file mode 100644 index 00000000000..2ab13aa7598 --- /dev/null +++ b/addons/auth_signup/static/src/js/auth_signup.js @@ -0,0 +1,60 @@ +openerp.auth_signup = function(instance) { + instance.auth_signup = instance.auth_signup || {}; + var _t = instance.web._t; + + instance.web.Login.include({ + start: function() { + var self = this; + this.$('a.oe_signup').click(function() { + var dbname = self.$("form [name=db]").val(); + self.do_action({ + type: 'ir.actions.client', + tag: 'auth_signup.signup', + params: {'dbname': dbname}, + target: 'new', + name: 'Sign up' + }); + return true; + }); + return this._super(); + }, + }); + + + instance.auth_signup.Signup = instance.web.Widget.extend({ + template: 'auth_signup.signup', + init: function(parent, params) { + this.params = params; + return this._super(); + }, + start: function() { + var self = this; + this.$('input[name=password_confirmation]').keyup(function() { + var v = $(this).val(); + var $b = self.$('button'); + if (_.isEmpty(v) || self.$('input[name=password]').val() === v) { + $b.removeAttr('disabled'); + } else { + $b.attr('disabled', 'disabled'); + } + }); + + this.$('form').submit(function(ev) { + if(ev) { + ev.preventDefault(); + } + var params = { + dbname : self.params.dbname, + name: self.$('input[name=name]').val(), + login: self.$('input[name=email]').val(), + password: self.$('input[name=password]').val(), + }; + var url = "/auth_signup/signup?" + $.param(params); + window.location = url; + }); + return this._super(); + } + }); + instance.web.client_actions.add("auth_signup.signup", "instance.auth_signup.Signup"); + +}; diff --git a/addons/auth_signup/static/src/xml/auth_signup.xml b/addons/auth_signup/static/src/xml/auth_signup.xml new file mode 100644 index 00000000000..c2eec846d15 --- /dev/null +++ b/addons/auth_signup/static/src/xml/auth_signup.xml @@ -0,0 +1,28 @@ + + + + + + +
  • + +
  • +
    +
    + + +
    +
    + Name =
    + Email =
    + Password =
    + Confirmation =
    + +
    +
    +
    + + + +
    diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index 1a3d96cbc33..b6eacda63c0 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -37,7 +37,7 @@ def get_datetime(date_field): date_split = date_field.split(' ') if len(date_split) == 1: date_field = date_split[0] + " 00:00:00" - + return datetime.strptime(date_field[:19], '%Y-%m-%d %H:%M:%S') @@ -185,7 +185,7 @@ the rule to mark CC(mail to any other person defined in actions)."), self.post_action(cr, uid, [new_id], model, context=context) return new_id return wrapper - + def _write(self, old_write, model, context=None): """ Return a wrapper around `old_write` calling both `old_write` and @@ -292,7 +292,7 @@ the rule to mark CC(mail to any other person defined in actions)."), 'object_description': hasattr(obj, 'description') and obj.description or False, 'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/', 'object_user_email': hasattr(obj, 'user_id') and (obj.user_id and \ - obj.user_id.user_email) or '/', + obj.user_id.email) or '/', 'object_user_phone': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and \ obj.partner_address_id.phone) or '/', 'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/', @@ -319,15 +319,15 @@ the rule to mark CC(mail to any other person defined in actions)."), mail_message = self.pool.get('mail.message') body = self.format_mail(obj, body) if not emailfrom: - if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.user_email: - emailfrom = obj.user_id.user_email + if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email: + emailfrom = obj.user_id.email name = '[%d] %s' % (obj.id, tools.ustr(obj.name)) emailfrom = tools.ustr(emailfrom) reply_to = emailfrom if not emailfrom: raise osv.except_osv(_('Error!'), - _("No Email ID Found for your Company address!")) + _("No email ID found for your company address.")) return mail_message.schedule_with_attach(cr, uid, emailfrom, emails, name, body, model='base.action.rule', reply_to=reply_to, res_id=obj.id) @@ -419,7 +419,7 @@ the rule to mark CC(mail to any other person defined in actions)."), emails = [] if hasattr(obj, 'user_id') and action.act_mail_to_user: if obj.user_id: - emails.append(obj.user_id.user_email) + emails.append(obj.user_id.email) if action.act_mail_to_watchers: emails += (action.act_email_cc or '').split(',') @@ -490,7 +490,7 @@ the rule to mark CC(mail to any other person defined in actions)."), return True _constraints = [ - (_check_mail, 'Error: The mail is not well formated', ['act_mail_body']), + (_check_mail, 'Error ! The mail is not well formated.', ['act_mail_body']), ] base_action_rule() diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index ba51b729305..0d268438a41 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -10,7 +10,6 @@ base.action.rule.form base.action.rule - form
    @@ -98,7 +97,6 @@ base.action.rule.tree base.action.rule - tree diff --git a/addons/base_action_rule/i18n/ar.po b/addons/base_action_rule/i18n/ar.po index af5bd10d9d7..dad10fc9d06 100644 --- a/addons/base_action_rule/i18n/ar.po +++ b/addons/base_action_rule/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/bg.po b/addons/base_action_rule/i18n/bg.po index b05fac2f8e5..00ac1646476 100644 --- a/addons/base_action_rule/i18n/bg.po +++ b/addons/base_action_rule/i18n/bg.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/bs.po b/addons/base_action_rule/i18n/bs.po index c6b4fb00ea5..1d0b81fc3ea 100644 --- a/addons/base_action_rule/i18n/bs.po +++ b/addons/base_action_rule/i18n/bs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/ca.po b/addons/base_action_rule/i18n/ca.po index cac6c06376e..f612d5a0a8f 100644 --- a/addons/base_action_rule/i18n/ca.po +++ b/addons/base_action_rule/i18n/ca.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/da.po b/addons/base_action_rule/i18n/da.po index 5a168088dfa..938b822eab3 100644 --- a/addons/base_action_rule/i18n/da.po +++ b/addons/base_action_rule/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/de.po b/addons/base_action_rule/i18n/de.po index 00783b2c2f3..f24a0dee05e 100644 --- a/addons/base_action_rule/i18n/de.po +++ b/addons/base_action_rule/i18n/de.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/el.po b/addons/base_action_rule/i18n/el.po index 2987f762260..06491b0a9fd 100644 --- a/addons/base_action_rule/i18n/el.po +++ b/addons/base_action_rule/i18n/el.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/es.po b/addons/base_action_rule/i18n/es.po index f60ac9c4b67..e4c51fa1199 100644 --- a/addons/base_action_rule/i18n/es.po +++ b/addons/base_action_rule/i18n/es.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/es_CR.po b/addons/base_action_rule/i18n/es_CR.po index d30bc9ac4a3..3e1c5732fd1 100644 --- a/addons/base_action_rule/i18n/es_CR.po +++ b/addons/base_action_rule/i18n/es_CR.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" "Language: es\n" #. module: base_action_rule diff --git a/addons/base_action_rule/i18n/es_EC.po b/addons/base_action_rule/i18n/es_EC.po index 9d5f317fb35..b17bef384aa 100644 --- a/addons/base_action_rule/i18n/es_EC.po +++ b/addons/base_action_rule/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/es_PY.po b/addons/base_action_rule/i18n/es_PY.po index 7cf4a3839c3..6380bc04f9e 100644 --- a/addons/base_action_rule/i18n/es_PY.po +++ b/addons/base_action_rule/i18n/es_PY.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/fa.po b/addons/base_action_rule/i18n/fa.po index 149d26b4b66..ef2a5f92039 100644 --- a/addons/base_action_rule/i18n/fa.po +++ b/addons/base_action_rule/i18n/fa.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/fi.po b/addons/base_action_rule/i18n/fi.po index 90a4c0173e2..2ae3bd6bd94 100644 --- a/addons/base_action_rule/i18n/fi.po +++ b/addons/base_action_rule/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/fr.po b/addons/base_action_rule/i18n/fr.po index ab26747b239..31715853a68 100644 --- a/addons/base_action_rule/i18n/fr.po +++ b/addons/base_action_rule/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/gl.po b/addons/base_action_rule/i18n/gl.po index 9e947dfdcb7..5d794b1d41e 100644 --- a/addons/base_action_rule/i18n/gl.po +++ b/addons/base_action_rule/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/gu.po b/addons/base_action_rule/i18n/gu.po index d6b072d01d9..ca6059780bf 100644 --- a/addons/base_action_rule/i18n/gu.po +++ b/addons/base_action_rule/i18n/gu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/hr.po b/addons/base_action_rule/i18n/hr.po index 41b93ae8840..cc40b2a8fe0 100644 --- a/addons/base_action_rule/i18n/hr.po +++ b/addons/base_action_rule/i18n/hr.po @@ -13,8 +13,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/hu.po b/addons/base_action_rule/i18n/hu.po index e39b1f4a344..c70333c8593 100644 --- a/addons/base_action_rule/i18n/hu.po +++ b/addons/base_action_rule/i18n/hu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/it.po b/addons/base_action_rule/i18n/it.po index 77068bb94d6..b951d476c6c 100644 --- a/addons/base_action_rule/i18n/it.po +++ b/addons/base_action_rule/i18n/it.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/ja.po b/addons/base_action_rule/i18n/ja.po index 2cd8946658d..aa831b0a595 100644 --- a/addons/base_action_rule/i18n/ja.po +++ b/addons/base_action_rule/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/lt.po b/addons/base_action_rule/i18n/lt.po index 310ff116a5d..a501963ea77 100644 --- a/addons/base_action_rule/i18n/lt.po +++ b/addons/base_action_rule/i18n/lt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/lv.po b/addons/base_action_rule/i18n/lv.po index a0a895ea52e..52940e160cf 100644 --- a/addons/base_action_rule/i18n/lv.po +++ b/addons/base_action_rule/i18n/lv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/mn.po b/addons/base_action_rule/i18n/mn.po index cf7e405aefd..168725af3b9 100644 --- a/addons/base_action_rule/i18n/mn.po +++ b/addons/base_action_rule/i18n/mn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/nl.po b/addons/base_action_rule/i18n/nl.po index 4497e52cfbe..b70d99d873f 100644 --- a/addons/base_action_rule/i18n/nl.po +++ b/addons/base_action_rule/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/pl.po b/addons/base_action_rule/i18n/pl.po index 25e477502c5..da30bd781ef 100644 --- a/addons/base_action_rule/i18n/pl.po +++ b/addons/base_action_rule/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/pt.po b/addons/base_action_rule/i18n/pt.po index aa151d7ce52..fadf1cf4a3d 100644 --- a/addons/base_action_rule/i18n/pt.po +++ b/addons/base_action_rule/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/pt_BR.po b/addons/base_action_rule/i18n/pt_BR.po index c2e28939410..b50b6fe73e7 100644 --- a/addons/base_action_rule/i18n/pt_BR.po +++ b/addons/base_action_rule/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/ro.po b/addons/base_action_rule/i18n/ro.po index 7c7b1cfe623..77f7cbe419a 100644 --- a/addons/base_action_rule/i18n/ro.po +++ b/addons/base_action_rule/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/ru.po b/addons/base_action_rule/i18n/ru.po index c26172223d3..85ec32c4367 100644 --- a/addons/base_action_rule/i18n/ru.po +++ b/addons/base_action_rule/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/sl.po b/addons/base_action_rule/i18n/sl.po index 15e158fe318..50e71449103 100644 --- a/addons/base_action_rule/i18n/sl.po +++ b/addons/base_action_rule/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/sq.po b/addons/base_action_rule/i18n/sq.po index a9de15fe6b1..d92f72b679e 100644 --- a/addons/base_action_rule/i18n/sq.po +++ b/addons/base_action_rule/i18n/sq.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/sr.po b/addons/base_action_rule/i18n/sr.po index ce91e8eef62..d8a0102b30f 100644 --- a/addons/base_action_rule/i18n/sr.po +++ b/addons/base_action_rule/i18n/sr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/sr@latin.po b/addons/base_action_rule/i18n/sr@latin.po index 9d914bc1e2b..4d471d2c230 100644 --- a/addons/base_action_rule/i18n/sr@latin.po +++ b/addons/base_action_rule/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/sv.po b/addons/base_action_rule/i18n/sv.po index 82994b49ef4..bcc7ec3c4bf 100644 --- a/addons/base_action_rule/i18n/sv.po +++ b/addons/base_action_rule/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/tr.po b/addons/base_action_rule/i18n/tr.po index d0c16b08b7c..75fa9df83b3 100644 --- a/addons/base_action_rule/i18n/tr.po +++ b/addons/base_action_rule/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/zh_CN.po b/addons/base_action_rule/i18n/zh_CN.po index e68da4375f4..1dc78ba4bad 100644 --- a/addons/base_action_rule/i18n/zh_CN.po +++ b/addons/base_action_rule/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_action_rule/i18n/zh_TW.po b/addons/base_action_rule/i18n/zh_TW.po index 3baffe9e4f2..803c62dd641 100644 --- a/addons/base_action_rule/i18n/zh_TW.po +++ b/addons/base_action_rule/i18n/zh_TW.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-08-07 05:34+0000\n" -"X-Generator: Launchpad (build 15745)\n" +"X-Launchpad-Export-Date: 2012-08-09 04:58+0000\n" +"X-Generator: Launchpad (build 15761)\n" #. module: base_action_rule #: help:base.action.rule,act_mail_to_user:0 diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index d14e0001be1..be3244f8a5b 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -48,18 +48,18 @@ def get_recurrent_dates(rrulestring, exdate, startdate=None, exrule=None): def todate(date): val = parser.parse(''.join((re.compile('\d')).findall(date))) return val - + if not startdate: startdate = datetime.now() - + if not exdate: exdate = [] - + rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True) for date in exdate: datetime_obj = todate(date) rset1._exdate.append(datetime_obj) - + if exrule: rset1.exrule(rrule.rrulestr(str(exrule), dtstart=startdate)) @@ -245,7 +245,7 @@ class calendar_attendee(osv.osv): continue else: result[id][name] = self._get_address(attdata.sent_by_uid.name, \ - attdata.sent_by_uid.user_email) + attdata.sent_by_uid.email) if name == 'cn': if attdata.user_id: @@ -289,7 +289,7 @@ class calendar_attendee(osv.osv): if name == 'language': user_obj = self.pool.get('res.users') - lang = user_obj.read(cr, uid, uid, ['context_lang'], context=context)['context_lang'] + lang = user_obj.read(cr, uid, uid, ['lang'], context=context)['lang'] result[id][name] = lang.replace('_', '-') return result @@ -413,7 +413,7 @@ property or property parameter."), cal = vobject.iCalendar() event = cal.add('vevent') if not event_obj.date_deadline or not event_obj.date: - raise osv.except_osv(_('Warning !'),_("Couldn't Invite because date is not specified!")) + raise osv.except_osv(_('Warning!'),_("First you have to specify the date of the invitation.")) event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S')) event.add('dtstart').value = ics_datetime(event_obj.date) event.add('dtend').value = ics_datetime(event_obj.date_deadline) @@ -434,7 +434,7 @@ property or property parameter."), if not organizer: organizer = event_obj.user_id event_org.params['CN'] = [organizer.name] - event_org.value = 'MAILTO:' + (organizer.user_email or organizer.name) + event_org.value = 'MAILTO:' + (organizer.email or organizer.name) if event_obj.alarm_id: # computes alarm data @@ -535,7 +535,7 @@ property or property parameter."), return {'value': {'email': ''}} usr_obj = self.pool.get('res.users') user = usr_obj.browse(cr, uid, user_id, *args) - return {'value': {'email': user.user_email, 'availability':user.availability}} + return {'value': {'email': user.email, 'availability':user.availability}} def do_tentative(self, cr, uid, ids, context=None, *args): """ Makes event invitation as Tentative @@ -891,9 +891,9 @@ From: """ % (alarm.name, alarm.trigger_date, alarm.description, \ alarm.user_id.name, alarm.user_id.signature) - mail_to = [alarm.user_id.user_email] + mail_to = [alarm.user_id.email] for att in alarm.attendee_ids: - mail_to.append(att.user_id.user_email) + mail_to.append(att.user_id.email) if mail_to: mail_message.schedule_with_attach(cr, uid, tools.config.get('email_from', False), @@ -947,7 +947,7 @@ class calendar_event(osv.osv): value['duration'] = duration # change start_date's time to 00:00:00 in the user's timezone user = self.pool.get('res.users').browse(cr, uid, uid) - tz = pytz.timezone(user.context_tz) if user.context_tz else pytz.utc + tz = pytz.timezone(user.tz) if user.tz else pytz.utc start = pytz.utc.localize(start).astimezone(tz) # convert start in user's timezone start = start.replace(hour=0, minute=0, second=0) # change start's time to 00:00:00 start = start.astimezone(pytz.utc) # convert start back to utc @@ -995,17 +995,17 @@ class calendar_event(osv.osv): @param context: A standard dictionary for contextual values @return: dictionary of rrule value. """ - + result = {} if not isinstance(ids, list): ids = [ids] - + for datas in self.read(cr, uid, ids, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'select1', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'exrule', 'day', 'week_list' ], context=context): event = datas['id'] if datas.get('interval', 0) < 0: - raise osv.except_osv(_('Warning!'), _('Interval cannot be negative')) + raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.')) if datas.get('count', 0) < 0: - raise osv.except_osv(_('Warning!'), _('Count cannot be negative')) + raise osv.except_osv(_('Warning!'), _('Count cannot be negative.')) if datas['recurrency']: result[event] = self.compute_rule_string(datas) else: @@ -1092,13 +1092,13 @@ rule or repeating pattern of time to exclude from the recurring rule."), true, it will allow you to hide the event alarm information without removing it."), 'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"), } - + def default_organizer(self, cr, uid, context=None): user_pool = self.pool.get('res.users') user = user_pool.browse(cr, uid, uid, context=context) res = user.name - if user.user_email: - res += " <%s>" %(user.user_email) + if user.email: + res += " <%s>" %(user.email) return res _defaults = { @@ -1189,23 +1189,23 @@ rule or repeating pattern of time to exclude from the recurring rule."), byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas)) if byday: return ';BYDAY=' + ','.join(byday) - return '' - + return '' + def get_month_string(freq, datas): if freq == 'monthly': if datas.get('select1')=='date' and (datas.get('day') < 1 or datas.get('day') > 31): - raise osv.except_osv(_('Error!'), ("Please select proper Day of month")) - + raise osv.except_osv(_('Error!'), ("Please select a proper day of the month.")) + if datas.get('select1')=='day': return ';BYDAY=' + datas.get('byday') + datas.get('week_list') elif datas.get('select1')=='date': return ';BYMONTHDAY=' + str(datas.get('day')) return '' - + def get_end_date(datas): if datas.get('end_date'): datas['end_date_new'] = ''.join((re.compile('\d')).findall(datas.get('end_date'))) + 'T235959Z' - + return (datas.get('end_type') == 'count' and (';COUNT=' + str(datas.get('count'))) or '') +\ ((datas.get('end_date_new') and datas.get('end_type') == 'end_date' and (';UNTIL=' + datas.get('end_date_new'))) or '') @@ -1216,32 +1216,32 @@ rule or repeating pattern of time to exclude from the recurring rule."), interval_srting = datas.get('interval') and (';INTERVAL=' + str(datas.get('interval'))) or '' return 'FREQ=' + freq.upper() + get_week_string(freq, datas) + interval_srting + get_end_date(datas) + get_month_string(freq, datas) - + def _get_empty_rrule_data(self): return { 'byday' : False, 'recurrency' : False, - 'end_date' : False, - 'rrule_type' : False, - 'select1' : False, - 'interval' : 0, - 'count' : False, - 'end_type' : False, - 'mo' : False, - 'tu' : False, - 'we' : False, - 'th' : False, - 'fr' : False, - 'sa' : False, - 'su' : False, - 'exrule' : False, - 'day' : False, + 'end_date' : False, + 'rrule_type' : False, + 'select1' : False, + 'interval' : 0, + 'count' : False, + 'end_type' : False, + 'mo' : False, + 'tu' : False, + 'we' : False, + 'th' : False, + 'fr' : False, + 'sa' : False, + 'su' : False, + 'exrule' : False, + 'day' : False, 'week_list' : False } #def _write_rrule(self, cr, uid, ids, field_value, rule_date=False, context=None): # data = self._get_empty_rrule_data() - # + # # if field_value: # data['recurrency'] = True # for event in self.browse(cr, uid, ids, context=context): @@ -1250,16 +1250,16 @@ rule or repeating pattern of time to exclude from the recurring rule."), # data.update(update_data) # #parse_rrule # self.write(cr, uid, event.id, data, context=context) - + def _parse_rrule(self, rule, data, date_start): day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] rrule_type = ['yearly', 'monthly', 'weekly', 'daily'] r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, "%Y-%m-%d %H:%M:%S")) - + if r._freq > 0 and r._freq < 4: data['rrule_type'] = rrule_type[r._freq] - + data['count'] = r._count data['interval'] = r._interval data['end_date'] = r._until and r._until.strftime("%Y-%m-%d %H:%M:%S") @@ -1270,36 +1270,36 @@ rule or repeating pattern of time to exclude from the recurring rule."), data[day_list[i]] = True data['rrule_type'] = 'weekly' #repeat monthly bynweekday ((weekday, weeknumber), ) - if r._bynweekday: + if r._bynweekday: data['week_list'] = day_list[r._bynweekday[0][0]].upper() data['byday'] = r._bynweekday[0][1] data['select1'] = 'day' - data['rrule_type'] = 'monthly' - + data['rrule_type'] = 'monthly' + if r._bymonthday: data['day'] = r._bymonthday[0] data['select1'] = 'date' data['rrule_type'] = 'monthly' - + #yearly but for openerp it's monthly, take same information as monthly but interval is 12 times if r._bymonth: data['interval'] = data['interval'] * 12 - + #FIXEME handle forever case - #end of recurrence + #end of recurrence #in case of repeat for ever that we do not support right now if not (data.get('count') or data.get('end_date')): data['count'] = 100 if data.get('count'): data['end_type'] = 'count' else: - data['end_type'] = 'end_date' - return data + data['end_type'] = 'end_date' + return data def remove_virtual_id(self, ids): if isinstance(ids, (str, int, long)): return base_calendar_id2real_id(ids) - + if isinstance(ids, (list, tuple)): res = [] for id in ids: @@ -1345,7 +1345,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), def need_to_update(self, event_id, vals): split_id = str(event_id).split("-") if len(split_id) < 2: - return False + return False else: date_start = vals.get('date', '') try: @@ -1409,9 +1409,9 @@ rule or repeating pattern of time to exclude from the recurring rule."), def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): if not context: context = {} - + if 'date' in groupby: - raise osv.except_osv(_('Warning !'), _('Group by date not supported, use the calendar view instead')) + raise osv.except_osv(_('Warning!'), _('Group by date is not supported, use the calendar view instead.')) virtual_id = context.get('virtual_id', True) context.update({'virtual_id': False}) res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) @@ -1479,7 +1479,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), def copy(self, cr, uid, id, default=None, context=None): if context is None: context = {} - + res = super(calendar_event, self).copy(cr, uid, base_calendar_id2real_id(id), default, context) alarm_obj = self.pool.get('res.alarm') alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context) diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index d48795173ed..89066ce74bb 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -6,13 +6,12 @@ calendar.attendee.form calendar.attendee - form
    - + colspan="4" required="1"/> + + on_change="onchange_dates(date,duration,False,allday)"/> - + on_change="onchange_dates(date,False,date_deadline)"/> + + widget="selection"/> @@ -222,11 +216,11 @@ - + - - + + @@ -241,31 +235,31 @@ - - - + + +
    +
    + + + +
    @@ -87,9 +111,10 @@

    OpenERP allows to automatically create leads (or others documents) - from incoming emails. You can synchronize emails with OpenERP - by connecting the mail gateway to your mail server or by manually - pressing buttons in our mail clients. + from incoming emails. You can automatically synchronize emails with OpenERP + using regular POP/IMAP accounts, using a direct email integration script for your + email server, or by manually pushing emails to OpenERP using specific + plugins for your preferred email application.