diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml index 66e17560bde..ed3649c300a 100644 --- a/addons/account/report/account_invoice_report_view.xml +++ b/addons/account/report/account_invoice_report_view.xml @@ -28,8 +28,7 @@ - - + diff --git a/addons/account_asset/account_asset_demo.xml b/addons/account_asset/account_asset_demo.xml index f81f3b7a63a..5b1a4b03be6 100644 --- a/addons/account_asset/account_asset_demo.xml +++ b/addons/account_asset/account_asset_demo.xml @@ -48,7 +48,7 @@ - 2014-08-11 + end V6 Engine and 10 inches tires @@ -63,7 +63,7 @@ open - 2012-01-01 + Office diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py index 6587fbfd9d9..9821030df0b 100644 --- a/addons/account_followup/account_followup.py +++ b/addons/account_followup/account_followup.py @@ -280,19 +280,29 @@ class res_partner(osv.osv): def do_button_print(self, cr, uid, ids, context=None): assert(len(ids) == 1) + company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id + #search if the partner has accounting entries to print. If not, it may not be present in the + #psql view the report is based on, so we need to stop the user here. + if not self.pool.get('account.move.line').search(cr, uid, [ + ('partner_id', '=', ids[0]), + ('account_id.type', '=', 'receivable'), + ('reconcile_id', '=', False), + ('state', '!=', 'draft'), + ('company_id', '=', company_id), + ], context=context): + raise osv.except_osv(_('Error!'),_("The partner does not have any accounting entries to print in the overdue report for the current company.")) self.message_post(cr, uid, [ids[0]], body=_('Printed overdue payments report'), context=context) - datas = { - 'ids': ids, - 'model': 'res.partner', - 'form': self.read(cr, uid, ids[0], context=context) + #build the id of this partner in the psql view. Could be replaced by a search with [('company_id', '=', company_id),('partner_id', '=', ids[0])] + wizard_partner_ids = [ids[0] * 10000 + company_id] + followup_ids = self.pool.get('account_followup.followup').search(cr, uid, [('company_id', '=', company_id)], context=context) + if not followup_ids: + raise osv.except_osv(_('Error!'),_("There is no followup plan defined for the current company.")) + data = { + 'date': fields.date.today(), + 'followup_id': followup_ids[0], } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.overdue', - 'datas': datas, - 'nodestroy' : True - } - + #call the print overdue report on this partner + return self.do_partner_print(cr, uid, wizard_partner_ids, data, context=context) def _get_amounts_and_date(self, cr, uid, ids, name, arg, context=None): ''' diff --git a/addons/account_followup/account_followup_view.xml b/addons/account_followup/account_followup_view.xml index 5560ca822dc..e233feb489e 100644 --- a/addons/account_followup/account_followup_view.xml +++ b/addons/account_followup/account_followup_view.xml @@ -123,24 +123,10 @@

- - Reconcile Invoices & Payments - - {'search_default_unreconciled': 1,'view_mode':True} - [('account_id.type', '=', 'receivable')] - account.move.line - - tree_account_reconciliation - -

- No journal items found. -

