diff --git a/addons/audittrail/security/ir.model.access.csv b/addons/audittrail/security/ir.model.access.csv index 25bba6a00b1..1d2198fd661 100644 --- a/addons/audittrail/security/ir.model.access.csv +++ b/addons/audittrail/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_audittrail_rule_all_users,audittrail rule all,model_audittrail_rule,base.group_user,1,0,0,0 +access_audittrail_rule_all_users,audittrail rule all,model_audittrail_rule,base.group_system,1,1,1,0 +access_audittrail_rule_all_access,audittrail rule all,model_audittrail_rule,base.group_erp_manager,1,1,1,0 access_audittrail_log_all_users,audittrail log all,model_audittrail_log,base.group_user,1,0,1,0 access_audittrail_log_line_all_users,audittrail log line all,model_audittrail_log_line,base.group_user,1,0,1,0 diff --git a/addons/base_contact/base_contact_view.xml b/addons/base_contact/base_contact_view.xml index 3e5edd201ac..475d85a5c1e 100644 --- a/addons/base_contact/base_contact_view.xml +++ b/addons/base_contact/base_contact_view.xml @@ -38,7 +38,7 @@ - + @@ -52,7 +52,7 @@
- + diff --git a/addons/crm/crm.py b/addons/crm/crm.py index bee1e48ada2..03cdb31832d 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -468,12 +468,10 @@ class crm_case(crm_base): self._action(cr, uid, cases, state) return True - #DEAD Code def remind_partner(self, cr, uid, ids, context=None, attach=False): return self.remind_user(cr, uid, ids, context, attach, destination=False) - #DEAD Code def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True): mail_message = self.pool.get('mail.message') for case in self.browse(cr, uid, ids, context=context): diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py index 10ad262d38e..3947eb58156 100644 --- a/addons/crm/crm_action_rule.py +++ b/addons/crm/crm_action_rule.py @@ -125,7 +125,7 @@ class base_action_rule(osv.osv): """Gets available states for crm""" res = super(base_action_rule, self).state_get(cr, uid, context=context) return res + crm.AVAILABLE_STATES - # Dead Code + def priority_get(self, cr, uid, context=None): res = super(base_action_rule, self).priority_get(cr, uid, context=context) return res + crm.AVAILABLE_PRIORITIES diff --git a/addons/edi/models/edi.py b/addons/edi/models/edi.py index b8fc8699ca2..c573115618e 100644 --- a/addons/edi/models/edi.py +++ b/addons/edi/models/edi.py @@ -601,7 +601,8 @@ class EDIMixin(object): self._name, external_id, value) # also need_new_ext_id here, but already been set above model = self.pool.get(model) - res_id, name = model.name_create(cr, uid, value, context=context) + # should use name_create() but e.g. res.partner won't allow it at the moment + res_id = model.create(cr, uid, {model._rec_name: value}, context=context) target = model.browse(cr, uid, res_id, context=context) if need_new_ext_id: ext_id_members = split_external_id(external_id) diff --git a/addons/l10n_fr/__openerp__.py b/addons/l10n_fr/__openerp__.py index d4b4f91d911..daccb5120c3 100644 --- a/addons/l10n_fr/__openerp__.py +++ b/addons/l10n_fr/__openerp__.py @@ -37,7 +37,7 @@ This is the module to manage the accounting chart for France in OpenERP. Credits: Sistheo Zeekom CrysaLEAD """, - "depends" : ['base', 'account', 'account_chart', 'base_vat', 'l10n_fr_rib'], + "depends" : ['base_iban', 'account', 'account_chart', 'base_vat', 'l10n_fr_rib'], "init_xml" : [], "update_xml" : [ "fr_report_demo.xml", diff --git a/addons/mrp/report/price.py b/addons/mrp/report/price.py index c072b821196..fc32eeeed9e 100644 --- a/addons/mrp/report/price.py +++ b/addons/mrp/report/price.py @@ -41,6 +41,7 @@ class report_custom(report_rml): rml_obj=report_sxw.rml_parse(cr, uid, product_pool._name,context) rml_obj.localcontext.update({'lang':context.get('lang',False)}) company_currency = user_pool.browse(cr, uid, uid).company_id.currency_id + company_currency_symbol = company_currency.symbol or company_currency.name def process_bom(bom, currency_id, factor=1): xml = '' sum = 0 @@ -62,7 +63,7 @@ class report_custom(report_rml): 'uom': prod.uom_po_id.id, 'date': time.strftime('%Y-%m-%d'), })[pricelist.id] - main_sp_price = """"""+rml_obj.formatLang(price)+' '+ company_currency.symbol+"""\r\n""" + main_sp_price = """"""+rml_obj.formatLang(price)+' '+ (company_currency_symbol)+"""\r\n""" sum += prod_qtty*price std_price = product_uom_pool._compute_price(cr, uid, prod.uom_id.id, prod.standard_price, to_uom_id=product_uom.id) main_strd_price = str(std_price) + '\r\n' @@ -75,11 +76,11 @@ class report_custom(report_rml): 'uom': prod.uom_po_id.id, 'date': time.strftime('%Y-%m-%d'), })[pricelist.id] - sellers_price += """"""+rml_obj.formatLang(price) +' '+ company_currency.symbol +"""\r\n""" + sellers_price += """"""+rml_obj.formatLang(price) +' '+ (company_currency_symbol) +"""\r\n""" xml += """ """+ prod_name +""" """+ main_sp_name + sellers + """ """+ rml_obj.formatLang(prod_qtty) +' '+ product_uom_name +""" - """+ rml_obj.formatLang(float(main_strd_price)) +' '+ company_currency.symbol +""" + """+ rml_obj.formatLang(float(main_strd_price)) +' '+ (company_currency_symbol) +""" """ + main_sp_price + sellers_price + """'""" xml += '' @@ -93,9 +94,9 @@ class report_custom(report_rml): xml = '' xml += "" + to_xml(workcenter.name) + '' xml += "" - xml += """"""+rml_obj.formatLang(cost_cycle)+' '+ company_currency.symbol + """""" - xml += """"""+rml_obj.formatLang(cost_hour)+' '+ company_currency.symbol + """""" - xml += """"""+rml_obj.formatLang(cost_hour + cost_cycle)+' '+ company_currency.symbol + """""" + xml += """"""+rml_obj.formatLang(cost_cycle)+' '+ (company_currency_symbol) + """""" + xml += """"""+rml_obj.formatLang(cost_hour)+' '+ (company_currency_symbol) + """""" + xml += """"""+rml_obj.formatLang(cost_hour + cost_cycle)+' '+ (company_currency_symbol) + """""" xml += '' return xml, total @@ -159,8 +160,8 @@ class report_custom(report_rml): """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: - """+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ company_currency.symbol + """ - """+ rml_obj.formatLang(total, digits=purchase_price_digits) +' '+ company_currency.symbol + """ + """+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """ + """+ rml_obj.formatLang(total, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """ '""" else: bom = bom_pool.browse(cr, uid, bom_id, context=context) @@ -186,7 +187,7 @@ class report_custom(report_rml): """ + _('Components Cost of %s %s') % (str(number), product_uom_name) + """: - """+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ company_currency.symbol + """ + """+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """ '""" @@ -204,13 +205,13 @@ class report_custom(report_rml): - """+ rml_obj.formatLang(total2, digits=purchase_price_digits) +' '+ company_currency.symbol +""" + """+ rml_obj.formatLang(total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) +""" '""" xml += """ """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: - """+ rml_obj.formatLang(total_strd+total2, digits=purchase_price_digits) +' '+ company_currency.symbol + """ + """+ rml_obj.formatLang(total_strd+total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """ '""" diff --git a/addons/plugin/plugin_handler.py b/addons/plugin/plugin_handler.py index fd5ca7da6c6..8a9f2073c2d 100644 --- a/addons/plugin/plugin_handler.py +++ b/addons/plugin/plugin_handler.py @@ -12,13 +12,14 @@ class plugin_handler(osv.osv_memory): def _make_url(self, cr, uid, res_id, model, context=None): """ - @param id: on which document the message is pushed + @param res_id: on which document the message is pushed @param model: name of the document linked with the mail @return url """ base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='http://localhost:8069', context=context) if base_url: - base_url += '/?id=%s&model=%s'%(res_id,model) + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) + base_url += '/web/webclient/login?db=%s&login=%s&key=%s#id=%s&model=%s' % (cr.dbname, user.login, user.password, res_id, model) return base_url def is_installed(self, cr, uid): diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index bff7892b74c..1eb9a0865f7 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -737,7 +737,6 @@ class product_product(osv.osv): 'expense_pdt': fields.boolean('PoS Cash Output', help="This is a product you can use to take cash from a statement for the point of sale backend, exemple: money lost, transfer to bank, etc."), 'img': fields.binary('Product Image, must be 50x50', help="Use an image size of 50x50."), 'pos_categ_id': fields.many2one('pos.category','PoS Category', - domain="[('type','=','normal')]", help="If you want to sell this product through the point of sale, select the category it belongs to.") } product_product() diff --git a/addons/point_of_sale/wizard/pos_box_out.py b/addons/point_of_sale/wizard/pos_box_out.py index 7e255d30e76..2a8037dbdc7 100644 --- a/addons/point_of_sale/wizard/pos_box_out.py +++ b/addons/point_of_sale/wizard/pos_box_out.py @@ -82,7 +82,7 @@ class pos_box_out(osv.osv_memory): stat_done = statement_obj.browse(cr, uid, done_statmt, context=context) am = 0.0 product = product_obj.browse(cr, uid, data['product_id'], context=context) - acc_id = product.property_account_income + acc_id = product.property_account_income or product.categ_id.property_account_income_categ if not acc_id: raise osv.except_osv(_('Error !'), _('please check that account is set to %s')%(product.name)) if not statement_ids: diff --git a/addons/project/project.py b/addons/project/project.py index 0046dea4409..02fdcf411e2 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -114,13 +114,6 @@ class project(osv.osv): if task.project_id: result[task.project_id.id] = True return result.keys() - #dead code - def _get_project_work(self, cr, uid, ids, context=None): - result = {} - for work in self.pool.get('project.task.work').browse(cr, uid, ids, context=context): - if work.task_id and work.task_id.project_id: result[work.task_id.project_id.id] = True - return result.keys() - def unlink(self, cr, uid, ids, *args, **kwargs): for proj in self.browse(cr, uid, ids): if proj.tasks: diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py index d5c091a8796..d402f16991a 100644 --- a/addons/project_long_term/project_long_term.py +++ b/addons/project_long_term/project_long_term.py @@ -72,13 +72,7 @@ class project_phase(osv.osv): if phase['date_start'] and phase['date_end'] and phase['date_start'] > phase['date_end']: return False return True - #dead code - def _get_default_uom_id(self, cr, uid): - model_data_obj = self.pool.get('ir.model.data') - model_data_id = model_data_obj._get_id(cr, uid, 'product', 'uom_hour') - return model_data_obj.read(cr, uid, [model_data_id], ['res_id'])[0]['res_id'] - #dead code def _compute_progress(self, cr, uid, ids, field_name, arg, context=None): res = {} if not ids: diff --git a/addons/project_scrum/project_scrum.py b/addons/project_scrum/project_scrum.py index 260eadd4a61..85eba636b90 100644 --- a/addons/project_scrum/project_scrum.py +++ b/addons/project_scrum/project_scrum.py @@ -254,6 +254,7 @@ class project_scrum_task(osv.osv): for task in line.tasks_id: result[task.id] = True return result.keys() + _columns = { 'product_backlog_id': fields.many2one('project.scrum.product.backlog', 'Product Backlog',help="Related product backlog that contains this task. Used in SCRUM methodology"), 'sprint_id': fields.related('product_backlog_id','sprint_id', type='many2one', relation='project.scrum.sprint', string='Sprint', @@ -262,12 +263,7 @@ class project_scrum_task(osv.osv): 'project.scrum.product.backlog': (_get_task, ['sprint_id'], 10) }), } - #dead code - def onchange_backlog_id(self, cr, uid, backlog_id=False): - if not backlog_id: - return {} - project_id = self.pool.get('project.scrum.product.backlog').browse(cr, uid, backlog_id).project_id.id - return {'value': {'project_id': project_id}} + project_scrum_task() class project_scrum_meeting(osv.osv): @@ -292,45 +288,6 @@ class project_scrum_meeting(osv.osv): _defaults = { 'date' : lambda *a: time.strftime('%Y-%m-%d'), } - # dead code - def button_send_to_master(self, cr, uid, ids, context=None): - meeting_id = self.browse(cr, uid, ids, context=context)[0] - if meeting_id and meeting_id.sprint_id.scrum_master_id.user_email: - res = self.email_send(cr, uid, ids, meeting_id.sprint_id.scrum_master_id.user_email) - if not res: - raise osv.except_osv(_('Error !'), _('Email notification could not be sent to the scrum master %s') % meeting_id.sprint_id.scrum_master_id.name) - else: - raise osv.except_osv(_('Error !'), _('Please provide email address for scrum master defined on sprint.')) - return True - - #dead code - def button_send_product_owner(self, cr, uid, ids, context=None): - if context is None: - context = {} - context.update({'button_send_product_owner': True}) - meeting_id = self.browse(cr, uid, ids, context=context)[0] - if meeting_id.sprint_id.product_owner_id.user_email: - res = self.email_send(cr,uid,ids,meeting_id.sprint_id.product_owner_id.user_email) - if not res: - raise osv.except_osv(_('Error !'), _('Email notification could not be sent to the product owner %s') % meeting_id.sprint_id.product_owner_id.name) - else: - raise osv.except_osv(_('Error !'), _('Please provide email address for product owner defined on sprint.')) - return True - - #dead code - def email_send(self, cr, uid, ids, email, context=None): - mail_message_obj = self.pool.get('mail.message') - meeting_id = self.browse(cr, uid, ids, context=context)[0] - user = self.pool.get('res.users').browse(cr, uid, uid, context=context) - user_email = user.user_email or tools.config.get('email_from', False) - body = _("Hello %s,\n \nI am sending you Daily Meeting Details of date %s for the Sprint %s\n") %(meeting_id.sprint_id.scrum_master_id.name, meeting_id.date, meeting_id.sprint_id.name) - body += _('\n* Tasks since yesterday:\n_______________________\n%s\n\n* Task for Today:\n_______________________ \n%s\n\n* Blocks encountered:\n_______________________ \n\n%s') %(meeting_id.question_yesterday,meeting_id.question_today, meeting_id.question_blocks or _('No Blocks')) - body += _("\n\nThank you,\n%s") % user.name - sub_name = meeting_id.name or _('Scrum Meeting of %s') % meeting_id.date - flag = mail_message_obj.schedule_with_attach(cr, uid, user_email , [email], sub_name, body, model='project.scrum.meeting', res_id=meeting_id.id, context=context) - if not flag: - return False - return True project_scrum_meeting() diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 0dc015834a0..b61f0d340d2 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -35,14 +35,6 @@ from osv.orm import browse_record, browse_null # class purchase_order(osv.osv): - def _calc_amount(self, cr, uid, ids, prop, unknow_none, unknow_dict): - res = {} - for order in self.browse(cr, uid, ids): - res[order.id] = 0 - for oline in order.order_line: - res[order.id] += oline.price_unit * oline.product_qty - return res - def _amount_all(self, cr, uid, ids, field_name, arg, context=None): res = {} cur_obj=self.pool.get('res.currency') @@ -300,25 +292,6 @@ class purchase_order(osv.osv): for id in ids: self.write(cr, uid, [id], {'state' : 'confirmed', 'validator' : uid}) return True - # Dead code: - def wkf_warn_buyer(self, cr, uid, ids): - self.write(cr, uid, ids, {'state' : 'wait', 'validator' : uid}) - request = pooler.get_pool(cr.dbname).get('res.request') - for po in self.browse(cr, uid, ids): - managers = [] - for oline in po.order_line: - manager = oline.product_id.product_manager - if manager and not (manager.id in managers): - managers.append(manager.id) - for manager_id in managers: - request.create(cr, uid,{ - 'name' : _("Purchase amount over the limit"), - 'act_from' : uid, - 'act_to' : manager_id, - 'body': _('Somebody has just confirmed a purchase with an amount over the defined limit'), - 'ref_partner_id': po.partner_id.id, - 'ref_doc1': 'purchase.order,%d' % (po.id,), - }) def _prepare_inv_line(self, cr, uid, account_id, order_line, context=None): """Collects require data from purchase order line that is used to create invoice line diff --git a/addons/purchase/report/order.py b/addons/purchase/report/order.py index c19ef9c4ba1..c253467f12a 100644 --- a/addons/purchase/report/order.py +++ b/addons/purchase/report/order.py @@ -27,60 +27,7 @@ import pooler class order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(order, self).__init__(cr, uid, name, context=context) - self.localcontext.update({ - 'time': time, - 'get_line_tax': self._get_line_tax, - 'get_tax': self._get_tax, - 'get_product_code': self._get_product_code, - }) - - #dead code - def _get_line_tax(self, line_obj): - self.cr.execute("SELECT tax_id FROM purchase_order_taxe WHERE order_line_id=%s", (line_obj.id)) - res = self.cr.fetchall() or None - if not res: - return "" - if isinstance(res, list): - tax_ids = [t[0] for t in res] - else: - tax_ids = res[0] - res = [tax.name for tax in pooler.get_pool(self.cr.dbname).get('account.tax').browse(self.cr, self.uid, tax_ids)] - return ",\n ".join(res) - - #dead code - def _get_tax(self, order_obj): - self.cr.execute("SELECT DISTINCT tax_id FROM purchase_order_taxe, purchase_order_line, purchase_order \ - WHERE (purchase_order_line.order_id=purchase_order.id) AND (purchase_order.id=%s)", (order_obj.id)) - res = self.cr.fetchall() or None - if not res: - return [] - if isinstance(res, list): - tax_ids = [t[0] for t in res] - else: - tax_ids = res[0] - tax_obj = pooler.get_pool(self.cr.dbname).get('account.tax') - res = [] - for tax in tax_obj.browse(self.cr, self.uid, tax_ids): - self.cr.execute("SELECT DISTINCT order_line_id FROM purchase_order_line, purchase_order_taxe \ - WHERE (purchase_order_taxe.tax_id=%s) AND (purchase_order_line.order_id=%s)", (tax.id, order_obj.id)) - lines = self.cr.fetchall() or None - if lines: - if isinstance(lines, list): - line_ids = [l[0] for l in lines] - else: - line_ids = lines[0] - base = 0 - for line in pooler.get_pool(self.cr.dbname).get('purchase.order.line').browse(self.cr, self.uid, line_ids): - base += line.price_subtotal - res.append({'code':tax.name, - 'base':base, - 'amount':base*tax.amount}) - return res - - #dead code - def _get_product_code(self, product_id, partner_id): - product_obj=pooler.get_pool(self.cr.dbname).get('product.product') - return product_obj._product_code(self.cr, self.uid, [product_id], name=None, arg=None, context={'partner_id': partner_id})[product_id] + self.localcontext.update({'time': time}) report_sxw.report_sxw('report.purchase.order','purchase.order','addons/purchase/report/order.rml',parser=order) diff --git a/addons/resource/__openerp__.py b/addons/resource/__openerp__.py index c8b60448c75..0c2e143c7a7 100644 --- a/addons/resource/__openerp__.py +++ b/addons/resource/__openerp__.py @@ -45,6 +45,10 @@ It also manages the leaves of every resource. ], 'demo_xml': ['resource_demo.xml' ], + 'test': [ + 'test/resource.yml', + 'test/duplicate_resource.yml', + ], 'installable': True, 'active': False, 'certificate': '00746371192190459469', diff --git a/addons/resource/resource.py b/addons/resource/resource.py index bd62c449d2b..edb900bf2fc 100644 --- a/addons/resource/resource.py +++ b/addons/resource/resource.py @@ -22,7 +22,6 @@ from datetime import datetime, timedelta import math from faces import * -from new import classobj from osv import fields, osv from tools.translate import _ @@ -44,9 +43,12 @@ class resource_calendar(osv.osv): } def working_hours_on_day(self, cr, uid, resource_calendar_id, day, context=None): - """ + """Calculates the Working Total Hours based on Resource Calendar and + given working day (datetime object). + @param resource_calendar_id: resource.calendar browse record @param day: datetime object + @return: returns the working hours (as float) men should work on the given day if is in the attendance_ids of the resource_calendar_id (i.e if that day is a working day), returns 0.0 otherwise """ res = 0.0 @@ -56,9 +58,16 @@ class resource_calendar(osv.osv): return res def _get_leaves(self, cr, uid, id, resource): + """Private Method to Calculate resource Leaves days + + @param id: resource calendar id + @param resource: resource id for which leaves will ew calculated + + @return : returns the list of dates, where resource on leave in + resource.calendar.leaves object (e.g.['%Y-%m-%d', '%Y-%m-%d']) + """ resource_cal_leaves = self.pool.get('resource.calendar.leaves') dt_leave = [] - resource_leave_ids = resource_cal_leaves.search(cr, uid, [('calendar_id','=',id), '|', ('resource_id','=',False), ('resource_id','=',resource)]) #res_leaves = resource_cal_leaves.read(cr, uid, resource_leave_ids, ['date_from', 'date_to']) res_leaves = resource_cal_leaves.browse(cr, uid, resource_leave_ids) @@ -73,6 +82,21 @@ class resource_calendar(osv.osv): return dt_leave def interval_min_get(self, cr, uid, id, dt_from, hours, resource=False): + """ + Calculates the working Schedule from supplied from date to till hours + will be satisfied based or resource calendar id. If resource is also + given then it will consider the resource leave also and than will + calculates resource working schedule + + @param dt_from: datetime object, start of working scheduled + @param hours: float, total number working hours needed scheduled from + start date + @param resource : Optional Resource id, if supplied than resource leaves + will also taken into consideration for calculating working + schedule. + @return : List datetime object of working schedule based on supplies + params + """ if not id: td = int(hours)*3 return [(dt_from - timedelta(hours=td), dt_from)] @@ -162,10 +186,32 @@ class resource_calendar(osv.osv): return results def interval_get(self, cr, uid, id, dt_from, hours, resource=False, byday=True): + """Calculates Resource Working Internal Timing Based on Resource Calendar. + + @param dt_from: start resource schedule calculation. + @param hours : total number of working hours to be scheduled. + @param resource: optional resource id, If supplied it will take care of + resource leave while scheduling. + @param byday: boolean flag bit enforce day wise scheduling + + @return : list of scheduled working timing based on resource calendar. + """ res = self.interval_get_multi(cr, uid, [(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)], resource, byday)[(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)] return res def interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource=False): + """ Calculates the Total Working hours based on given start_date to + end_date, If resource id is supplied that it will consider the source + leaves also in calculating the hours. + + @param dt_from : date start to calculate hours + @param dt_end : date end to calculate hours + @param resource: optional resource id, If given resource leave will be + considered. + + @return : Total number of working hours based dt_from and dt_end and + resource if supplied. + """ if not id: return 0.0 dt_leave = self._get_leaves(cr, uid, id, resource) @@ -290,6 +336,7 @@ class resource_resource(osv.osv): def compute_vacation(self, cr, uid, calendar_id, resource_id=False, resource_calendar=False, context=None): """ Compute the vacation from the working calendar of the resource. + @param calendar_id : working calendar of the project @param resource_id : resource working on phase/task @param resource_calendar : working calendar of the resource @@ -366,13 +413,6 @@ class resource_resource(osv.osv): wktime_cal.append((non_working[:-1], time_range)) return wktime_cal - #TODO: Write optimized alogrothem for resource availability. : Method Yet not implemented - def check_availability(self, cr, uid, ids, start, end, context=None): - if context == None: - contex = {} - allocation = {} - return allocation - resource_resource() class resource_calendar_leaves(osv.osv): diff --git a/addons/resource/resource_demo.xml b/addons/resource/resource_demo.xml index 2d1b6622e07..acd96cd992b 100644 --- a/addons/resource/resource_demo.xml +++ b/addons/resource/resource_demo.xml @@ -5,73 +5,73 @@ - 38 Hours/Week + 45 Hours/Week - + Monday morning 0 08 12 - + Monday evening 0 13 18 - + Tuesday morning 1 08 12 - + Tuesday evening 1 13 18 - + Wednesday morning 2 08 12 - + Wednesday evening 2 13 18 - + Thursday morning 3 08 12 - + Thursday evening 13 18 3 - + Friday morning 4 08 12 - + Friday evening 4 13 @@ -79,5 +79,47 @@ + + + + Analyst + + + user + + + + + + Designer + + + user + + + + + + Developer + + + user + + + + 2 Hours On Leave + + + + + + + + Dummy Resource Leave + + + + + diff --git a/addons/resource/test/duplicate_resource.yml b/addons/resource/test/duplicate_resource.yml new file mode 100644 index 00000000000..5869530e2f4 --- /dev/null +++ b/addons/resource/test/duplicate_resource.yml @@ -0,0 +1,6 @@ +- + I duplicate the resource "Analyst" +- + !python {model: resource.resource}: | + copied_id = self.copy(cr, uid, ref("resource_analyst")) + assert copied_id, "Unable to Duplicate Resource" diff --git a/addons/resource/test/resource.yml b/addons/resource/test/resource.yml new file mode 100644 index 00000000000..5b7fa108101 --- /dev/null +++ b/addons/resource/test/resource.yml @@ -0,0 +1,59 @@ +- + In order to test resource. +- + I assign working calendar '45 Hours/Week' to human resource. +- + !python {model: resource.resource}: | + self.write(cr, uid, [ref('resource_analyst'), ref('resource_designer'), ref('resource_developer')], {'calendar_id' : ref('timesheet_group1'), 'resource_type': 'user'}) + +- + I had Project of OpenERP Integration of 50 Hours with three human resource assigned on it. I have started project from this week start. +- + First, I generate the resource detail and check the resource Efficiency assigned. +- + !python {model: resource.resource}: | + resources = self.generate_resources(cr, uid, [ref('base.user_root'),ref('base.user_demo')], ref('timesheet_group1'), context) + for resource in resources.values(): + assert resource.get('efficiency', 0.0) == 1.0, 'Invalid resource generated.' +- + I check per day work hour availability of the Resource based on Working Calendar Assigned to each resource, for first day of the week. +- + !python {model: resource.resource}: | + calendar_pool = self.pool.get('resource.calendar') + resources = self.browse(cr, uid, [ref('resource_analyst'), ref('resource_designer'), ref('resource_developer')], context) + from datetime import datetime, timedelta + now = datetime.now() + dt = now - timedelta(days=now.weekday()) + for resource in resources: + result = calendar_pool.working_hours_on_day(cr, uid, resource.calendar_id, dt, context) + assert result == 9.0, 'Wrong calculation of day work hour availability of the Resource.' +- + Now, resource "Developer" drafted leave on Thursday in this week. +- + !python {model: resource.calendar.leaves}: | + from datetime import datetime,timedelta + now = datetime.now() + dt = (now - timedelta(days=now.weekday()) ) + timedelta(days=3) + self.write(cr, uid, [ref('resource_dummyleave')], {'resource_id': ref('resource_developer'), 'calendar_id': ref('timesheet_group1'), 'date_from': dt.strftime("%Y-%m-%d 09:00:00"), 'date_to': dt.strftime("%Y-%m-%d 18:00:00")}) + +- + I check Actual working hours on resource 'Developer' from this week +- + !python {model: resource.calendar}: | + from datetime import datetime, timedelta + now = datetime.now() + dt_from = now - timedelta(days=now.weekday()) + dt_to = dt_from+ timedelta(days=6) + hours = self.interval_hours_get(cr, uid, ref('timesheet_group1'), dt_from, dt_to, resource=ref('resource_developer')) + assert hours > 27 , 'Invalid Total Week working hour calculated' +- + Project Analysis work is of 20 hours which will start from Week start so i will calculate working schedule for resource Analyst for the same. +- + !python {model: resource.calendar}: | + + from datetime import datetime, timedelta + now = datetime.now() + work_intreval = self.interval_min_get(cr, uid, ref('timesheet_group1'), now, 20.0, resource=ref('resource_designer')) + assert len(work_intreval) >= 5, 'Wrong Schedule Calculated' + + diff --git a/addons/sale/sale.py b/addons/sale/sale.py index e2487d7c1cf..e56aa7d0968 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -771,6 +771,11 @@ class sale_order(osv.osv): self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty}) return True + def _get_date_planned(self, cr, uid, order, line, start_date, *args): + date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0) + date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) + return date_planned + def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, *args): """Create the required procurements to supply sale order lines, also connecting the procurements to appropriate stock moves in order to bring the goods to the @@ -799,8 +804,7 @@ class sale_order(osv.osv): if line.state == 'done': continue - date_planned = datetime.strptime(order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0) - date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) + date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, *args) if line.product_id: if line.product_id.product_tmpl_id.type in ('product', 'consu'): diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv index 25d063d49e9..2e08a025971 100644 --- a/addons/sale/security/ir.model.access.csv +++ b/addons/sale/security/ir.model.access.csv @@ -58,3 +58,4 @@ access_product_pricelist_type_sale_manager,product.pricelist.type salemanager,pr access_product_pricelist_sale_manager,product.pricelist salemanager,product.model_product_pricelist,base.group_sale_manager,1,1,1,1 access_product_group_res_partner_sale_manager,res_partner group_sale_manager,base.model_res_partner,base.group_sale_manager,1,1,1,0 access_product_pricelist_version_sale_manager,product.pricelist.version sale_manager,product.model_product_pricelist_version,base.group_sale_manager,1,1,1,1 +access_account_invoice_report_salesman,account.invoice.report salesman,account.model_account_invoice_report,base.group_sale_salesman,1,0,0,0 \ No newline at end of file diff --git a/addons/sale_crm/security/ir.model.access.csv b/addons/sale_crm/security/ir.model.access.csv index d4e6eede351..75317a244ad 100644 --- a/addons/sale_crm/security/ir.model.access.csv +++ b/addons/sale_crm/security/ir.model.access.csv @@ -1,2 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_account_invoice_report_salesman,account.invoice.report salesman,account.model_account_invoice_report,base.group_sale_salesman,1,0,0,0 + diff --git a/addons/sale_layout/sale_layout_view.xml b/addons/sale_layout/sale_layout_view.xml index 27b8e4b4f96..78f98d3002f 100644 --- a/addons/sale_layout/sale_layout_view.xml +++ b/addons/sale_layout/sale_layout_view.xml @@ -9,7 +9,7 @@ sale.order.form.inherit_1 sale.order - 30 + 1000 form diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py index 92954988dcc..52f8d5c471e 100644 --- a/addons/share/wizard/share_wizard.py +++ b/addons/share/wizard/share_wizard.py @@ -95,10 +95,13 @@ class share_wizard(osv.osv_memory): # NOTE: take _ids in parameter to allow usage through browse_record objects base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='', context=context) if base_url: - base_url += '/?db=%(dbname)s&login=%(login)s' + base_url += '/web/webclient/login?db=%(dbname)s&login=%(login)s' extra = context and context.get('share_url_template_extra_arguments') if extra: base_url += '&' + '&'.join('%s=%%(%s)s' % (x,x) for x in extra) + hash_ = context and context.get('share_url_template_hash_arguments') + if hash_: + base_url += '#' + '&'.join('%s=%%(%s)s' % (x,x) for x in hash_) return base_url def _share_root_url(self, cr, uid, ids, _fieldname, _args, context=None): @@ -156,9 +159,10 @@ class share_wizard(osv.osv_memory): result = dict.fromkeys(ids, '') for this in self.browse(cr, uid, ids, context=context): if this.result_line_ids: - ctx = dict(context, share_url_template_extra_arguments=['key']) + ctx = dict(context, share_url_template_extra_arguments=['key'], + share_url_template_hash_arguments=['action_id']) user = this.result_line_ids[0] - data = dict(dbname=cr.dbname, login=user.login, key=user.password) + data = dict(dbname=cr.dbname, login=user.login, key=user.password, action_id=this.action_id.id) result[this.id] = this.share_url_template(context=ctx) % data return result diff --git a/addons/thunderbird/plugin/openerp_plugin.xpi b/addons/thunderbird/plugin/openerp_plugin.xpi index 367a4faa049..167e7c589a5 100644 Binary files a/addons/thunderbird/plugin/openerp_plugin.xpi and b/addons/thunderbird/plugin/openerp_plugin.xpi differ diff --git a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar index 28b70611a25..0d4cc3a4018 100644 Binary files a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar and b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar differ diff --git a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin/content/overlay.js b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin/content/overlay.js index fde29df4dbe..bbfad8634d6 100644 --- a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin/content/overlay.js +++ b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin/content/overlay.js @@ -169,6 +169,16 @@ function searchmail() } +function url_for(model, id) { + var base = getWebServerURL(), + db = getDbName(), + login = getusername(), + password = getPassword(); + + return base + '/web/webclient/login?db='+db+'&login='+login+'&key='+password+'#model='+model+'&id='+id; + +} + var openPartnerHandler = { onResult: function(client, context, result) { netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserAccess'); @@ -186,15 +196,11 @@ var openPartnerHandler = { } if(strlSearchResult=="partner_id"){ partner_id = strlSearchResultValue; - weburl = getWebServerURL(); if (parseInt(partner_id) > 0){ - //Encode the url and form an url to have menu in webclient - var encoded = encodeURIComponent("/openerp/form/view?model=res.partner&id="+partner_id) - var t = weburl + "?next=" + encoded var messenger = Components.classes["@mozilla.org/messenger;1"].createInstance(); messenger = messenger.QueryInterface(Components.interfaces.nsIMessenger); - messenger.launchExternalURL(t); + messenger.launchExternalURL(url_for('res.partner', partner_id)); } else{ alert("Partner is not Available."); @@ -298,7 +304,6 @@ var listDocumentHandler = { var res = result.QueryInterface(Components.interfaces.nsISupportsArray); res_id = res.QueryElementAt(1, Components.interfaces.nsISupportsPRInt32); model = res.QueryElementAt(0, Components.interfaces.nsISupportsCString); - weburl = getWebServerURL(); if(res_id==0) { alert("Document is not available."); @@ -307,11 +312,9 @@ var listDocumentHandler = { else { - var encoded = encodeURIComponent("/openerp/form/view?model=" + model +"&id=" + res_id) - var t = weburl + "?next=" + encoded var messenger = Components.classes["@mozilla.org/messenger;1"].createInstance(); messenger = messenger.QueryInterface(Components.interfaces.nsIMessenger); - messenger.launchExternalURL(t); + messenger.launchExternalURL(url_for(model, res_id)); } },