[Merge] Merge with main addons
bzr revid: mdi@tinyerp.com-20111221065640-ekqu516ob7fspdbt
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
<page string="General">
|
||||
<group colspan="4" col="4">
|
||||
<group colspan="2" col="4">
|
||||
<separator string="Communication" colspan="4"/>
|
||||
<separator string="Personal Information" colspan="4"/>
|
||||
<field name="mobile"/>
|
||||
<field name="email" widget="email"/>
|
||||
<field name="website"/>
|
||||
@@ -52,7 +52,7 @@
|
||||
<form string="Functions and Addresses">
|
||||
<field name="location_id"/>
|
||||
<field name="function" />
|
||||
<separator string="Communication" colspan="4"/>
|
||||
<separator string="Professional Info" colspan="4"/>
|
||||
<field name="phone"/>
|
||||
<field name="fax"/>
|
||||
<field name="email" widget="email"/>
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
+12
-11
@@ -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 = '<row>'
|
||||
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 = """<b>"""+rml_obj.formatLang(price)+' '+ company_currency.symbol+"""</b>\r\n"""
|
||||
main_sp_price = """<b>"""+rml_obj.formatLang(price)+' '+ (company_currency_symbol)+"""</b>\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 += """<i>"""+rml_obj.formatLang(price) +' '+ company_currency.symbol +"""</i>\r\n"""
|
||||
sellers_price += """<i>"""+rml_obj.formatLang(price) +' '+ (company_currency_symbol) +"""</i>\r\n"""
|
||||
xml += """<col para='yes'> """+ prod_name +""" </col>
|
||||
<col para='yes'> """+ main_sp_name + sellers + """ </col>
|
||||
<col f='yes'>"""+ rml_obj.formatLang(prod_qtty) +' '+ product_uom_name +"""</col>
|
||||
<col f='yes'>"""+ rml_obj.formatLang(float(main_strd_price)) +' '+ company_currency.symbol +"""</col>
|
||||
<col f='yes'>"""+ rml_obj.formatLang(float(main_strd_price)) +' '+ (company_currency_symbol) +"""</col>
|
||||
<col f='yes'>""" + main_sp_price + sellers_price + """</col>'"""
|
||||
|
||||
xml += '</row>'
|
||||
@@ -93,9 +94,9 @@ class report_custom(report_rml):
|
||||
xml = '<row>'
|
||||
xml += "<col para='yes'>" + to_xml(workcenter.name) + '</col>'
|
||||
xml += "<col/>"
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_cycle)+' '+ company_currency.symbol + """</col>"""
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour)+' '+ company_currency.symbol + """</col>"""
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour + cost_cycle)+' '+ company_currency.symbol + """</col>"""
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_cycle)+' '+ (company_currency_symbol) + """</col>"""
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour)+' '+ (company_currency_symbol) + """</col>"""
|
||||
xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour + cost_cycle)+' '+ (company_currency_symbol) + """</col>"""
|
||||
xml += '</row>'
|
||||
|
||||
return xml, total
|
||||
@@ -159,8 +160,8 @@ class report_custom(report_rml):
|
||||
<col> """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: </col>
|
||||
<col/>
|
||||
<col f='yes'/>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ company_currency.symbol + """</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total, digits=purchase_price_digits) +' '+ company_currency.symbol + """</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
|
||||
</row></lines>'"""
|
||||
else:
|
||||
bom = bom_pool.browse(cr, uid, bom_id, context=context)
|
||||
@@ -186,7 +187,7 @@ class report_custom(report_rml):
|
||||
<col> """ + _('Components Cost of %s %s') % (str(number), product_uom_name) + """: </col>
|
||||
<col/>
|
||||
<col t='yes'/>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ company_currency.symbol + """</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
|
||||
<col t='yes'></col>
|
||||
</row></lines>'"""
|
||||
|
||||
@@ -204,13 +205,13 @@ class report_custom(report_rml):
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total2, digits=purchase_price_digits) +' '+ company_currency.symbol +"""</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) +"""</col>
|
||||
</row></lines>'"""
|
||||
xml += """<lines style='total'> <row>
|
||||
<col> """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: </col>
|
||||
<col/>
|
||||
<col t='yes'/>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd+total2, digits=purchase_price_digits) +' '+ company_currency.symbol + """</col>
|
||||
<col t='yes'>"""+ rml_obj.formatLang(total_strd+total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
|
||||
<col t='yes'></col>
|
||||
</row></lines>'"""
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
+50
-10
@@ -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):
|
||||
|
||||
@@ -5,73 +5,73 @@
|
||||
<!-- Example employee -->
|
||||
|
||||
<record id="timesheet_group1" model="resource.calendar">
|
||||
<field name="name">38 Hours/Week</field>
|
||||
<field name="name">45 Hours/Week</field>
|
||||
</record>
|
||||
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_mon1">
|
||||
<field name="name">Monday morning</field>
|
||||
<field name="dayofweek">0</field>
|
||||
<field name="hour_from">08</field>
|
||||
<field name="hour_to">12</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_mon2">
|
||||
<field name="name">Monday evening</field>
|
||||
<field name="dayofweek">0</field>
|
||||
<field name="hour_from">13</field>
|
||||
<field name="hour_to">18</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_tue1">
|
||||
<field name="name">Tuesday morning</field>
|
||||
<field name="dayofweek">1</field>
|
||||
<field name="hour_from">08</field>
|
||||
<field name="hour_to">12</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_tue2">
|
||||
<field name="name">Tuesday evening</field>
|
||||
<field name="dayofweek">1</field>
|
||||
<field name="hour_from">13</field>
|
||||
<field name="hour_to">18</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_wed1">
|
||||
<field name="name">Wednesday morning</field>
|
||||
<field name="dayofweek">2</field>
|
||||
<field name="hour_from">08</field>
|
||||
<field name="hour_to">12</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_wed2">
|
||||
<field name="name">Wednesday evening</field>
|
||||
<field name="dayofweek">2</field>
|
||||
<field name="hour_from">13</field>
|
||||
<field name="hour_to">18</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_thu1">
|
||||
<field name="name">Thursday morning</field>
|
||||
<field name="dayofweek">3</field>
|
||||
<field name="hour_from">08</field>
|
||||
<field name="hour_to">12</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_thu2">
|
||||
<field name="name">Thursday evening</field>
|
||||
<field name="hour_from">13</field>
|
||||
<field name="hour_to">18</field>
|
||||
<field name="dayofweek">3</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_fri1">
|
||||
<field name="name">Friday morning</field>
|
||||
<field name="dayofweek">4</field>
|
||||
<field name="hour_from">08</field>
|
||||
<field name="hour_to">12</field>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
<record model="resource.calendar.attendance">
|
||||
<record model="resource.calendar.attendance" id="calendar_attendance_fri2">
|
||||
<field name="name">Friday evening</field>
|
||||
<field name="dayofweek">4</field>
|
||||
<field name="hour_from">13</field>
|
||||
@@ -79,5 +79,47 @@
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
|
||||
<record id="resource_analyst" model="resource.resource">
|
||||
<field eval="1.0" name="time_efficiency"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Analyst</field>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
<field name="resource_type">user</field>
|
||||
</record>
|
||||
|
||||
<record id="resource_designer" model="resource.resource">
|
||||
<field eval="1.0" name="time_efficiency"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="name">Designer</field>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
<field name="resource_type">user</field>
|
||||
</record>
|
||||
|
||||
<record id="resource_developer" model="resource.resource">
|
||||
<field eval="1.0" name="time_efficiency"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="name">Developer</field>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
<field name="resource_type">user</field>
|
||||
</record>
|
||||
|
||||
<record id="resource_analyst_leaves_demoleave1" model="resource.calendar.leaves">
|
||||
<field name="name">2 Hours On Leave</field>
|
||||
<field name="resource_id" ref="resource_analyst"/>
|
||||
<field name="date_from" eval="time.strftime('%Y-%m-%d 08:00:00')"/>
|
||||
<field name="date_to" eval="time.strftime('%Y-%m-%d 11:00:00')"/>
|
||||
<field name="calendar_id" ref="timesheet_group1"/>
|
||||
</record>
|
||||
|
||||
<record id="resource_dummyleave" model="resource.calendar.leaves">
|
||||
<field name="name">Dummy Resource Leave</field>
|
||||
<field name="resource_id" ref="resource_analyst"/>
|
||||
<field name="date_from" eval="time.strftime('%Y-%m-%d 08:00:00')"/>
|
||||
<field name="date_to" eval="time.strftime('%Y-%m-%d 11:00:00')"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -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"
|
||||
@@ -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'
|
||||
|
||||
|
||||
+6
-2
@@ -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'):
|
||||
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<field name="name">sale.order.form.inherit_1</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale.view_order_form"/>
|
||||
<field name="priority">30</field>
|
||||
<field name="priority">1000</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/notebook/page/field[@name='order_line']" position="replace">
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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));
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user