-
-
diff --git a/addons/account_followup/report/account_followup_print.py b/addons/account_followup/report/account_followup_print.py index 0343fe023f9..16d88d69572 100644 --- a/addons/account_followup/report/account_followup_print.py +++ b/addons/account_followup/report/account_followup_print.py @@ -79,24 +79,29 @@ class report_rappel(report_sxw.rml_parse): def _get_text(self, stat_line, followup_id, context=None): if context is None: context = {} + context.update({'lang': stat_line.partner_id.lang}) fp_obj = pooler.get_pool(self.cr.dbname).get('account_followup.followup') - fp_line = fp_obj.browse(self.cr, self.uid, followup_id).followup_line + fp_line = fp_obj.browse(self.cr, self.uid, followup_id, context=context).followup_line + if not fp_line: + raise osv.except_osv(_('Error!'),_("The followup plan defined for the current company does not have any followup action.")) + #the default text will be the first fp_line in the sequence with a description. + default_text = '' li_delay = [] for line in fp_line: + if not default_text and line.description: + default_text = line.description li_delay.append(line.delay) li_delay.sort(reverse=True) - text = "" a = {} - partner_line_ids = pooler.get_pool(self.cr.dbname).get('account.move.line').search(self.cr, self.uid, [('partner_id','=',stat_line.partner_id.id),('reconcile_id','=',False),('company_id','=',stat_line.company_id.id),('blocked','=',False)]) - partner_delay = [] - context.update({'lang': stat_line.partner_id.lang}) - for i in pooler.get_pool(self.cr.dbname).get('account.move.line').browse(self.cr, self.uid, partner_line_ids, context): - for delay in li_delay: - if i.followup_line_id and str(i.followup_line_id.delay)==str(delay): - text = i.followup_line_id.description - a[delay] = text - partner_delay.append(delay) - text = partner_delay and a[max(partner_delay)] or '' + #look into the lines of the partner that already have a followup level, and take the description of the higher level for which it is available + partner_line_ids = pooler.get_pool(self.cr.dbname).get('account.move.line').search(self.cr, self.uid, [('partner_id','=',stat_line.partner_id.id),('reconcile_id','=',False),('company_id','=',stat_line.company_id.id),('blocked','=',False),('state','!=','draft'),('debit','!=',False),('account_id.type','=','receivable'),('followup_line_id','!=',False)]) + partner_max_delay = 0 + partner_max_text = '' + for i in pooler.get_pool(self.cr.dbname).get('account.move.line').browse(self.cr, self.uid, partner_line_ids, context=context): + if i.followup_line_id.delay > partner_max_delay and i.followup_line_id.description: + partner_max_delay = i.followup_line_id.delay + partner_max_text = i.followup_line_id.description + text = partner_max_delay and partner_max_text or default_text if text: text = text % { 'partner_name': stat_line.partner_id.name, diff --git a/addons/account_followup/test/account_followup.yml b/addons/account_followup/test/account_followup.yml index 54dd3280984..ceb7ec2ea9b 100644 --- a/addons/account_followup/test/account_followup.yml +++ b/addons/account_followup/test/account_followup.yml @@ -3,7 +3,7 @@ - !record {model: account.invoice, id: account.demo_invoice_0}: check_total: 14.0 - date_invoice: 2012-06-2 + date_invoice: !eval "'%s-06-2' %(datetime.now().year)" invoice_line: - account_id : account.a_sale name: 'Test PC' diff --git a/addons/account_voucher/account_voucher_data.xml b/addons/account_voucher/account_voucher_data.xml index adfd6c8f228..440d1c5814a 100644 --- a/addons/account_voucher/account_voucher_data.xml +++ b/addons/account_voucher/account_voucher_data.xml @@ -17,7 +17,7 @@ Status Change account.voucher - Status <b>changed</b> + Status changed diff --git a/addons/analytic/analytic_data.xml b/addons/analytic/analytic_data.xml index 51c9d1471e0..26eb5ae3dd5 100644 --- a/addons/analytic/analytic_data.xml +++ b/addons/analytic/analytic_data.xml @@ -6,17 +6,17 @@ Contract to Renew account.analytic.account - Contract <b>pending</b> + Contract pending Contract Finished account.analytic.account - Contract <b>closed</b> + Contract closed Contract Opened account.analytic.account - Stage <b>opened</b> + Contract opened diff --git a/addons/auth_openid/controllers/main.py b/addons/auth_openid/controllers/main.py index be59b9ae5b5..1fcc34c82a0 100644 --- a/addons/auth_openid/controllers/main.py +++ b/addons/auth_openid/controllers/main.py @@ -46,7 +46,18 @@ oidutil.log = _logger.debug def get_system_user(): """Return system user info string, such as USERNAME-EUID""" - info = getpass.getuser() + try: + info = getpass.getuser() + except ImportError: + if os.name == 'nt': + # when there is no 'USERNAME' in environment, getpass.getuser() + # fail when trying to import 'pwd' module - which is unix only. + # In that case we have to fallback to real win32 API. + import win32api + info = win32api.GetUserName() + else: + raise + euid = getattr(os, 'geteuid', None) # Non available on some platforms if euid is not None: info = '%s-%d' % (info, euid()) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 233b3be6853..5c558ca68d7 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -252,12 +252,19 @@ class res_users(osv.Model): raise osv.except_osv(_("Cannot send email: user has no email address."), user.name) mail_id = self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, True, context=context) mail_state = mail_obj.read(cr, uid, mail_id, ['state'], context=context) - if mail_state and mail_state == 'exception': + if mail_state and mail_state['state'] == 'exception': raise osv.except_osv(_("Cannot send email: no outgoing email server configured.\nYou can configure it under Settings/General Settings."), user.name) else: - raise osv.except_osv(_("Mail sent to:"), user.email) - - return True + return { + 'type': 'ir.actions.client', + 'name': '_(Server Notification)', + 'tag': 'action_notify', + 'params': { + 'title': 'Mail Sent to: %s' % user.name, + 'text': 'You can reset the password by yourself using this link' % user.partner_id.signup_url, + 'sticky': True, + } + } def create(self, cr, uid, values, context=None): # overridden to automatically invite user to sign up diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index a06bfd485bb..ab0d8d324b4 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -142,7 +142,7 @@ html_invitation = """ You are invited for %(company)s Event. - Below are the details of event: + Below are the details of event. Hours and dates expressed in %(timezone)s time. @@ -427,12 +427,9 @@ property or property parameter."), res = None def ics_datetime(idate, short=False): if idate: - if short or len(idate)<=10: - return date.fromtimestamp(time.mktime(time.strptime(idate, '%Y-%m-%d'))) - else: - return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S') - else: - return False + #returns the datetime as UTC, because it is stored as it in the database + return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.timezone('UTC')) + return False try: # FIXME: why isn't this in CalDAV? import vobject @@ -516,9 +513,17 @@ property or property parameter."), att_infos.append(((att2.user_id and att2.user_id.name) or \ (att2.partner_id and att2.partner_id.name) or \ att2.email) + ' - Status: ' + att2.state.title()) + #dates and times are gonna be expressed in `tz` time (local timezone of the `uid`) + tz = context.get('tz', pytz.timezone('UTC')) + #res_obj.date and res_obj.date_deadline are in UTC in database so we use context_timestamp() to transform them in the `tz` timezone + date_start = fields.datetime.context_timestamp(cr, uid, datetime.strptime(res_obj.date, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context) + date_stop = False + if res_obj.date_deadline: + date_stop = fields.datetime.context_timestamp(cr, uid, datetime.strptime(res_obj.date_deadline, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context) body_vals = {'name': res_obj.name, - 'start_date': res_obj.date, - 'end_date': res_obj.date_deadline or False, + 'start_date': date_start, + 'end_date': date_stop, + 'timezone': tz, 'description': res_obj.description or '-', 'location': res_obj.location or '-', 'attendees': '
'.join(att_infos), @@ -623,7 +628,7 @@ property or property parameter."), email = filter(lambda x:x.__contains__('@'), cnval) vals['email'] = email and email[0] or '' vals['cn'] = vals.get("cn") - res = super(calendar_attendee, self).create(cr, uid, vals, context) + res = super(calendar_attendee, self).create(cr, uid, vals, context=context) return res calendar_attendee() @@ -842,7 +847,7 @@ class calendar_alarm(osv.osv): current_datetime = datetime.now() alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context) - mail_to = [] + mail_to = "" for alarm in self.browse(cr, uid, alarm_ids, context=context): next_trigger_date = None @@ -891,9 +896,9 @@ From: """ % (alarm.name, alarm.trigger_date, alarm.description, \ alarm.user_id.name, alarm.user_id.signature) - mail_to = [alarm.user_id.email] + mail_to = alarm.user_id.email for att in alarm.attendee_ids: - mail_to.append(att.user_id.email) + mail_to = mail_to + " " + att.user_id.email if mail_to: vals = { 'state': 'outgoing', @@ -1117,7 +1122,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), for att in event.attendee_ids: attendees[att.partner_id.id] = True new_attendees = [] - mail_to = [] + mail_to = "" for partner in event.partner_ids: if partner.id in attendees: continue @@ -1128,7 +1133,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), 'email': partner.email }, context=context) if partner.email: - mail_to.append(partner.email) + mail_to = mail_to + " " + partner.email self.write(cr, uid, [event.id], { 'attendee_ids': [(4, att_id)] }, context=context) @@ -1136,7 +1141,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), if mail_to and current_user.email: att_obj._send_mail(cr, uid, new_attendees, mail_to, - email_from = current_user.email) + email_from = current_user.email, context=context) return True def default_organizer(self, cr, uid, context=None): @@ -1747,57 +1752,4 @@ class virtual_report_spool(web_services.report_spool): virtual_report_spool() -class res_users(osv.osv): - _inherit = 'res.users' - - def _get_user_avail(self, cr, uid, ids, context=None): - """ - Get User Availability - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user's ID for security checks, - @param ids: List of res user's IDs. - @param context: A standard dictionary for contextual values - """ - - current_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - res = {} - attendee_obj = self.pool.get('calendar.attendee') - attendee_ids = attendee_obj.search(cr, uid, [ - ('event_date', '<=', current_datetime), ('event_end_date', '<=', current_datetime), - ('state', '=', 'accepted'), ('user_id', 'in', ids) - ]) - - for attendee_data in attendee_obj.read(cr, uid, attendee_ids, ['user_id']): - user_id = attendee_data['user_id'] - status = 'busy' - res.update({user_id:status}) - - #TOCHECK: Delegated Event - for user_id in ids: - if user_id not in res: - res[user_id] = 'free' - - return res - - def _get_user_avail_fun(self, cr, uid, ids, name, args, context=None): - """ - Get User Availability Function - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user's ID for security checks, - @param ids: List of res user's IDs. - @param context: A standard dictionary for contextual values - """ - - return self._get_user_avail(cr, uid, ids, context=context) - - _columns = { - 'availability': fields.function(_get_user_avail_fun, type='selection', \ - selection=[('free', 'Free'), ('busy', 'Busy')], \ - string='Free/Busy'), - } - -res_users() - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml index 2efc76997cc..c2adc01cd54 100644 --- a/addons/base_calendar/crm_meeting_view.xml +++ b/addons/base_calendar/crm_meeting_view.xml @@ -181,10 +181,6 @@ -
- - -
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index bbd7e3a56b9..3fae85f311d 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -84,9 +84,20 @@ class crm_lead(base_stage, format_address, osv.osv): }, } + def create(self, cr, uid, vals, context=None): + if context is None: + context = {} + if not vals.get('stage_id') and vals.get('section_id'): + ctx = context.copy() + ctx['default_section_id'] = vals['section_id'] + vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx) + elif not vals.get('stage_id') and context.get('default_section_id'): + vals['stage_id'] = self._get_default_stage_id(cr, uid, context=context) + return super(crm_lead, self).create(cr, uid, vals, context=context) + def _get_default_section_id(self, cr, uid, context=None): """ Gives default section by checking if present in the context """ - return (self._resolve_section_id_from_context(cr, uid, context=context) or False) + return self._resolve_section_id_from_context(cr, uid, context=context) or False def _get_default_stage_id(self, cr, uid, context=None): """ Gives default stage_id """ @@ -671,9 +682,9 @@ class crm_lead(base_stage, format_address, osv.osv): section_id = lead.section_id and lead.section_id.id or False if section_id: - stage_ids = crm_stage.search(cr, uid, [('sequence','>=',1), ('section_ids','=', section_id)]) + stage_ids = crm_stage.search(cr, uid, [('sequence', '>=', 1), ('section_ids', '=', section_id), ('probability', '>', 0)]) else: - stage_ids = crm_stage.search(cr, uid, [('sequence','>=',1)]) + stage_ids = crm_stage.search(cr, uid, [('sequence', '>=', 1), ('probability', '>', 0)]) stage_id = stage_ids and stage_ids[0] or False return { diff --git a/addons/crm/crm_lead_demo.xml b/addons/crm/crm_lead_demo.xml index 86a944544ff..99fb0e895c2 100644 --- a/addons/crm/crm_lead_demo.xml +++ b/addons/crm/crm_lead_demo.xml @@ -402,9 +402,9 @@ Andrew
Leland Martinez info@deltapc.com Delta PC - Fremont + London 3661 Station Street - + diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 2bab40ee457..24837cff586 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -156,7 +156,7 @@