[MERGE] forward port of branch saas-2 up to revid 9010 dle@openerp.com-20131125143003-vjtzj1c5051pdnk3
bzr revid: chs@openerp.com-20131125150054-b135qshkx6icakgk
This commit is contained in:
commit
bb1e256f5b
|
@ -1447,6 +1447,8 @@ class account_move(osv.osv):
|
||||||
def unlink(self, cr, uid, ids, context=None, check=True):
|
def unlink(self, cr, uid, ids, context=None, check=True):
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
if isinstance(ids, (int, long)):
|
||||||
|
ids = [ids]
|
||||||
toremove = []
|
toremove = []
|
||||||
obj_move_line = self.pool.get('account.move.line')
|
obj_move_line = self.pool.get('account.move.line')
|
||||||
for move in self.browse(cr, uid, ids, context=context):
|
for move in self.browse(cr, uid, ids, context=context):
|
||||||
|
|
|
@ -311,13 +311,13 @@ class account_move_line(osv.osv):
|
||||||
context = {}
|
context = {}
|
||||||
c = context.copy()
|
c = context.copy()
|
||||||
c['initital_bal'] = True
|
c['initital_bal'] = True
|
||||||
sql = """SELECT l2.id, SUM(l1.debit-l1.credit)
|
sql = """SELECT l1.id, COALESCE(SUM(l2.debit-l2.credit), 0)
|
||||||
FROM account_move_line l1, account_move_line l2
|
FROM account_move_line l1 LEFT JOIN account_move_line l2
|
||||||
WHERE l2.account_id = l1.account_id
|
ON (l1.account_id = l2.account_id
|
||||||
AND l1.id <= l2.id
|
AND l2.id <= l1.id
|
||||||
AND l2.id IN %s AND """ + \
|
AND """ + \
|
||||||
self._query_get(cr, uid, obj='l1', context=c) + \
|
self._query_get(cr, uid, obj='l2', context=c) + \
|
||||||
" GROUP BY l2.id"
|
") WHERE l1.id IN %s GROUP BY l1.id"
|
||||||
|
|
||||||
cr.execute(sql, [tuple(ids)])
|
cr.execute(sql, [tuple(ids)])
|
||||||
return dict(cr.fetchall())
|
return dict(cr.fetchall())
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_payment_term_line_immediate" model="account.payment.term.line">
|
<record id="account_payment_term_line_immediate" model="account.payment.term.line">
|
||||||
<field name="name">Immediate Payment</field>
|
|
||||||
<field name="value">balance</field>
|
<field name="value">balance</field>
|
||||||
<field eval="0" name="days"/>
|
<field eval="0" name="days"/>
|
||||||
<field eval="0" name="days2"/>
|
<field eval="0" name="days2"/>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<!--Email template -->
|
<!--Email template -->
|
||||||
<record id="email_template_edi_invoice" model="email.template">
|
<record id="email_template_edi_invoice" model="email.template">
|
||||||
<field name="name">Invoice - Send by Email</field>
|
<field name="name">Invoice - Send by Email</field>
|
||||||
<field name="email_from">${object.user_id.email or object.company_id.email or 'noreply@localhost'}</field>
|
<field name="email_from">${(object.user_id.email or object.company_id.email or 'noreply@localhost')|safe}</field>
|
||||||
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a'})</field>
|
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a'})</field>
|
||||||
<field name="partner_to">${object.partner_id.id}</field>
|
<field name="partner_to">${object.partner_id.id}</field>
|
||||||
<field name="model_id" ref="account.model_account_invoice"/>
|
<field name="model_id" ref="account.model_account_invoice"/>
|
||||||
|
|
|
@ -107,14 +107,15 @@ class res_partner(osv.osv):
|
||||||
_description = 'Partner'
|
_description = 'Partner'
|
||||||
|
|
||||||
def _credit_debit_get(self, cr, uid, ids, field_names, arg, context=None):
|
def _credit_debit_get(self, cr, uid, ids, field_names, arg, context=None):
|
||||||
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
|
ctx = context.copy()
|
||||||
|
ctx['all_fiscalyear'] = True
|
||||||
|
query = self.pool.get('account.move.line')._query_get(cr, uid, context=ctx)
|
||||||
cr.execute("""SELECT l.partner_id, a.type, SUM(l.debit-l.credit)
|
cr.execute("""SELECT l.partner_id, a.type, SUM(l.debit-l.credit)
|
||||||
FROM account_move_line l
|
FROM account_move_line l
|
||||||
LEFT JOIN account_account a ON (l.account_id=a.id)
|
LEFT JOIN account_account a ON (l.account_id=a.id)
|
||||||
WHERE a.type IN ('receivable','payable')
|
WHERE a.type IN ('receivable','payable')
|
||||||
AND l.partner_id IN %s
|
AND l.partner_id IN %s
|
||||||
AND (l.reconcile_id IS NULL OR
|
AND l.reconcile_id IS NULL
|
||||||
reconcile_id in (SELECT id FROM account_move_reconcile WHERE opening_reconciliation is TRUE))
|
|
||||||
AND """ + query + """
|
AND """ + query + """
|
||||||
GROUP BY l.partner_id, a.type
|
GROUP BY l.partner_id, a.type
|
||||||
""",
|
""",
|
||||||
|
|
|
@ -170,6 +170,7 @@
|
||||||
<paraStyle name="Heading 9" fontName="Helvetica-Bold" fontSize="75%" leading="NaN" spaceBefore="12.0" spaceAfter="6.0"/>
|
<paraStyle name="Heading 9" fontName="Helvetica-Bold" fontSize="75%" leading="NaN" spaceBefore="12.0" spaceAfter="6.0"/>
|
||||||
<paraStyle name="terp_tblheader_General" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
<paraStyle name="terp_tblheader_General" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||||
<paraStyle name="terp_tblheader_Details" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
<paraStyle name="terp_tblheader_Details" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||||
|
<paraStyle name="terp_default_Centre_7" fontName="Helvetica" fontSize="7.0" leading="9" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||||
<paraStyle name="terp_default_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
<paraStyle name="terp_default_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||||
<paraStyle name="terp_default_Bold_8" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
<paraStyle name="terp_default_Bold_8" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||||
<paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
|
<paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||||
|
|
|
@ -52,10 +52,19 @@ class account_invoice_refund(osv.osv_memory):
|
||||||
journal = obj_journal.search(cr, uid, [('type', '=', type), ('company_id','=',company_id)], limit=1, context=context)
|
journal = obj_journal.search(cr, uid, [('type', '=', type), ('company_id','=',company_id)], limit=1, context=context)
|
||||||
return journal and journal[0] or False
|
return journal and journal[0] or False
|
||||||
|
|
||||||
|
def _get_reason(self, cr, uid, context=None):
|
||||||
|
active_id = context and context.get('active_id', False)
|
||||||
|
if active_id:
|
||||||
|
inv = self.pool.get('account.invoice').browse(cr, uid, active_id, context=context)
|
||||||
|
return inv.name
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'date': lambda *a: time.strftime('%Y-%m-%d'),
|
'date': lambda *a: time.strftime('%Y-%m-%d'),
|
||||||
'journal_id': _get_journal,
|
'journal_id': _get_journal,
|
||||||
'filter_refund': 'refund',
|
'filter_refund': 'refund',
|
||||||
|
'description': _get_reason,
|
||||||
}
|
}
|
||||||
|
|
||||||
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
|
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
<record id="account_analytic_cron_email_template" model="email.template">
|
<record id="account_analytic_cron_email_template" model="email.template">
|
||||||
<field name="name">Contract expiration reminder</field>
|
<field name="name">Contract expiration reminder</field>
|
||||||
<field name="email_from">${object.email or ''}</field>
|
<field name="email_from">${(object.email or '')|safe}</field>
|
||||||
<field name="subject">Contract expiration reminder ${user.company_id.name}</field>
|
<field name="subject">Contract expiration reminder ${user.company_id.name}</field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="lang">${object.lang}</field>
|
<field name="lang">${object.lang}</field>
|
||||||
<field name="model_id" ref="base.model_res_users"/>
|
<field name="model_id" ref="base.model_res_users"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
|
|
|
@ -182,19 +182,19 @@
|
||||||
<blockTable colWidths="221.0,82.0,83.0,85.0,57.0" style="Table4">
|
<blockTable colWidths="221.0,82.0,83.0,85.0,57.0" style="Table4">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_9"><font face="Helvetica" size="9.0" color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica" size="8.0"> [[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ a['name'] ]]</para>
|
<para style="terp_default_9"><font face="Helvetica" size="9.0" color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica" size="8.0"> [[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ a['name'] ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['pln'], currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['pln'], currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['prac'], currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['prac'], currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Centre_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['perc']) ]]%</para>
|
<para style="terp_default_Centre_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['perc']) ]]%</para>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</blockTable>
|
</blockTable>
|
||||||
|
|
|
@ -145,19 +145,19 @@
|
||||||
<blockTable colWidths="185.0,79.0,78.0,81.0,59.0" style="Table4">
|
<blockTable colWidths="185.0,79.0,78.0,81.0,59.0" style="Table4">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_9"><font color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica">[[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]] </font>[[ a['name'] ]]</para>
|
<para style="terp_default_9"><font color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica">[[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] </font>[[ a['name'] ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['perc'], digits=2) ]]%</para>
|
<para style="terp_default_Right_9"><font face="Helvetica">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] </font>[[ formatLang(a['perc'], digits=2) ]]%</para>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</blockTable>
|
</blockTable>
|
||||||
|
|
|
@ -160,19 +160,19 @@
|
||||||
<blockTable colWidths="205.0,88.0,87.0,90.0,66.0" style="Table4">
|
<blockTable colWidths="205.0,88.0,87.0,90.0,66.0" style="Table4">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_9"><font face="Helvetica" size="10.0" color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica" size="8.0">[[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ a['name'] ]]</para>
|
<para style="terp_default_9"><font face="Helvetica" size="10.0" color="white">[['.....' *(a['status']-1) ]]</font><font face="Helvetica" size="8.0">[[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ a['name'] ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['theo'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['pln'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['pln'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['prac'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
<para style="terp_default_Right_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['prac'], dp='Account', currency_obj=company.currency_id) ]]</para>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<para style="terp_default_Centre_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['perc'],digits=2) ]]%</para>
|
<para style="terp_default_Centre_9"><font face="Helvetica" size="8.0">[[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]]</font> [[ formatLang(a['perc'],digits=2) ]]%</para>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</blockTable>
|
</blockTable>
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
<!--Mail template level 0-->
|
<!--Mail template level 0-->
|
||||||
<record id="email_template_account_followup_level0" model="email.template">
|
<record id="email_template_account_followup_level0" model="email.template">
|
||||||
<field name="name">First polite payment follow-up reminder email</field>
|
<field name="name">First polite payment follow-up reminder email</field>
|
||||||
<field name="email_from">${user.email or ''}</field>
|
<field name="email_from">${(user.email or '')|safe}</field>
|
||||||
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="lang">${object.lang}</field>
|
<field name="lang">${object.lang}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
|
@ -45,9 +45,9 @@ ${object.get_followup_table_html() | safe}
|
||||||
<!--Mail template level 1 -->
|
<!--Mail template level 1 -->
|
||||||
<record id="email_template_account_followup_level1" model="email.template">
|
<record id="email_template_account_followup_level1" model="email.template">
|
||||||
<field name="name">A bit urging second payment follow-up reminder email</field>
|
<field name="name">A bit urging second payment follow-up reminder email</field>
|
||||||
<field name="email_from">${user.email or ''}</field>
|
<field name="email_from">${(user.email or '')|safe}</field>
|
||||||
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="lang">${object.lang}</field>
|
<field name="lang">${object.lang}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
|
@ -85,9 +85,9 @@ ${object.get_followup_table_html() | safe}
|
||||||
<!--Mail template level 2 -->
|
<!--Mail template level 2 -->
|
||||||
<record id="email_template_account_followup_level2" model="email.template">
|
<record id="email_template_account_followup_level2" model="email.template">
|
||||||
<field name="name">Urging payment follow-up reminder email</field>
|
<field name="name">Urging payment follow-up reminder email</field>
|
||||||
<field name="email_from">${user.email or ''}</field>
|
<field name="email_from">${(user.email or '')|safe}</field>
|
||||||
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="lang">${object.lang}</field>
|
<field name="lang">${object.lang}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
|
@ -122,9 +122,9 @@ ${object.get_followup_table_html() | safe}
|
||||||
<!-- Default follow up message -->
|
<!-- Default follow up message -->
|
||||||
<record id="email_template_account_followup_default" model="email.template">
|
<record id="email_template_account_followup_default" model="email.template">
|
||||||
<field name="name">Default payment follow-up reminder e-mail</field>
|
<field name="name">Default payment follow-up reminder e-mail</field>
|
||||||
<field name="email_from">${user.email or ''}</field>
|
<field name="email_from">${(user.email or '')|safe}</field>
|
||||||
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
<field name="subject">${user.company_id.name} Payment Reminder</field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="lang">${object.lang}</field>
|
<field name="lang">${object.lang}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
|
@ -162,7 +162,7 @@ ${object.get_followup_table_html() | safe}
|
||||||
<field name="sequence">0</field>
|
<field name="sequence">0</field>
|
||||||
<field name="delay">15</field>
|
<field name="delay">15</field>
|
||||||
<field name="followup_id" ref="demo_followup1"/>
|
<field name="followup_id" ref="demo_followup1"/>
|
||||||
<field name="send-email">True</field>
|
<field name="send_email">True</field>
|
||||||
<field name="description">
|
<field name="description">
|
||||||
Dear %(partner_name)s,
|
Dear %(partner_name)s,
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ _logger = logging.getLogger(__name__)
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
def fragment_to_query_string(func):
|
def fragment_to_query_string(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(self, **kw):
|
def wrapper(self, *a, **kw):
|
||||||
if not kw:
|
if not kw:
|
||||||
return """<html><head><script>
|
return """<html><head><script>
|
||||||
var l = window.location;
|
var l = window.location;
|
||||||
|
@ -31,7 +31,7 @@ def fragment_to_query_string(func):
|
||||||
}
|
}
|
||||||
window.location = r;
|
window.location = r;
|
||||||
</script></head><body></body></html>"""
|
</script></head><body></body></html>"""
|
||||||
return func(self, **kw)
|
return func(self, *a, **kw)
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
<record id="reset_password_email" model="email.template">
|
<record id="reset_password_email" model="email.template">
|
||||||
<field name="name">Reset Password</field>
|
<field name="name">Reset Password</field>
|
||||||
<field name="model_id" ref="base.model_res_users"/>
|
<field name="model_id" ref="base.model_res_users"/>
|
||||||
<field name="email_from"><![CDATA[${object.company_id.name} <${object.company_id.email or user.email}>]]></field>
|
<field name="email_from"><![CDATA[${object.company_id.name} <${(object.company_id.email or user.email)|safe}>]]></field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="subject">Password reset</field>
|
<field name="subject">Password reset</field>
|
||||||
<field name="body_html"><![CDATA[
|
<field name="body_html"><![CDATA[
|
||||||
<p>A password reset was requested for the OpenERP account linked to this email.</p>
|
<p>A password reset was requested for the OpenERP account linked to this email.</p>
|
||||||
|
@ -37,8 +37,8 @@
|
||||||
<record id="set_password_email" model="email.template">
|
<record id="set_password_email" model="email.template">
|
||||||
<field name="name">OpenERP Enterprise Connection</field>
|
<field name="name">OpenERP Enterprise Connection</field>
|
||||||
<field name="model_id" ref="base.model_res_users"/>
|
<field name="model_id" ref="base.model_res_users"/>
|
||||||
<field name="email_from"><![CDATA[${object.company_id.name} <${object.company_id.email or user.email}>]]></field>
|
<field name="email_from"><![CDATA[${object.company_id.name} <${(object.company_id.email or user.email)|safe}>]]></field>
|
||||||
<field name="email_to">${object.email}</field>
|
<field name="email_to">${object.email|safe}</field>
|
||||||
<field name="subject"><![CDATA[${object.company_id.name} invitation to connect on OpenERP]]></field>
|
<field name="subject"><![CDATA[${object.company_id.name} invitation to connect on OpenERP]]></field>
|
||||||
<field name="body_html">
|
<field name="body_html">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
|
|
@ -39,12 +39,6 @@ openerp.auth_signup = function(instance) {
|
||||||
delete self.params.error_message;
|
delete self.params.error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case of a signup, retrieve the user information from the token
|
|
||||||
if (dbname && self.params.token) {
|
|
||||||
self.rpc("/auth_signup/retrieve", {dbname: dbname, token: self.params.token})
|
|
||||||
.done(self.on_token_loaded)
|
|
||||||
.fail(self.on_token_failed);
|
|
||||||
}
|
|
||||||
if (dbname && self.params.login) {
|
if (dbname && self.params.login) {
|
||||||
self.$("form input[name=login]").val(self.params.login);
|
self.$("form input[name=login]").val(self.params.login);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +47,7 @@ openerp.auth_signup = function(instance) {
|
||||||
self.$('a.oe_signup_reset_password').click(self.do_reset_password);
|
self.$('a.oe_signup_reset_password').click(self.do_reset_password);
|
||||||
|
|
||||||
if (dbname) {
|
if (dbname) {
|
||||||
self.rpc("/auth_signup/get_config", {dbname: dbname}).done(function(result) {
|
self.rpc("/auth_signup/get_config", {dbname: dbname}).then(function(result) {
|
||||||
self.signup_enabled = result.signup;
|
self.signup_enabled = result.signup;
|
||||||
self.reset_password_enabled = result.reset_password;
|
self.reset_password_enabled = result.reset_password;
|
||||||
if (!self.signup_enabled || self.$("form input[name=login]").val()){
|
if (!self.signup_enabled || self.$("form input[name=login]").val()){
|
||||||
|
@ -61,6 +55,13 @@ openerp.auth_signup = function(instance) {
|
||||||
} else {
|
} else {
|
||||||
self.set('login_mode', 'signup');
|
self.set('login_mode', 'signup');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in case of a signup, retrieve the user information from the token
|
||||||
|
if (self.params.token) {
|
||||||
|
self.rpc("/auth_signup/retrieve", {dbname: dbname, token: self.params.token})
|
||||||
|
.then(self.on_token_loaded, self.on_token_failed);
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// TODO: support multiple database mode
|
// TODO: support multiple database mode
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
access_base_action_rule,base.action.rule,model_base_action_rule,,1,0,0,0
|
access_base_action_rule,base.action.rule,model_base_action_rule,,1,0,0,0
|
||||||
access_base_action_rule_config,base.action.rule config,model_base_action_rule,base.group_system,1,1,1,1
|
access_base_action_rule_config,base.action.rule config,model_base_action_rule,base.group_system,1,1,1,1
|
||||||
|
access_base_action_rule_lead_test,access_base_action_rule_lead_test,model_base_action_rule_lead_test,base.group_system,1,1,1,1
|
||||||
|
|
|
|
@ -51,7 +51,12 @@ openerp.base_import = function (instance) {
|
||||||
type: 'ir.actions.client',
|
type: 'ir.actions.client',
|
||||||
tag: 'import',
|
tag: 'import',
|
||||||
params: {
|
params: {
|
||||||
model: self.dataset.model
|
model: self.dataset.model,
|
||||||
|
// self.dataset.get_context() could be a compound?
|
||||||
|
// not sure. action's context should be evaluated
|
||||||
|
// so safer bet. Odd that timezone & al in it
|
||||||
|
// though
|
||||||
|
context: self.getParent().action.context,
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
on_reverse_breadcrumb: function () {
|
on_reverse_breadcrumb: function () {
|
||||||
|
@ -127,6 +132,7 @@ openerp.base_import = function (instance) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
this.res_model = action.params.model;
|
this.res_model = action.params.model;
|
||||||
|
this.parent_context = action.params.context || {};
|
||||||
// import object id
|
// import object id
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.Import = new instance.web.Model('base_import.import');
|
this.Import = new instance.web.Model('base_import.import');
|
||||||
|
@ -353,11 +359,12 @@ openerp.base_import = function (instance) {
|
||||||
},
|
},
|
||||||
|
|
||||||
//- import itself
|
//- import itself
|
||||||
call_import: function (options) {
|
call_import: function (kwargs) {
|
||||||
var fields = this.$('.oe_import_fields input.oe_import_match_field').map(function (index, el) {
|
var fields = this.$('.oe_import_fields input.oe_import_match_field').map(function (index, el) {
|
||||||
return $(el).select2('val') || false;
|
return $(el).select2('val') || false;
|
||||||
}).get();
|
}).get();
|
||||||
return this.Import.call('do', [this.id, fields, this.import_options()], options)
|
kwargs.context = this.parent_context;
|
||||||
|
return this.Import.call('do', [this.id, fields, this.import_options()], kwargs)
|
||||||
.then(undefined, function (error, event) {
|
.then(undefined, function (error, event) {
|
||||||
// In case of unexpected exception, convert
|
// In case of unexpected exception, convert
|
||||||
// "JSON-RPC error" to an import failure, and
|
// "JSON-RPC error" to an import failure, and
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# OpenERP, Open Source Management Solution
|
# OpenERP, Open Source Management Solution
|
||||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||||
# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
|
# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License as
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
@ -49,6 +49,7 @@ class board_board(osv.osv):
|
||||||
('value', 'in', refs),
|
('value', 'in', refs),
|
||||||
], context=context)
|
], context=context)
|
||||||
menu_ids = map(itemgetter('res_id'), IrValues.read(cr, uid, irv_ids, ['res_id'], context=context))
|
menu_ids = map(itemgetter('res_id'), IrValues.read(cr, uid, irv_ids, ['res_id'], context=context))
|
||||||
|
menu_ids = Menus._filter_visible_menus(cr, uid, menu_ids, context=context)
|
||||||
menu_names = Menus.name_get(cr, uid, menu_ids, context=context)
|
menu_names = Menus.name_get(cr, uid, menu_ids, context=context)
|
||||||
return [dict(id=m[0], name=m[1]) for m in menu_names]
|
return [dict(id=m[0], name=m[1]) for m in menu_names]
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
import openerp
|
|
||||||
from openerp.addons.web.controllers.main import load_actions_from_ir_values
|
from openerp.addons.web.controllers.main import load_actions_from_ir_values
|
||||||
|
from openerp.addons.web.http import Controller, route, request
|
||||||
|
|
||||||
class Board(openerp.http.Controller):
|
class Board(Controller):
|
||||||
@openerp.http.route('/board/add_to_dashboard', type='json', auth='user')
|
@route('/board/add_to_dashboard', type='json', auth='user')
|
||||||
def add_to_dashboard(self, menu_id, action_id, context_to_save, domain, view_mode, name=''):
|
def add_to_dashboard(self, menu_id, action_id, context_to_save, domain, view_mode, name=''):
|
||||||
req = openerp.http.request
|
|
||||||
# FIXME move this method to board.board model
|
# FIXME move this method to board.board model
|
||||||
dashboard_action = load_actions_from_ir_values('action', 'tree_but_open', [('ir.ui.menu', menu_id)], False)
|
dashboard_action = load_actions_from_ir_values('action', 'tree_but_open',
|
||||||
|
[('ir.ui.menu', menu_id)], False)
|
||||||
|
|
||||||
if dashboard_action:
|
if dashboard_action:
|
||||||
action = dashboard_action[0][2]
|
action = dashboard_action[0][2]
|
||||||
if action['res_model'] == 'board.board' and action['views'][0][1] == 'form':
|
if action['res_model'] == 'board.board' and action['views'][0][1] == 'form':
|
||||||
# Maybe should check the content instead of model board.board ?
|
# Maybe should check the content instead of model board.board ?
|
||||||
view_id = action['views'][0][0]
|
view_id = action['views'][0][0]
|
||||||
board = req.session.model(action['res_model']).fields_view_get(view_id, 'form')
|
board = request.session.model(action['res_model']).fields_view_get(view_id, 'form')
|
||||||
if board and 'arch' in board:
|
if board and 'arch' in board:
|
||||||
xml = ElementTree.fromstring(board['arch'])
|
xml = ElementTree.fromstring(board['arch'])
|
||||||
column = xml.find('./board/column')
|
column = xml.find('./board/column')
|
||||||
|
@ -30,10 +30,10 @@ class Board(openerp.http.Controller):
|
||||||
})
|
})
|
||||||
column.insert(0, new_action)
|
column.insert(0, new_action)
|
||||||
arch = ElementTree.tostring(xml, 'utf-8')
|
arch = ElementTree.tostring(xml, 'utf-8')
|
||||||
return req.session.model('ir.ui.view.custom').create({
|
return request.session.model('ir.ui.view.custom').create({
|
||||||
'user_id': req.session._uid,
|
'user_id': request.session.uid,
|
||||||
'ref_id': view_id,
|
'ref_id': view_id,
|
||||||
'arch': arch
|
'arch': arch
|
||||||
}, req.context)
|
}, request.context)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -20,10 +20,7 @@
|
||||||
<field name="view_mode">graph,tree,form</field>
|
<field name="view_mode">graph,tree,form</field>
|
||||||
<field name="view_id" ref="view_crm_opportunity_stage_graph"/>
|
<field name="view_id" ref="view_crm_opportunity_stage_graph"/>
|
||||||
<!-- avoid done / cancelled -->
|
<!-- avoid done / cancelled -->
|
||||||
<field name="domain">['|',
|
<field name="domain">['&', ('stage_id.fold', '=', False), ('type', '=', 'opportunity')]</field>
|
||||||
'!', '&', ('probability', '=', 100), ('stage_id.on_change', '=', 1),
|
|
||||||
'!', '&', ('probability', '=', 0), ('stage_id.sequence', '!=', 1),
|
|
||||||
('type', '=', 'opportunity')]</field>
|
|
||||||
<field name="context">{'search_default_Stage':1}</field>
|
<field name="context">{'search_default_Stage':1}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
@ -48,7 +45,7 @@
|
||||||
<field name="view_mode">graph,tree,form</field>
|
<field name="view_mode">graph,tree,form</field>
|
||||||
<field name="view_id" ref="view_crm_opportunity_user_stage_graph"/>
|
<field name="view_id" ref="view_crm_opportunity_user_stage_graph"/>
|
||||||
<!-- avoid cancelled -->
|
<!-- avoid cancelled -->
|
||||||
<field name="domain">['!', '&', ('probability', '=', 0), ('stage_id.sequence', '!=', 1)]</field>
|
<field name="domain">['|', ('stage_id.fold', '=', False), ('stage_id.probability', '=', 100)]</field>
|
||||||
<field name="context">{'search_default_user': 1, 'search_default_Stage': 1}</field>
|
<field name="context">{'search_default_user': 1, 'search_default_Stage': 1}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,9 @@ class crm_case_stage(osv.osv):
|
||||||
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
|
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
|
||||||
'case_default': fields.boolean('Default to New Sales Team',
|
'case_default': fields.boolean('Default to New Sales Team',
|
||||||
help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
|
help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
|
||||||
'fold': fields.boolean('Fold by Default',
|
'fold': fields.boolean('Folded in Kanban View',
|
||||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
help='This stage is folded in the kanban view when'
|
||||||
|
'there are no records in that stage to display.'),
|
||||||
'type': fields.selection([('lead', 'Lead'),
|
'type': fields.selection([('lead', 'Lead'),
|
||||||
('opportunity', 'Opportunity'),
|
('opportunity', 'Opportunity'),
|
||||||
('both', 'Both')],
|
('both', 'Both')],
|
||||||
|
@ -78,8 +79,8 @@ class crm_case_stage(osv.osv):
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'sequence': lambda *args: 1,
|
'sequence': 1,
|
||||||
'probability': lambda *args: 0.0,
|
'probability': 0.0,
|
||||||
'on_change': True,
|
'on_change': True,
|
||||||
'fold': False,
|
'fold': False,
|
||||||
'type': 'both',
|
'type': 'both',
|
||||||
|
|
|
@ -72,10 +72,11 @@ class crm_lead(format_address, osv.osv):
|
||||||
|
|
||||||
_track = {
|
_track = {
|
||||||
'stage_id': {
|
'stage_id': {
|
||||||
'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence == 1,
|
# this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
|
||||||
'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: (obj.stage_id and obj.stage_id.sequence != 1) and obj.probability < 100,
|
'crm.mt_lead_create': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence <= 1,
|
||||||
'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj.probability == 100 and obj.stage_id and obj.stage_id.on_change,
|
'crm.mt_lead_stage': lambda self, cr, uid, obj, ctx=None: (obj.stage_id and obj.stage_id.sequence > 1) and obj.probability < 100,
|
||||||
'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence != 1,
|
'crm.mt_lead_won': lambda self, cr, uid, obj, ctx=None: obj.probability == 100 and obj.stage_id and obj.stage_id.fold,
|
||||||
|
'crm.mt_lead_lost': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.fold and obj.stage_id.sequence > 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ class crm_lead(format_address, osv.osv):
|
||||||
def _get_default_stage_id(self, cr, uid, context=None):
|
def _get_default_stage_id(self, cr, uid, context=None):
|
||||||
""" Gives default stage_id """
|
""" Gives default stage_id """
|
||||||
section_id = self._get_default_section_id(cr, uid, context=context)
|
section_id = self._get_default_section_id(cr, uid, context=context)
|
||||||
return self.stage_find(cr, uid, [], section_id, [('sequence', '=', '1')], context=context)
|
return self.stage_find(cr, uid, [], section_id, [('fold', '=', False)], context=context)
|
||||||
|
|
||||||
def _resolve_section_id_from_context(self, cr, uid, context=None):
|
def _resolve_section_id_from_context(self, cr, uid, context=None):
|
||||||
""" Returns ID of section based on the value of 'section_id'
|
""" Returns ID of section based on the value of 'section_id'
|
||||||
|
@ -382,34 +383,52 @@ class crm_lead(format_address, osv.osv):
|
||||||
# AND with the domain in parameter
|
# AND with the domain in parameter
|
||||||
search_domain += list(domain)
|
search_domain += list(domain)
|
||||||
# perform search, return the first found
|
# perform search, return the first found
|
||||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, context=context)
|
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, limit=1, context=context)
|
||||||
if stage_ids:
|
if stage_ids:
|
||||||
return stage_ids[0]
|
return stage_ids[0]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def case_mark_lost(self, cr, uid, ids, context=None):
|
def case_mark_lost(self, cr, uid, ids, context=None):
|
||||||
""" Mark the case as lost: state=cancel and probability=0 """
|
""" Mark the case as lost: state=cancel and probability=0
|
||||||
for lead in self.browse(cr, uid, ids):
|
:deprecated: this method will be removed in OpenERP v8.
|
||||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
|
"""
|
||||||
|
stages_leads = {}
|
||||||
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
|
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('fold', '=', True), ('sequence', '>', 1)], context=context)
|
||||||
if stage_id:
|
if stage_id:
|
||||||
return self.write(cr, uid, [lead.id], {'stage_id': stage_id}, context=context)
|
if stages_leads.get(stage_id):
|
||||||
|
stages_leads[stage_id].append(lead.id)
|
||||||
|
else:
|
||||||
|
stages_leads[stage_id] = [lead.id]
|
||||||
else:
|
else:
|
||||||
raise osv.except_osv(_('Warning!'),
|
raise osv.except_osv(_('Warning!'),
|
||||||
_('To relieve your sales pipe and group all Lost opportunities, configure one of your sales stage as follow:\n'
|
_('To relieve your sales pipe and group all Lost opportunities, configure one of your sales stage as follow:\n'
|
||||||
'probability = 0 %, select "Change Probability Automatically".\n'
|
'probability = 0 %, select "Change Probability Automatically".\n'
|
||||||
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
|
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
|
||||||
|
for stage_id, lead_ids in stages_leads.items():
|
||||||
|
self.write(cr, uid, lead_ids, {'stage_id': stage_id}, context=context)
|
||||||
|
return True
|
||||||
|
|
||||||
def case_mark_won(self, cr, uid, ids, context=None):
|
def case_mark_won(self, cr, uid, ids, context=None):
|
||||||
""" Mark the case as won: state=done and probability=100 """
|
""" Mark the case as won: state=done and probability=100
|
||||||
for lead in self.browse(cr, uid, ids):
|
:deprecated: this method will be removed in OpenERP v8.
|
||||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
|
"""
|
||||||
|
stages_leads = {}
|
||||||
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
|
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('fold', '=', True)], context=context)
|
||||||
if stage_id:
|
if stage_id:
|
||||||
return self.write(cr, uid, [lead.id], {'stage_id': stage_id}, context=context)
|
if stages_leads.get(stage_id):
|
||||||
|
stages_leads[stage_id].append(lead.id)
|
||||||
|
else:
|
||||||
|
stages_leads[stage_id] = [lead.id]
|
||||||
else:
|
else:
|
||||||
raise osv.except_osv(_('Warning!'),
|
raise osv.except_osv(_('Warning!'),
|
||||||
_('To relieve your sales pipe and group all Won opportunities, configure one of your sales stage as follow:\n'
|
_('To relieve your sales pipe and group all Won opportunities, configure one of your sales stage as follow:\n'
|
||||||
'probability = 100 % and select "Change Probability Automatically".\n'
|
'probability = 100 % and select "Change Probability Automatically".\n'
|
||||||
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
|
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
|
||||||
|
for stage_id, lead_ids in stages_leads.items():
|
||||||
|
self.write(cr, uid, lead_ids, {'stage_id': stage_id}, context=context)
|
||||||
|
return True
|
||||||
|
|
||||||
def case_escalate(self, cr, uid, ids, context=None):
|
def case_escalate(self, cr, uid, ids, context=None):
|
||||||
""" Escalates case to parent level """
|
""" Escalates case to parent level """
|
||||||
|
@ -617,7 +636,7 @@ class crm_lead(format_address, osv.osv):
|
||||||
# An Opportunity always has higher confidence level than a lead, unless its stage probability is 0.0
|
# An Opportunity always has higher confidence level than a lead, unless its stage probability is 0.0
|
||||||
for opportunity in opportunities:
|
for opportunity in opportunities:
|
||||||
sequence = -1
|
sequence = -1
|
||||||
if opportunity.stage_id and (opportunity.stage_id.probability != 0 or opportunity.stage_id.sequence == 1):
|
if opportunity.stage_id and not opportunity.stage_id.fold:
|
||||||
sequence = opportunity.stage_id.sequence
|
sequence = opportunity.stage_id.sequence
|
||||||
sequenced_opps.append(((int(sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id), opportunity))
|
sequenced_opps.append(((int(sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id), opportunity))
|
||||||
|
|
||||||
|
@ -678,7 +697,7 @@ class crm_lead(format_address, osv.osv):
|
||||||
'phone': customer and customer.phone or lead.phone,
|
'phone': customer and customer.phone or lead.phone,
|
||||||
}
|
}
|
||||||
if not lead.stage_id or lead.stage_id.type=='lead':
|
if not lead.stage_id or lead.stage_id.type=='lead':
|
||||||
val['stage_id'] = self.stage_find(cr, uid, [lead], section_id, [('sequence', '=', '1'), ('type', 'in', ('opportunity','both'))], context=context)
|
val['stage_id'] = self.stage_find(cr, uid, [lead], section_id, [('type', 'in', ('opportunity', 'both'))], context=context)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
|
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
|
||||||
|
@ -688,7 +707,7 @@ class crm_lead(format_address, osv.osv):
|
||||||
customer = partner.browse(cr, uid, partner_id, context=context)
|
customer = partner.browse(cr, uid, partner_id, context=context)
|
||||||
for lead in self.browse(cr, uid, ids, context=context):
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
# TDE: was if lead.state in ('done', 'cancel'):
|
# TDE: was if lead.state in ('done', 'cancel'):
|
||||||
if (lead.probability == '100') or (lead.probability == '0' and lead.stage_id.sequence != '1'):
|
if lead.probability == 100 or (lead.probability == 0 and lead.stage_id.fold):
|
||||||
continue
|
continue
|
||||||
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
|
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
|
||||||
self.write(cr, uid, [lead.id], vals, context=context)
|
self.write(cr, uid, [lead.id], vals, context=context)
|
||||||
|
@ -818,9 +837,11 @@ class crm_lead(format_address, osv.osv):
|
||||||
model_data = self.pool.get('ir.model.data')
|
model_data = self.pool.get('ir.model.data')
|
||||||
phonecall_dict = {}
|
phonecall_dict = {}
|
||||||
if not categ_id:
|
if not categ_id:
|
||||||
|
try:
|
||||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||||
if res_id:
|
|
||||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
for lead in self.browse(cr, uid, ids, context=context):
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
if not section_id:
|
if not section_id:
|
||||||
section_id = lead.section_id and lead.section_id.id or False
|
section_id = lead.section_id and lead.section_id.id or False
|
||||||
|
@ -927,6 +948,23 @@ class crm_lead(format_address, osv.osv):
|
||||||
vals.update(onchange_stage_values)
|
vals.update(onchange_stage_values)
|
||||||
return super(crm_lead, self).write(cr, uid, ids, vals, context=context)
|
return super(crm_lead, self).write(cr, uid, ids, vals, context=context)
|
||||||
|
|
||||||
|
def copy(self, cr, uid, id, default=None, context=None):
|
||||||
|
if not default:
|
||||||
|
default = {}
|
||||||
|
if not context:
|
||||||
|
context = {}
|
||||||
|
lead = self.browse(cr, uid, id, context=context)
|
||||||
|
local_context = dict(context)
|
||||||
|
local_context.setdefault('default_type', lead.type)
|
||||||
|
local_context.setdefault('default_section_id', lead.section_id)
|
||||||
|
if lead.type == 'opportunity':
|
||||||
|
default['date_open'] = fields.datetime.now()
|
||||||
|
else:
|
||||||
|
default['date_open'] = False
|
||||||
|
default['date_closed'] = False
|
||||||
|
default['stage_id'] = self._get_default_stage_id(cr, uid, local_context)
|
||||||
|
return super(crm_lead, self).copy(cr, uid, id, default, context=context)
|
||||||
|
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
# Mail Gateway
|
# Mail Gateway
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
<record model="crm.case.stage" id="stage_lead6">
|
<record model="crm.case.stage" id="stage_lead6">
|
||||||
<field name="name">Won</field>
|
<field name="name">Won</field>
|
||||||
<field name="case_default">1</field>
|
<field name="case_default">1</field>
|
||||||
|
<field name="fold">1</field>
|
||||||
<field name="probability">100</field>
|
<field name="probability">100</field>
|
||||||
<field name="on_change">1</field>
|
<field name="on_change">1</field>
|
||||||
<field name="sequence">70</field>
|
<field name="sequence">70</field>
|
||||||
|
@ -203,7 +204,7 @@
|
||||||
<field name="model_id" ref="crm.model_crm_lead"/>
|
<field name="model_id" ref="crm.model_crm_lead"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
<field name="partner_to">${object.partner_id != False and object.partner_id.id}</field>
|
<field name="partner_to">${object.partner_id != False and object.partner_id.id}</field>
|
||||||
<field name="email_to">${not object.partner_id and object.email_from}</field>
|
<field name="email_to">${(not object.partner_id and object.email_from)|safe}</field>
|
||||||
<field name="body_html"></field>
|
<field name="body_html"></field>
|
||||||
</record>
|
</record>
|
||||||
<record id="email_template_opportunity_reminder_mail" model="email.template">
|
<record id="email_template_opportunity_reminder_mail" model="email.template">
|
||||||
|
@ -211,7 +212,7 @@
|
||||||
<field name="model_id" ref="crm.model_crm_lead"/>
|
<field name="model_id" ref="crm.model_crm_lead"/>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
<field name="email_from">admin@example.com</field>
|
<field name="email_from">admin@example.com</field>
|
||||||
<field name="email_to">${object.user_id != False and object.user_id.email}</field>
|
<field name="email_to">${(object.user_id != False and object.user_id.email)|safe}</field>
|
||||||
<field name="subject">Reminder on Lead: ${object.id} from ${object.partner_id != False and object.partner_id.name or object.contact_name}</field>
|
<field name="subject">Reminder on Lead: ${object.id} from ${object.partner_id != False and object.partner_id.name or object.contact_name}</field>
|
||||||
<field name="body_html"><![CDATA[<p>This opportunity did not have any activity since at least 5 days. Here are some details:</p>
|
<field name="body_html"><![CDATA[<p>This opportunity did not have any activity since at least 5 days. Here are some details:</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -323,7 +323,7 @@
|
||||||
<field name="model">crm.lead</field>
|
<field name="model">crm.lead</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="Search Leads">
|
<search string="Search Leads">
|
||||||
<field name="name" string="Lead / Customer" filter_domain="['|','|',('partner_name','ilike',self),('email_from','ilike',self),('name','ilike',self)]"/>
|
<field name="name" string="Lead / Customer" filter_domain="['|','|','|',('partner_name','ilike',self),('email_from','ilike',self),('contact_name','ilike',self),('name','ilike',self)]"/>
|
||||||
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
|
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
|
||||||
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
|
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
|
||||||
<field name="user_id"/>
|
<field name="user_id"/>
|
||||||
|
@ -334,14 +334,14 @@
|
||||||
<filter string="Unassigned" name="unassigned"
|
<filter string="Unassigned" name="unassigned"
|
||||||
domain="[('user_id','=', False)]"
|
domain="[('user_id','=', False)]"
|
||||||
help="No salesperson"/>
|
help="No salesperson"/>
|
||||||
<filter string="Assigned to Me"
|
<filter string="My Leads"
|
||||||
domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
|
domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
|
||||||
help="Leads that are assigned to me"/>
|
help="Leads that are assigned to me"/>
|
||||||
<filter string="Assigned to My Team(s)" groups="base.group_multi_salesteams"
|
<filter string="My Team(s)" groups="base.group_multi_salesteams"
|
||||||
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
|
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
|
||||||
help="Leads that are assigned to any sales teams I am member of"/>
|
help="Leads that are assigned to any sales teams I am member of"/>
|
||||||
<filter string="Dead" name="dead"
|
<filter string="Dead" name="dead"
|
||||||
domain="[('probability', '=', '0'), ('stage_id.sequence', '!=', 1)]"/>
|
domain="[('probability', '=', '0'), ('stage_id.fold', '=', True)]"/>
|
||||||
<separator />
|
<separator />
|
||||||
<filter string="Available for mass mailing"
|
<filter string="Available for mass mailing"
|
||||||
name='not_opt_out' domain="[('opt_out', '=', False)]"
|
name='not_opt_out' domain="[('opt_out', '=', False)]"
|
||||||
|
@ -379,10 +379,12 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Opportunities" version="7.0">
|
<form string="Opportunities" version="7.0">
|
||||||
<header>
|
<header>
|
||||||
|
<!-- :deprecated: this button will be removed from the view with OpenERP v8 -->
|
||||||
<button name="case_mark_won" string="Mark Won" type="object" class="oe_highlight"
|
<button name="case_mark_won" string="Mark Won" type="object" class="oe_highlight"
|
||||||
attrs="{'invisible': [('probability', '=', 100)]}"/>
|
invisible="True"/>
|
||||||
|
<!-- :deprecated: this button will be removed from the view with OpenERP v8 -->
|
||||||
<button name="case_mark_lost" string="Mark Lost" type="object" class="oe_highlight"
|
<button name="case_mark_lost" string="Mark Lost" type="object" class="oe_highlight"
|
||||||
attrs="{'invisible': ['|', ('probability', '=', 0), ('probability', '=', 100)]}"/>
|
invisible="True"/>
|
||||||
<field name="stage_id" widget="statusbar" clickable="True"
|
<field name="stage_id" widget="statusbar" clickable="True"
|
||||||
domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
|
domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
|
||||||
</header>
|
</header>
|
||||||
|
@ -550,18 +552,16 @@
|
||||||
<field name="stage_id" domain="[]"/>
|
<field name="stage_id" domain="[]"/>
|
||||||
<field name="probability"/>
|
<field name="probability"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="New" name="new"
|
|
||||||
domain="[('probability', '=', 0), ('stage_id.sequence', '=', 1)]"/>
|
|
||||||
<filter string="Won" name="won"
|
<filter string="Won" name="won"
|
||||||
domain="[('probability', '=', 100), ('stage_id.on_change', '=', 1)]"/>
|
domain="[('probability', '=', 100), ('stage_id.fold', '=', True)]"/>
|
||||||
<filter string="Lost" name="lost"
|
<filter string="Lost" name="lost"
|
||||||
domain="[('probability', '=', 0), ('stage_id.sequence', '!=', 1)]"/>
|
domain="[('probability', '=', 0), ('stage_id.fold', '=', True)]"/>
|
||||||
<filter string="Unassigned" name="unassigned"
|
<filter string="Unassigned" name="unassigned"
|
||||||
domain="[('user_id','=', False)]" help="No salesperson"/>
|
domain="[('user_id','=', False)]" help="No salesperson"/>
|
||||||
<filter string="My Opportunities" name="assigned_to_me"
|
<filter string="My Opportunities" name="assigned_to_me"
|
||||||
domain="[('user_id', '=', uid)]" context="{'invisible_section': False}"
|
domain="[('user_id', '=', uid)]" context="{'invisible_section': False}"
|
||||||
help="Opportunities that are assigned to me"/>
|
help="Opportunities that are assigned to me"/>
|
||||||
<filter string="Assigned to My Team(s)"
|
<filter string="My Team(s)"
|
||||||
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
|
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
|
||||||
help="Opportunities that are assigned to any sales teams I am member of"/>
|
help="Opportunities that are assigned to any sales teams I am member of"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
|
@ -600,7 +600,7 @@
|
||||||
id="crm.action_lead_mass_mail"
|
id="crm.action_lead_mass_mail"
|
||||||
context="{
|
context="{
|
||||||
'default_composition_mode': 'mass_mail',
|
'default_composition_mode': 'mass_mail',
|
||||||
'default_email_to':'{$object.email or \'\'}',
|
'default_email_to':'{($object.email or \'\')|safe}',
|
||||||
'default_use_template': True,
|
'default_use_template': True,
|
||||||
'default_template_id': ref('crm.email_template_opportunity_mail'),
|
'default_template_id': ref('crm.email_template_opportunity_mail'),
|
||||||
}"
|
}"
|
||||||
|
|
|
@ -117,9 +117,11 @@ class crm_phonecall(osv.osv):
|
||||||
model_data = self.pool.get('ir.model.data')
|
model_data = self.pool.get('ir.model.data')
|
||||||
phonecall_dict = {}
|
phonecall_dict = {}
|
||||||
if not categ_id:
|
if not categ_id:
|
||||||
|
try:
|
||||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||||
if res_id:
|
|
||||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
for call in self.browse(cr, uid, ids, context=context):
|
for call in self.browse(cr, uid, ids, context=context):
|
||||||
if not section_id:
|
if not section_id:
|
||||||
section_id = call.section_id and call.section_id.id or False
|
section_id = call.section_id and call.section_id.id or False
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="partner_id"
|
<field name="partner_id"
|
||||||
on_change="onchange_partner_id(partner_id)"/>
|
on_change="on_change_partner_id(partner_id)"/>
|
||||||
<field name="partner_phone"
|
<field name="partner_phone"
|
||||||
invisible="1"/>
|
invisible="1"/>
|
||||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||||
|
|
|
@ -93,14 +93,19 @@
|
||||||
<field name="priority" eval="1"/>
|
<field name="priority" eval="1"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="Stage" version="7.0">
|
<form string="Stage" version="7.0">
|
||||||
<group col="4">
|
<group>
|
||||||
|
<group>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="probability"/>
|
|
||||||
<field name="type"/>
|
|
||||||
<field name="on_change"/>
|
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name="case_default" groups="base.group_multi_salesteams"/>
|
<field name="type"/>
|
||||||
|
<field name="probability"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
<field name="fold"/>
|
<field name="fold"/>
|
||||||
|
<field name="on_change"/>
|
||||||
|
<field name="case_default" groups="base.group_multi_salesteams"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
<separator string="Requirements"/>
|
<separator string="Requirements"/>
|
||||||
<field name="requirements" nolabel="1"/>
|
<field name="requirements" nolabel="1"/>
|
||||||
|
|
|
@ -59,11 +59,11 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
||||||
|
|
||||||
if partner_id:
|
if partner_id:
|
||||||
# Search for opportunities that have the same partner and that arent done or cancelled
|
# Search for opportunities that have the same partner and that arent done or cancelled
|
||||||
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('probability', '<', '100')])
|
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), '|', ('probability', '=', False), ('probability', '<', '100')])
|
||||||
for id in ids:
|
for id in ids:
|
||||||
tomerge.add(id)
|
tomerge.add(id)
|
||||||
if email:
|
if email:
|
||||||
ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), ('probability', '<', '100')])
|
ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), '|', ('probability', '=', False), ('probability', '<', '100')])
|
||||||
for id in ids:
|
for id in ids:
|
||||||
tomerge.add(id)
|
tomerge.add(id)
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,11 @@ class crm_opportunity2phonecall(osv.osv_memory):
|
||||||
opp_obj = self.pool.get('crm.lead')
|
opp_obj = self.pool.get('crm.lead')
|
||||||
categ_id = False
|
categ_id = False
|
||||||
data_obj = self.pool.get('ir.model.data')
|
data_obj = self.pool.get('ir.model.data')
|
||||||
|
try:
|
||||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||||
if res_id:
|
|
||||||
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
record_ids = context and context.get('active_ids', []) or []
|
record_ids = context and context.get('active_ids', []) or []
|
||||||
res = {}
|
res = {}
|
||||||
|
|
|
@ -78,9 +78,11 @@ class crm_phonecall2phonecall(osv.osv_memory):
|
||||||
|
|
||||||
categ_id = False
|
categ_id = False
|
||||||
data_obj = self.pool.get('ir.model.data')
|
data_obj = self.pool.get('ir.model.data')
|
||||||
|
try:
|
||||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||||
if res_id:
|
|
||||||
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
if 'name' in fields:
|
if 'name' in fields:
|
||||||
res.update({'name': phonecall.name})
|
res.update({'name': phonecall.name})
|
||||||
|
|
|
@ -173,7 +173,8 @@ class crm_claim(osv.osv):
|
||||||
through message_process.
|
through message_process.
|
||||||
This override updates the document according to the email.
|
This override updates the document according to the email.
|
||||||
"""
|
"""
|
||||||
if custom_values is None: custom_values = {}
|
if custom_values is None:
|
||||||
|
custom_values = {}
|
||||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||||
defaults = {
|
defaults = {
|
||||||
'name': msg.get('subject') or _("No Subject"),
|
'name': msg.get('subject') or _("No Subject"),
|
||||||
|
@ -185,33 +186,7 @@ class crm_claim(osv.osv):
|
||||||
if msg.get('priority'):
|
if msg.get('priority'):
|
||||||
defaults['priority'] = msg.get('priority')
|
defaults['priority'] = msg.get('priority')
|
||||||
defaults.update(custom_values)
|
defaults.update(custom_values)
|
||||||
return super(crm_claim,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
return super(crm_claim, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||||
|
|
||||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
|
||||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
|
||||||
through message_process.
|
|
||||||
This method updates the document according to the email.
|
|
||||||
"""
|
|
||||||
if isinstance(ids, (str, int, long)):
|
|
||||||
ids = [ids]
|
|
||||||
if update_vals is None: update_vals = {}
|
|
||||||
|
|
||||||
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
|
|
||||||
update_vals['priority'] = msg.get('priority')
|
|
||||||
|
|
||||||
maps = {
|
|
||||||
'cost':'planned_cost',
|
|
||||||
'revenue': 'planned_revenue',
|
|
||||||
'probability':'probability'
|
|
||||||
}
|
|
||||||
for line in msg['body'].split('\n'):
|
|
||||||
line = line.strip()
|
|
||||||
res = tools.command_re.match(line)
|
|
||||||
if res and maps.get(res.group(1).lower()):
|
|
||||||
key = maps.get(res.group(1).lower())
|
|
||||||
update_vals[key] = res.group(2).lower()
|
|
||||||
|
|
||||||
return super(crm_claim,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
|
||||||
|
|
||||||
class res_partner(osv.osv):
|
class res_partner(osv.osv):
|
||||||
_inherit = 'res.partner'
|
_inherit = 'res.partner'
|
||||||
|
|
|
@ -127,7 +127,8 @@ class crm_helpdesk(osv.osv):
|
||||||
through message_process.
|
through message_process.
|
||||||
This override updates the document according to the email.
|
This override updates the document according to the email.
|
||||||
"""
|
"""
|
||||||
if custom_values is None: custom_values = {}
|
if custom_values is None:
|
||||||
|
custom_values = {}
|
||||||
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
desc = html2plaintext(msg.get('body')) if msg.get('body') else ''
|
||||||
defaults = {
|
defaults = {
|
||||||
'name': msg.get('subject') or _("No Subject"),
|
'name': msg.get('subject') or _("No Subject"),
|
||||||
|
@ -138,32 +139,6 @@ class crm_helpdesk(osv.osv):
|
||||||
'partner_id': msg.get('author_id', False),
|
'partner_id': msg.get('author_id', False),
|
||||||
}
|
}
|
||||||
defaults.update(custom_values)
|
defaults.update(custom_values)
|
||||||
return super(crm_helpdesk,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
return super(crm_helpdesk, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||||
|
|
||||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
|
||||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
|
||||||
through message_process.
|
|
||||||
This method updates the document according to the email.
|
|
||||||
"""
|
|
||||||
if isinstance(ids, (str, int, long)):
|
|
||||||
ids = [ids]
|
|
||||||
if update_vals is None: update_vals = {}
|
|
||||||
|
|
||||||
if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
|
|
||||||
update_vals['priority'] = msg.get('priority')
|
|
||||||
|
|
||||||
maps = {
|
|
||||||
'cost':'planned_cost',
|
|
||||||
'revenue': 'planned_revenue',
|
|
||||||
'probability':'probability'
|
|
||||||
}
|
|
||||||
for line in msg['body'].split('\n'):
|
|
||||||
line = line.strip()
|
|
||||||
res = tools.command_re.match(line)
|
|
||||||
if res and maps.get(res.group(1).lower()):
|
|
||||||
key = maps.get(res.group(1).lower())
|
|
||||||
update_vals[key] = res.group(2).lower()
|
|
||||||
|
|
||||||
return super(crm_helpdesk,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -21,20 +21,17 @@
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Partners Geo-Localization',
|
'name': 'CRM Geolocation',
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'category': 'Customer Relationship Management',
|
'category': 'Customer Relationship Management',
|
||||||
'description': """
|
'description': """
|
||||||
This is the module used by OpenERP SA to redirect customers to its partners, based on geolocalization.
|
This is the module used by OpenERP SA to redirect customers to its partners, based on geolocation.
|
||||||
======================================================================================================
|
======================================================================================================
|
||||||
|
|
||||||
You can geolocalize your opportunities by using this module.
|
This modules lets you geolocate Leads, Opportunities and Partners based on their address.
|
||||||
|
|
||||||
Use geolocalization when assigning opportunities to partners.
|
Once the coordinates of the Lead/Opportunity is known, they can be automatically assigned
|
||||||
Determine the GPS coordinates according to the address of the partner.
|
to an appropriate local partner, based on the distance and the weight that was assigned to the partner.
|
||||||
|
|
||||||
The most appropriate partner can be assigned.
|
|
||||||
You can also use the geolocalization without using the GPS coordinates.
|
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'depends': ['crm', 'account', 'portal'],
|
'depends': ['crm', 'account', 'portal'],
|
||||||
|
|
|
@ -42,3 +42,17 @@ class crm_lead(osv.osv):
|
||||||
|
|
||||||
def case_disinterested(self, cr, uid, ids, context=None):
|
def case_disinterested(self, cr, uid, ids, context=None):
|
||||||
return self.get_interested_action(cr, uid, False, context=context)
|
return self.get_interested_action(cr, uid, False, context=context)
|
||||||
|
|
||||||
|
def assign_salesman_of_assigned_partner(self, cr, uid, ids, context=None):
|
||||||
|
salesmans_leads = {}
|
||||||
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
|
if (lead.stage_id.probability > 0 and lead.stage_id.probability < 100) or lead.stage_id.sequence == 1:
|
||||||
|
if lead.partner_assigned_id and lead.partner_assigned_id.user_id and lead.partner_assigned_id.user_id != lead.user_id:
|
||||||
|
salesman_id = lead.partner_assigned_id.user_id.id
|
||||||
|
if salesmans_leads.get(salesman_id):
|
||||||
|
salesmans_leads[salesman_id].append(lead.id)
|
||||||
|
else:
|
||||||
|
salesmans_leads[salesman_id] = [lead.id]
|
||||||
|
for salesman_id, lead_ids in salesmans_leads.items():
|
||||||
|
salesteam_id = self.on_change_user(cr, uid, lead_ids, salesman_id, context=None)['value'].get('section_id')
|
||||||
|
self.write(cr, uid, lead_ids, {'user_id': salesman_id, 'section_id': salesteam_id}, context=context)
|
||||||
|
|
|
@ -65,6 +65,9 @@
|
||||||
domain="[]" context="{'group_by':'date_assign'}"/>
|
domain="[]" context="{'group_by':'date_assign'}"/>
|
||||||
|
|
||||||
</filter>
|
</filter>
|
||||||
|
<filter string="My Team(s)" position="after">
|
||||||
|
<filter string="My Assigned Partners" domain="[('partner_assigned_id.user_id', '=', uid)]"/>
|
||||||
|
</filter>
|
||||||
<field name="partner_id" position="after">
|
<field name="partner_id" position="after">
|
||||||
<field name="partner_assigned_id"/>
|
<field name="partner_assigned_id"/>
|
||||||
</field>
|
</field>
|
||||||
|
@ -131,11 +134,40 @@
|
||||||
<filter string="Team" position="after">
|
<filter string="Team" position="after">
|
||||||
<filter string="Assigned Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_assigned_id'}"/>
|
<filter string="Assigned Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_assigned_id'}"/>
|
||||||
</filter>
|
</filter>
|
||||||
|
<filter string="My Team(s)" position="after">
|
||||||
|
<filter string="My Assigned Partners" domain="[('partner_assigned_id.user_id', '=', uid)]"/>
|
||||||
|
</filter>
|
||||||
<field name="partner_id" position="after">
|
<field name="partner_id" position="after">
|
||||||
<field name="partner_assigned_id"/>
|
<field name="partner_assigned_id"/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="action_assign_salesman_according_assigned_partner" model="ir.actions.server">
|
||||||
|
<field name="name">Assign salesman of assigned partner</field>
|
||||||
|
<field name="model_id" ref="model_crm_lead"/>
|
||||||
|
<field name="state">code</field>
|
||||||
|
<field name="code">
|
||||||
|
if context.get('active_model') == 'crm.lead':
|
||||||
|
ids = []
|
||||||
|
if context.get('active_domain'):
|
||||||
|
ids = self.search(cr, uid, context['active_domain'], context=context)
|
||||||
|
elif context.get('active_ids'):
|
||||||
|
ids = context['active_ids']
|
||||||
|
if ids:
|
||||||
|
self.assign_salesman_of_assigned_partner(cr, uid, ids, context=context)
|
||||||
|
</field>
|
||||||
|
<field name="groups_id" eval="[(4,ref('base.group_sale_manager'))]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.values" id="ir_assign_salesman_according_assigned_partner">
|
||||||
|
<field name="model_id" ref="model_crm_lead" />
|
||||||
|
<field name="name">Assign salesman of assigned partner</field>
|
||||||
|
<field name="key2">client_action_multi</field>
|
||||||
|
<field eval="'ir.actions.server,%d'%action_assign_salesman_according_assigned_partner" name="value"/>
|
||||||
|
<field name="key">action</field>
|
||||||
|
<field name="model">crm.lead</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -179,22 +179,26 @@ class crm_lead(osv.osv):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
|
def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
|
||||||
|
if latitude and longitude:
|
||||||
|
self.write(cr, uid, ids, {
|
||||||
|
'partner_latitude': latitude,
|
||||||
|
'partner_longitude': longitude
|
||||||
|
}, context=context)
|
||||||
|
return True
|
||||||
# Don't pass context to browse()! We need country name in english below
|
# Don't pass context to browse()! We need country name in english below
|
||||||
for lead in self.browse(cr, uid, ids):
|
for lead in self.browse(cr, uid, ids):
|
||||||
if not lead.country_id:
|
if lead.partner_latitude and lead.partner_longitude:
|
||||||
continue
|
continue
|
||||||
|
if lead.country_id:
|
||||||
result = geo_find(geo_query_address(street=lead.street,
|
result = geo_find(geo_query_address(street=lead.street,
|
||||||
zip=lead.zip,
|
zip=lead.zip,
|
||||||
city=lead.city,
|
city=lead.city,
|
||||||
state=lead.state_id.name,
|
state=lead.state_id.name,
|
||||||
country=lead.country_id.name))
|
country=lead.country_id.name))
|
||||||
if not latitude and result:
|
if result:
|
||||||
latitude = result[0]
|
|
||||||
if not longitude and result:
|
|
||||||
longitude = result[1]
|
|
||||||
self.write(cr, uid, [lead.id], {
|
self.write(cr, uid, [lead.id], {
|
||||||
'partner_latitude': latitude,
|
'partner_latitude': result[0],
|
||||||
'partner_longitude': longitude
|
'partner_longitude': result[1]
|
||||||
}, context=context)
|
}, context=context)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@
|
||||||
<record model="crm.case.stage" id="stage_portal_lead_assigned">
|
<record model="crm.case.stage" id="stage_portal_lead_assigned">
|
||||||
<field name="name">Assigned</field>
|
<field name="name">Assigned</field>
|
||||||
<field eval="1" name="case_default"/>
|
<field eval="1" name="case_default"/>
|
||||||
<field eval="0" name="probability"/>
|
<field eval="10" name="probability"/>
|
||||||
<field eval="12" name="sequence"/>
|
<field eval="12" name="sequence"/>
|
||||||
<field name="type">lead</field>
|
<field name="type">lead</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="crm.case.stage" id="stage_portal_lead_recycle">
|
<record model="crm.case.stage" id="stage_portal_lead_recycle">
|
||||||
<field name="name">To Recycle</field>
|
<field name="name">To Recycle</field>
|
||||||
<field eval="1" name="case_default"/>
|
<field eval="1" name="case_default"/>
|
||||||
<field eval="0" name="probability"/>
|
<field eval="5" name="probability"/>
|
||||||
<field eval="11" name="sequence"/>
|
<field eval="11" name="sequence"/>
|
||||||
<field name="type">lead</field>
|
<field name="type">lead</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
<field name="name">Lead Mass Mail</field>
|
<field name="name">Lead Mass Mail</field>
|
||||||
<field name="model_id" model="ir.model" search="[('name', '=', 'crm.lead.forward.to.partner')]"></field>
|
<field name="model_id" model="ir.model" search="[('name', '=', 'crm.lead.forward.to.partner')]"></field>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field name="auto_delete" eval="True"/>
|
||||||
<field name="email_to">${ctx['partner_id'].email}</field>
|
<field name="email_to">${ctx['partner_id'].email|safe}</field>
|
||||||
<field name="email_from">${user.email or ''}</field>
|
<field name="email_from">${(user.email or '')|safe}</field>
|
||||||
<field name="subject">Fwd: Lead: ${ctx['partner_id'].name}</field>
|
<field name="subject">Fwd: Lead: ${ctx['partner_id'].name}</field>
|
||||||
<field name="body_html"><![CDATA[
|
<field name="body_html"><![CDATA[
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
% for lead in ctx['partner_leads']:
|
% for lead in ctx['partner_leads']:
|
||||||
<li><a href="${lead.lead_link}">${lead.lead_id.name or 'Subject Undefined'}</a>, ${lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''} </li></br>
|
<li><a href="${lead.lead_link}">${lead.lead_id.name or 'Subject Undefined'}</a>, ${lead.lead_id.partner_name or lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''} </li></br>
|
||||||
% endfor
|
% endfor
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,9 @@ class stock_move(osv.osv):
|
||||||
# Redefinition of the new fields in order to update the model stock.picking.out in the orm
|
# Redefinition of the new fields in order to update the model stock.picking.out in the orm
|
||||||
# FIXME: this is a temporary workaround because of a framework bug (ref: lp996816). It should be removed as soon as
|
# FIXME: this is a temporary workaround because of a framework bug (ref: lp996816). It should be removed as soon as
|
||||||
# the bug is fixed
|
# the bug is fixed
|
||||||
|
|
||||||
|
# TODO in trunk: Remove the duplication below using a mixin class!
|
||||||
|
|
||||||
class stock_picking_out(osv.osv):
|
class stock_picking_out(osv.osv):
|
||||||
_inherit = 'stock.picking.out'
|
_inherit = 'stock.picking.out'
|
||||||
|
|
||||||
|
@ -212,6 +215,7 @@ class stock_picking_out(osv.osv):
|
||||||
}),
|
}),
|
||||||
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
|
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
|
||||||
'number_of_packages': fields.integer('Number of Packages'),
|
'number_of_packages': fields.integer('Number of Packages'),
|
||||||
|
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of measurement for Weight",),
|
||||||
}
|
}
|
||||||
|
|
||||||
class stock_picking_in(osv.osv):
|
class stock_picking_in(osv.osv):
|
||||||
|
@ -224,6 +228,8 @@ class stock_picking_in(osv.osv):
|
||||||
return self.pool.get('stock.picking')._get_picking_line(cr, uid, ids, context=context)
|
return self.pool.get('stock.picking')._get_picking_line(cr, uid, ids, context=context)
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
|
'carrier_id':fields.many2one("delivery.carrier","Carrier"),
|
||||||
|
'volume': fields.float('Volume'),
|
||||||
'weight': fields.function(_cal_weight, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight',
|
'weight': fields.function(_cal_weight, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight',
|
||||||
store={
|
store={
|
||||||
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
|
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
|
||||||
|
@ -234,6 +240,9 @@ class stock_picking_in(osv.osv):
|
||||||
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
|
'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20),
|
||||||
'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20),
|
'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20),
|
||||||
}),
|
}),
|
||||||
|
'carrier_tracking_ref': fields.char('Carrier Tracking Ref', size=32),
|
||||||
|
'number_of_packages': fields.integer('Number of Packages'),
|
||||||
|
'weight_uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True,readonly="1",help="Unit of measurement for Weight",),
|
||||||
}
|
}
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -15,3 +15,4 @@ access_report_document_user_group_document_manager,report.document.user document
|
||||||
access_report_document_file_group_document_manager,report.document.file document manager,model_report_document_file,base.group_system,1,0,0,0
|
access_report_document_file_group_document_manager,report.document.file document manager,model_report_document_file,base.group_system,1,0,0,0
|
||||||
access_report_document_file_group_document,report.document.file document manager,model_report_document_file,base.group_document_user,1,0,0,0
|
access_report_document_file_group_document,report.document.file document manager,model_report_document_file,base.group_document_user,1,0,0,0
|
||||||
access_report_document_user_knowledgeuser,report.document.user knowledgeuser,document.model_report_document_user,base.group_document_user,1,0,0,0
|
access_report_document_user_knowledgeuser,report.document.user knowledgeuser,document.model_report_document_user,base.group_document_user,1,0,0,0
|
||||||
|
access_document_storage,access_document_storage,model_document_storage,base.group_system,1,1,1,1
|
||||||
|
|
|
|
@ -9,7 +9,7 @@ openerp.document = function (instance) {
|
||||||
on_attachments_loaded: function(attachments) {
|
on_attachments_loaded: function(attachments) {
|
||||||
//to display number in name if more then one attachment which has same name.
|
//to display number in name if more then one attachment which has same name.
|
||||||
var self = this;
|
var self = this;
|
||||||
_.chain(attachments.reverse())
|
_.chain(attachments)
|
||||||
.groupBy(function(attachment) { return attachment.name})
|
.groupBy(function(attachment) { return attachment.name})
|
||||||
.each(function(attachment){
|
.each(function(attachment){
|
||||||
if(attachment.length > 1)
|
if(attachment.length > 1)
|
||||||
|
|
|
@ -34,6 +34,9 @@ def start_server():
|
||||||
if openerp.multi_process:
|
if openerp.multi_process:
|
||||||
_logger.info("FTP disabled in multiprocess mode")
|
_logger.info("FTP disabled in multiprocess mode")
|
||||||
return
|
return
|
||||||
|
if openerp.evented:
|
||||||
|
_logger.info("FTP disabled in evented mode")
|
||||||
|
return
|
||||||
HOST = config.get('ftp_server_host', '127.0.0.1')
|
HOST = config.get('ftp_server_host', '127.0.0.1')
|
||||||
PORT = int(config.get('ftp_server_port', '8021'))
|
PORT = int(config.get('ftp_server_port', '8021'))
|
||||||
PASSIVE_PORTS = None
|
PASSIVE_PORTS = None
|
||||||
|
|
|
@ -378,7 +378,7 @@ class email_template(osv.osv):
|
||||||
# Ensure report is rendered using template's language
|
# Ensure report is rendered using template's language
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
if template.lang:
|
if template.lang:
|
||||||
ctx['lang'] = self.render_template_batch(cr, uid, template.lang, template.model, res_id, context) # take 0 ?
|
ctx['lang'] = self.render_template_batch(cr, uid, template.lang, template.model, [res_id], context)[res_id] # take 0 ?
|
||||||
result, format = openerp.report.render_report(cr, uid, [res_id], report_service, {'model': template.model}, ctx)
|
result, format = openerp.report.render_report(cr, uid, [res_id], report_service, {'model': template.model}, ctx)
|
||||||
result = base64.b64encode(result)
|
result = base64.b64encode(result)
|
||||||
if not report_name:
|
if not report_name:
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
<record id="confirmation_event" model="email.template">
|
<record id="confirmation_event" model="email.template">
|
||||||
<field name="name">Confirmation of the Event</field>
|
<field name="name">Confirmation of the Event</field>
|
||||||
<field name="model_id" ref="event.model_event_registration"/>
|
<field name="model_id" ref="event.model_event_registration"/>
|
||||||
<field name="email_from" >${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'}</field>
|
<field name="email_from" >${(object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com')|safe}</field>
|
||||||
<field name="email_to" >${object.email}</field>
|
<field name="email_to" >${object.email|safe}</field>
|
||||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||||
<field name="body_html"><![CDATA[
|
<field name="body_html"><![CDATA[
|
||||||
<p>Hello ${object.name},</p>
|
<p>Hello ${object.name},</p>
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
<record id="confirmation_registration" model="email.template">
|
<record id="confirmation_registration" model="email.template">
|
||||||
<field name="name">Confirmation of the Registration</field>
|
<field name="name">Confirmation of the Registration</field>
|
||||||
<field name="model_id" ref="event.model_event_registration"/>
|
<field name="model_id" ref="event.model_event_registration"/>
|
||||||
<field name="email_from" >${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'}</field>
|
<field name="email_from" >${(object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com')|safe}</field>
|
||||||
<field name="email_to" >${object.email}</field>
|
<field name="email_to" >${object.email|safe}</field>
|
||||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||||
<field name="body_html"><![CDATA[
|
<field name="body_html"><![CDATA[
|
||||||
<p>Hello ${object.name},</p>
|
<p>Hello ${object.name},</p>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data>
|
||||||
|
<!--Users-->
|
||||||
<record id="base.user_demo" model="res.users">
|
<record id="base.user_demo" model="res.users">
|
||||||
<field name="groups_id" eval="[(4, ref('fleet.group_fleet_user'))]" />
|
<field name="groups_id" eval="[(4, ref('fleet.group_fleet_manager'))]" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="vehicle_state_inshop" model="fleet.vehicle.state">
|
<record id="vehicle_state_inshop" model="fleet.vehicle.state">
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model='ir.ui.view' id='fleet_vehicle_model_tree'>
|
<record model='ir.ui.view' id='fleet_vehicle_model_tree'>
|
||||||
<field name="name">fleet.vehicle.model.tree</field>
|
<field name="name">fleet.vehicle.model.tree</field>
|
||||||
<field name="model">fleet.vehicle.model</field>
|
<field name="model">fleet.vehicle.model</field>
|
||||||
|
@ -565,7 +566,7 @@
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<!--
|
|
||||||
<record model='ir.ui.view' id='fleet_vehicle_odometer_search'>
|
<record model='ir.ui.view' id='fleet_vehicle_odometer_search'>
|
||||||
<field name="name">fleet.vehicle.odometer.search</field>
|
<field name="name">fleet.vehicle.odometer.search</field>
|
||||||
<field name="model">fleet.vehicle.odometer</field>
|
<field name="model">fleet.vehicle.odometer</field>
|
||||||
|
@ -575,11 +576,12 @@
|
||||||
<field name="value"/>
|
<field name="value"/>
|
||||||
<field name="unit"/>
|
<field name="unit"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
|
<group expand="0" string="Group By...">
|
||||||
<filter name="groupby_vehicle" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
|
<filter name="groupby_vehicle" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
|
||||||
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
-->
|
|
||||||
|
|
||||||
<record model="ir.ui.view" id="fleet_vehicle_odometer_graph">
|
<record model="ir.ui.view" id="fleet_vehicle_odometer_graph">
|
||||||
<field name="name">fleet.vehicle.odometer.graph</field>
|
<field name="name">fleet.vehicle.odometer.graph</field>
|
||||||
|
@ -672,6 +674,23 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model='ir.ui.view' id='fleet_vehicle_log_fuel_search'>
|
||||||
|
<field name="name">fleet.vehicle.log.fuel.search</field>
|
||||||
|
<field name="model">fleet.vehicle.log.fuel</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="Vehicles Fuel Logs" >
|
||||||
|
<field name="vehicle_id" />
|
||||||
|
<field name="date"/>
|
||||||
|
<field name="purchaser_id" />
|
||||||
|
<field name="liter" />
|
||||||
|
<field name="amount" sum="Price"/>
|
||||||
|
<group expand="0" string="Group By...">
|
||||||
|
<filter name="groupby_vehicle" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
|
||||||
|
</group>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="fleet_vehicle_log_fuel_graph">
|
<record model="ir.ui.view" id="fleet_vehicle_log_fuel_graph">
|
||||||
<field name="name">fleet.vehicle.log.fuel.graph</field>
|
<field name="name">fleet.vehicle.log.fuel.graph</field>
|
||||||
<field name="model">fleet.vehicle.log.fuel</field>
|
<field name="model">fleet.vehicle.log.fuel</field>
|
||||||
|
@ -690,6 +709,7 @@
|
||||||
<field name="res_model">fleet.vehicle.log.fuel</field>
|
<field name="res_model">fleet.vehicle.log.fuel</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form,graph</field>
|
<field name="view_mode">tree,form,graph</field>
|
||||||
|
<field name="context">{"search_default_groupby_vehicle" : True}</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
<p class="oe_view_nocontent_create">
|
<p class="oe_view_nocontent_create">
|
||||||
Click to create a new fuel log.
|
Click to create a new fuel log.
|
||||||
|
|
|
@ -236,11 +236,13 @@ class hr_employee(osv.osv):
|
||||||
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
|
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
|
||||||
employee = self.browse(cr, uid, employee_id, context=context)
|
employee = self.browse(cr, uid, employee_id, context=context)
|
||||||
if employee.user_id:
|
if employee.user_id:
|
||||||
|
res_users = self.pool['res.users']
|
||||||
# send a copy to every user of the company
|
# send a copy to every user of the company
|
||||||
company_id = employee.user_id.partner_id.company_id.id
|
# TODO: post to the `Whole Company` mail.group when we'll be able to link to the employee record
|
||||||
partner_ids = self.pool.get('res.partner').search(cr, uid, [
|
_model, group_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')
|
||||||
('company_id', '=', company_id),
|
user_ids = res_users.search(cr, uid, [('company_id', '=', employee.user_id.company_id.id),
|
||||||
('user_ids', '!=', False)], context=context)
|
('groups_id', 'in', group_id)])
|
||||||
|
partner_ids = list(set(u.partner_id.id for u in res_users.browse(cr, uid, user_ids, context=context)))
|
||||||
else:
|
else:
|
||||||
partner_ids = []
|
partner_ids = []
|
||||||
self.message_post(cr, uid, [employee_id],
|
self.message_post(cr, uid, [employee_id],
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
<field name="model">hr.employee</field>
|
<field name="model">hr.employee</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="Employees">
|
<search string="Employees">
|
||||||
<field name="name" string="Employees"/>
|
<field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/>
|
||||||
<field name="department_id" />
|
<field name="department_id" />
|
||||||
<field name="category_ids" groups="base.group_hr_user"/>
|
<field name="category_ids" groups="base.group_hr_user"/>
|
||||||
<group expand="0" string="Group By...">
|
<group expand="0" string="Group By...">
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<filter icon="terp-document-new" domain="[('state','=','draft')]" string="New" help="New Expense"/>
|
<filter icon="terp-document-new" domain="[('state','=','draft')]" string="New" help="New Expense"/>
|
||||||
<filter icon="terp-camera_test" domain="[('state','=','confirm')]" string="To Approve" help="Confirmed Expenses"/>
|
<filter icon="terp-camera_test" domain="[('state','=','confirm')]" string="To Approve" help="Confirmed Expenses"/>
|
||||||
<filter icon="terp-dolar" domain="[('state','=','accepted')]" string="To Pay" help="Expenses to Invoice"/>
|
<filter icon="terp-dolar" domain="['|',('state','=','accepted'),('state','=','done')]" string="To Pay" help="Expenses to Invoice"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter domain="[('user_id', '=', uid)]" string="My Expenses"/>
|
<filter domain="[('user_id', '=', uid)]" string="My Expenses"/>
|
||||||
<field name="employee_id"/>
|
<field name="employee_id"/>
|
||||||
|
|
|
@ -145,7 +145,9 @@ class hr_holidays(osv.osv):
|
||||||
|
|
||||||
def _check_date(self, cr, uid, ids):
|
def _check_date(self, cr, uid, ids):
|
||||||
for holiday in self.browse(cr, uid, ids):
|
for holiday in self.browse(cr, uid, ids):
|
||||||
holiday_ids = self.search(cr, uid, [('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from), ('employee_id', '=', holiday.employee_id.id), ('id', '<>', holiday.id)])
|
holiday_ids = self.search(cr, uid, [('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from),
|
||||||
|
('employee_id', '=', holiday.employee_id.id), ('id', '<>', holiday.id),
|
||||||
|
('state', 'not in', ['cancel', 'refuse'])])
|
||||||
if holiday_ids:
|
if holiday_ids:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
<record model="workflow.activity" id="act_refuse"> <!-- refused -->
|
<record model="workflow.activity" id="act_refuse"> <!-- refused -->
|
||||||
<field name="wkf_id" ref="wkf_holidays" />
|
<field name="wkf_id" ref="wkf_holidays" />
|
||||||
<field name="name">refuse</field>
|
<field name="name">refuse</field>
|
||||||
|
<field name="flow_stop" eval="False"/>
|
||||||
<field name="kind">function</field>
|
<field name="kind">function</field>
|
||||||
<field name="action">holidays_refuse()</field>
|
<field name="action">holidays_refuse()</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -52,12 +52,13 @@ class hr_recruitment_stage(osv.osv):
|
||||||
'name': fields.char('Name', size=64, required=True, translate=True),
|
'name': fields.char('Name', size=64, required=True, translate=True),
|
||||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of stages."),
|
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of stages."),
|
||||||
'department_id':fields.many2one('hr.department', 'Specific to a Department', help="Stages of the recruitment process may be different per department. If this stage is common to all departments, keep this field empty."),
|
'department_id':fields.many2one('hr.department', 'Specific to a Department', help="Stages of the recruitment process may be different per department. If this stage is common to all departments, keep this field empty."),
|
||||||
'fold': fields.boolean('Hide in views if empty', help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
|
||||||
'requirements': fields.text('Requirements'),
|
'requirements': fields.text('Requirements'),
|
||||||
|
'fold': fields.boolean('Folded in Kanban View',
|
||||||
|
help='This stage is folded in the kanban view when'
|
||||||
|
'there are no records in that stage to display.'),
|
||||||
}
|
}
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'sequence': 1,
|
'sequence': 1,
|
||||||
'fold': False,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class hr_recruitment_degree(osv.osv):
|
class hr_recruitment_degree(osv.osv):
|
||||||
|
@ -82,8 +83,9 @@ class hr_applicant(osv.Model):
|
||||||
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
||||||
_track = {
|
_track = {
|
||||||
'stage_id': {
|
'stage_id': {
|
||||||
'hr_recruitment.mt_applicant_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence == 1,
|
# this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
|
||||||
'hr_recruitment.mt_applicant_stage_changed': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence != 1,
|
'hr_recruitment.mt_applicant_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence <= 1,
|
||||||
|
'hr_recruitment.mt_applicant_stage_changed': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence > 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +96,7 @@ class hr_applicant(osv.Model):
|
||||||
def _get_default_stage_id(self, cr, uid, context=None):
|
def _get_default_stage_id(self, cr, uid, context=None):
|
||||||
""" Gives default stage_id """
|
""" Gives default stage_id """
|
||||||
department_id = self._get_default_department_id(cr, uid, context=context)
|
department_id = self._get_default_department_id(cr, uid, context=context)
|
||||||
return self.stage_find(cr, uid, [], department_id, [('sequence', '=', '1')], context=context)
|
return self.stage_find(cr, uid, [], department_id, [('fold', '=', False)], context=context)
|
||||||
|
|
||||||
def _resolve_department_id_from_context(self, cr, uid, context=None):
|
def _resolve_department_id_from_context(self, cr, uid, context=None):
|
||||||
""" Returns ID of department based on the value of 'default_department_id'
|
""" Returns ID of department based on the value of 'default_department_id'
|
||||||
|
@ -241,7 +243,7 @@ class hr_applicant(osv.Model):
|
||||||
|
|
||||||
def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None):
|
def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None):
|
||||||
if not stage_id:
|
if not stage_id:
|
||||||
stage_id = self.stage_find(cr, uid, [], department_id, [('sequence', '=', '1')], context=context)
|
stage_id = self.stage_find(cr, uid, [], department_id, [('fold', '=', False)], context=context)
|
||||||
return {'value': {'stage_id': stage_id}}
|
return {'value': {'stage_id': stage_id}}
|
||||||
|
|
||||||
def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
|
def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
|
||||||
|
@ -331,7 +333,8 @@ class hr_applicant(osv.Model):
|
||||||
through message_process.
|
through message_process.
|
||||||
This override updates the document according to the email.
|
This override updates the document according to the email.
|
||||||
"""
|
"""
|
||||||
if custom_values is None: custom_values = {}
|
if custom_values is None:
|
||||||
|
custom_values = {}
|
||||||
val = msg.get('from').split('<')[0]
|
val = msg.get('from').split('<')[0]
|
||||||
defaults = {
|
defaults = {
|
||||||
'name': msg.get('subject') or _("No Subject"),
|
'name': msg.get('subject') or _("No Subject"),
|
||||||
|
@ -344,38 +347,7 @@ class hr_applicant(osv.Model):
|
||||||
if msg.get('priority'):
|
if msg.get('priority'):
|
||||||
defaults['priority'] = msg.get('priority')
|
defaults['priority'] = msg.get('priority')
|
||||||
defaults.update(custom_values)
|
defaults.update(custom_values)
|
||||||
return super(hr_applicant,self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
return super(hr_applicant, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||||
|
|
||||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
|
||||||
""" Override mail_thread message_update that is called by the mailgateway
|
|
||||||
through message_process.
|
|
||||||
This method updates the document according to the email.
|
|
||||||
"""
|
|
||||||
if isinstance(ids, (str, int, long)):
|
|
||||||
ids = [ids]
|
|
||||||
if update_vals is None:
|
|
||||||
update_vals = {}
|
|
||||||
|
|
||||||
update_vals.update({
|
|
||||||
'email_from': msg.get('from'),
|
|
||||||
'email_cc': msg.get('cc'),
|
|
||||||
})
|
|
||||||
if msg.get('priority'):
|
|
||||||
update_vals['priority'] = msg.get('priority')
|
|
||||||
|
|
||||||
maps = {
|
|
||||||
'cost': 'planned_cost',
|
|
||||||
'revenue': 'planned_revenue',
|
|
||||||
'probability': 'probability',
|
|
||||||
}
|
|
||||||
for line in msg.get('body', '').split('\n'):
|
|
||||||
line = line.strip()
|
|
||||||
res = tools.command_re.match(line)
|
|
||||||
if res and maps.get(res.group(1).lower(), False):
|
|
||||||
key = maps.get(res.group(1).lower())
|
|
||||||
update_vals[key] = res.group(2).lower()
|
|
||||||
|
|
||||||
return super(hr_applicant, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
if context is None:
|
if context is None:
|
||||||
|
|
|
@ -71,12 +71,14 @@
|
||||||
<record model="hr.recruitment.stage" id="stage_job5">
|
<record model="hr.recruitment.stage" id="stage_job5">
|
||||||
<field name="name">Contract Signed</field>
|
<field name="name">Contract Signed</field>
|
||||||
<field name="sequence">5</field>
|
<field name="sequence">5</field>
|
||||||
|
<field name="fold" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
<record model="hr.recruitment.stage" id="stage_job6">
|
<record model="hr.recruitment.stage" id="stage_job6">
|
||||||
<field name="name">Refused</field>
|
<field name="name">Refused</field>
|
||||||
<field name="sequence">6</field>
|
<field name="sequence">6</field>
|
||||||
<field name="fold" eval="True"/>
|
<field name="fold" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="survey_job_0" model="survey">
|
<record id="survey_job_0" model="survey">
|
||||||
<field name="title">Job Survey</field>
|
<field name="title">Job Survey</field>
|
||||||
<field name="max_response_limit">20</field>
|
<field name="max_response_limit">20</field>
|
||||||
|
|
|
@ -342,6 +342,7 @@
|
||||||
<field name="sequence" invisible="1"/>
|
<field name="sequence" invisible="1"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="department_id"/>
|
<field name="department_id"/>
|
||||||
|
<field name="fold"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -90,7 +90,7 @@ class hr_recruitment_report(osv.Model):
|
||||||
(sum(salary_proposed)/count(*)) as salary_prop_avg,
|
(sum(salary_proposed)/count(*)) as salary_prop_avg,
|
||||||
sum(salary_expected) as salary_exp,
|
sum(salary_expected) as salary_exp,
|
||||||
(sum(salary_expected)/count(*)) as salary_exp_avg,
|
(sum(salary_expected)/count(*)) as salary_exp_avg,
|
||||||
extract('epoch' from (s.date_closed-s.create_date))/(3600*24) as delay_close,
|
extract('epoch' from (s.write_date-s.create_date))/(3600*24) as delay_close,
|
||||||
count(*) as nbr
|
count(*) as nbr
|
||||||
from hr_applicant s
|
from hr_applicant s
|
||||||
group by
|
group by
|
||||||
|
@ -101,6 +101,7 @@ class hr_recruitment_report(osv.Model):
|
||||||
date_trunc('day',s.date_closed),
|
date_trunc('day',s.date_closed),
|
||||||
s.date_open,
|
s.date_open,
|
||||||
s.create_date,
|
s.create_date,
|
||||||
|
s.write_date,
|
||||||
s.date_closed,
|
s.date_closed,
|
||||||
s.date_last_stage_update,
|
s.date_last_stage_update,
|
||||||
s.partner_id,
|
s.partner_id,
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.actions.act_window" id="act_analytic_cost_revenue">
|
<record model="ir.actions.act_window" id="act_analytic_cost_revenue">
|
||||||
<field name="context">{'search_default_account_id': [active_id], 'default_account_id': active_id, 'search_default_group_date': 1, 'search_default_group_journal': 1}</field>
|
<field name="context">{'search_default_group_date': 1, 'search_default_group_journal': 1}</field>
|
||||||
|
<field name="domain">[('account_id','child_of', active_id)]</field>
|
||||||
<field name="name">Costs & Revenues</field>
|
<field name="name">Costs & Revenues</field>
|
||||||
<field name="res_model">account.analytic.line</field>
|
<field name="res_model">account.analytic.line</field>
|
||||||
<field name="src_model">account.analytic.account</field>
|
<field name="src_model">account.analytic.account</field>
|
||||||
|
|
|
@ -95,7 +95,7 @@ class timesheet_report(osv.osv):
|
||||||
htss.state
|
htss.state
|
||||||
from account_analytic_line as aal
|
from account_analytic_line as aal
|
||||||
left join hr_analytic_timesheet as hat ON (hat.line_id=aal.id)
|
left join hr_analytic_timesheet as hat ON (hat.line_id=aal.id)
|
||||||
left join hr_timesheet_sheet_sheet as htss ON (hat.line_id=htss.id)
|
left join hr_timesheet_sheet_sheet as htss ON (hat.sheet_id=htss.id)
|
||||||
group by
|
group by
|
||||||
aal.account_id,
|
aal.account_id,
|
||||||
aal.date,
|
aal.date,
|
||||||
|
|
|
@ -62,16 +62,12 @@
|
||||||
this.user_search_dm = new instance.web.DropMisordered();
|
this.user_search_dm = new instance.web.DropMisordered();
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function() {
|
||||||
|
var self = this;
|
||||||
this.$el.css("right", -this.$el.outerWidth());
|
this.$el.css("right", -this.$el.outerWidth());
|
||||||
$(window).scroll(_.bind(this.calc_box, this));
|
$(window).scroll(_.bind(this.calc_box, this));
|
||||||
$(window).resize(_.bind(this.calc_box, this));
|
$(window).resize(_.bind(this.calc_box, this));
|
||||||
this.calc_box();
|
this.calc_box();
|
||||||
|
|
||||||
this.on("change:current_search", this, this.search_changed);
|
this.on("change:current_search", this, this.search_changed);
|
||||||
this.search_changed();
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
return this.c_manager.start_polling().then(function() {
|
return this.c_manager.start_polling().then(function() {
|
||||||
self.c_manager.on("new_conversation", self, function(conv) {
|
self.c_manager.on("new_conversation", self, function(conv) {
|
||||||
conv.$el.droppable({
|
conv.$el.droppable({
|
||||||
|
@ -80,6 +76,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
self.search_changed();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
calc_box: function() {
|
calc_box: function() {
|
||||||
|
|
|
@ -65,6 +65,7 @@ Wizards provided by this module:
|
||||||
'account_pcmn_belgium.xml',
|
'account_pcmn_belgium.xml',
|
||||||
'account_tax_code_template.xml',
|
'account_tax_code_template.xml',
|
||||||
'account_chart_template.xml',
|
'account_chart_template.xml',
|
||||||
|
'account_chart_template.yml',
|
||||||
'account_tax_template.xml',
|
'account_tax_template.xml',
|
||||||
'wizard/l10n_be_account_vat_declaration_view.xml',
|
'wizard/l10n_be_account_vat_declaration_view.xml',
|
||||||
'wizard/l10n_be_vat_intra_view.xml',
|
'wizard/l10n_be_vat_intra_view.xml',
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
<field name="property_account_payable" ref="a_pay"/>
|
<field name="property_account_payable" ref="a_pay"/>
|
||||||
<field name="property_account_expense_categ" ref="a_expense"/>
|
<field name="property_account_expense_categ" ref="a_expense"/>
|
||||||
<field name="property_account_income_categ" ref="a_sale"/>
|
<field name="property_account_income_categ" ref="a_sale"/>
|
||||||
<field name="spoken_languages" eval="'nl_BE'"/>
|
|
||||||
<field name="currency_id" ref="base.EUR"/>
|
<field name="currency_id" ref="base.EUR"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
-
|
||||||
|
!python {model: account.chart.template}: |
|
||||||
|
if 'spoken_languages' in self._all_columns:
|
||||||
|
self.write(cr, uid, [ref('l10nbe_chart_template')], {'spoken_languages': 'nl_BE'})
|
|
@ -185,7 +185,7 @@ class l10n_be_vat_declaration(osv.osv_memory):
|
||||||
for item in cases_list:
|
for item in cases_list:
|
||||||
grid_amount_data = {
|
grid_amount_data = {
|
||||||
'code': str(int(item['code'])),
|
'code': str(int(item['code'])),
|
||||||
'amount': str(abs(item['sum_period'])),
|
'amount': '%.2f' % abs(item['sum_period']),
|
||||||
}
|
}
|
||||||
data_of_file += '\n\t\t\t<ns2:Amount GridNumber="%(code)s">%(amount)s</ns2:Amount''>' % (grid_amount_data)
|
data_of_file += '\n\t\t\t<ns2:Amount GridNumber="%(code)s">%(amount)s</ns2:Amount''>' % (grid_amount_data)
|
||||||
|
|
||||||
|
|
|
@ -177,14 +177,12 @@
|
||||||
<record model="account.account.type" id="account_type_receivable">
|
<record model="account.account.type" id="account_type_receivable">
|
||||||
<field name="name">Bilan : Debiteurs</field>
|
<field name="name">Bilan : Debiteurs</field>
|
||||||
<field name="code">receivable</field>
|
<field name="code">receivable</field>
|
||||||
<field name="partner_account" eval="True"/>
|
|
||||||
<field name="close_method">unreconciled</field>
|
<field name="close_method">unreconciled</field>
|
||||||
<field name="report_type">none</field>
|
<field name="report_type">none</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="account.account.type" id="account_type_payable">
|
<record model="account.account.type" id="account_type_payable">
|
||||||
<field name="name">Bilan : Fournisseurs</field>
|
<field name="name">Bilan : Fournisseurs</field>
|
||||||
<field name="code">payable</field>
|
<field name="code">payable</field>
|
||||||
<field name="partner_account" eval="True"/>
|
|
||||||
<field name="close_method">unreconciled</field>
|
<field name="close_method">unreconciled</field>
|
||||||
<field name="report_type">none</field>
|
<field name="report_type">none</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -11809,7 +11807,6 @@
|
||||||
<field name="property_account_income" ref="ch_3200"/>
|
<field name="property_account_income" ref="ch_3200"/>
|
||||||
<field name="property_account_income_opening" ref="ch_2990"/>
|
<field name="property_account_income_opening" ref="ch_2990"/>
|
||||||
<field name="property_account_expense_opening" ref="ch_2990"/>
|
<field name="property_account_expense_opening" ref="ch_2990"/>
|
||||||
<field name="property_reserve_and_surplus_account" ref="ch_2991"/>
|
|
||||||
<field name="code_digits" eval="0"/>
|
<field name="code_digits" eval="0"/>
|
||||||
<field name="spoken_languages" eval="'it_IT;de_DE'"/>
|
<field name="spoken_languages" eval="'it_IT;de_DE'"/>
|
||||||
<field name="currency_id" ref="base.CHF"/>
|
<field name="currency_id" ref="base.CHF"/>
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
<!-- Exentas IVA -->
|
<!-- Exentas IVA -->
|
||||||
<record id="base_assoc_sop_ex" model="account.tax.code.template">
|
<record id="base_assoc_sop_ex" model="account.tax.code.template">
|
||||||
<field name="name">Base adquisiciones exentas</field>
|
<field name="name">Base adquisiciones exentas</field>
|
||||||
<field name="company_id" model="res.company" search="[]"/>
|
|
||||||
<field name="parent_id" ref="vat_code_chart_assoc_root"/>
|
<field name="parent_id" ref="vat_code_chart_assoc_root"/>
|
||||||
<field name="code">--</field>
|
<field name="code">--</field>
|
||||||
<field name="sign">1.0</field>
|
<field name="sign">1.0</field>
|
||||||
|
@ -53,7 +52,6 @@
|
||||||
<record id="base_assoc_rep_ex" model="account.tax.code.template">
|
<record id="base_assoc_rep_ex" model="account.tax.code.template">
|
||||||
<field name="name">Base ventas exentas</field>
|
<field name="name">Base ventas exentas</field>
|
||||||
<field name="code">--</field>
|
<field name="code">--</field>
|
||||||
<field name="company_id" model="res.company" search="[]"/>
|
|
||||||
<field name="parent_id" ref="vat_code_chart_assoc_root"/>
|
<field name="parent_id" ref="vat_code_chart_assoc_root"/>
|
||||||
<field name="sign">1.0</field>
|
<field name="sign">1.0</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -219,8 +219,8 @@
|
||||||
<field name="tax_code_id" ref="tax_acq_196"/>
|
<field name="tax_code_id" ref="tax_acq_196"/>
|
||||||
<field name="tax_sign" eval="-1"/>
|
<field name="tax_sign" eval="-1"/>
|
||||||
|
|
||||||
<field name="account_collected_id" ref="pcg_445662"/>
|
<field name="account_collected_id" ref="pcg_44566"/>
|
||||||
<field name="account_paid_id" ref="pcg_445662"/>
|
<field name="account_paid_id" ref="pcg_44566"/>
|
||||||
|
|
||||||
<field name="ref_base_code_id" ref="tax_acq_196_ht"/>
|
<field name="ref_base_code_id" ref="tax_acq_196_ht"/>
|
||||||
<field name="ref_base_sign" eval="1"/>
|
<field name="ref_base_sign" eval="1"/>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base"
|
"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id/id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base"
|
||||||
1,"fix",1,1,,100,"Education Allowance For One Child","Allowance",23,"CHEAONE","hr_payroll_rule_child1","range","employee.children",
|
1,"fix",1,1,,100,"Education Allowance For One Child",hr_payroll.ALW,23,"CHEAONE","hr_payroll_rule_child1","range","employee.children",
|
||||||
2,"fix",2,10,,200,"Education Allowance For Two Child","Allowance",24,"CHEATWO","hr_payroll_rule_child1","range","employee.children",
|
2,"fix",2,10,,200,"Education Allowance For Two Child",hr_payroll.ALW,24,"CHEATWO","hr_payroll_rule_child1","range","employee.children",
|
||||||
3,"fix",1,1,,300,"Child Hostel Allowance For One Child","Allowance",26,"CHOONE","hr_payroll_rule_child2","range","employee.children",
|
3,"fix",1,1,,300,"Child Hostel Allowance For One Child",hr_payroll.ALW,26,"CHOONE","hr_payroll_rule_child2","range","employee.children",
|
||||||
4,"fix",2,10,,600,"Child Hostel Allowance For Two Child","Allowance",27,"CHOTWO","hr_payroll_rule_child2","range","employee.children",
|
4,"fix",2,10,,600,"Child Hostel Allowance For Two Child",hr_payroll.ALW,27,"CHOTWO","hr_payroll_rule_child2","range","employee.children",
|
||||||
|
|
|
|
@ -33,6 +33,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
"""
|
"""
|
||||||
_inherit = 'wizard.multi.charts.accounts'
|
_inherit = 'wizard.multi.charts.accounts'
|
||||||
|
|
||||||
|
# FIXME: in trunk, drop the force_write param entirely
|
||||||
def process_translations(self, cr, uid, langs, in_obj, in_field, in_ids, out_obj, out_ids, force_write=False, context=None):
|
def process_translations(self, cr, uid, langs, in_obj, in_field, in_ids, out_obj, out_ids, force_write=False, context=None):
|
||||||
"""
|
"""
|
||||||
This method copies translations values of templates into new Accounts/Taxes/Journals for languages selected
|
This method copies translations values of templates into new Accounts/Taxes/Journals for languages selected
|
||||||
|
@ -45,8 +46,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
:param in_ids: List of ids of source object
|
:param in_ids: List of ids of source object
|
||||||
:param out_obj: Destination object for which translation is to be copied
|
:param out_obj: Destination object for which translation is to be copied
|
||||||
:param out_ids: List of ids of destination object
|
:param out_ids: List of ids of destination object
|
||||||
:param force_write: boolean that depicts if we need to create a translation OR simply replace the actual value
|
:param force_write: Deprecated as of 7.0, do not use
|
||||||
with the translation in the uid's language by doing a write (in case it's TRUE)
|
|
||||||
:param context: usual context information. May contain the key 'lang', which is the language of the user running
|
:param context: usual context information. May contain the key 'lang', which is the language of the user running
|
||||||
the wizard, that will be used if force_write is True
|
the wizard, that will be used if force_write is True
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
for j in range(len(in_ids)):
|
for j in range(len(in_ids)):
|
||||||
in_id = in_ids[j]
|
in_id = in_ids[j]
|
||||||
if value[in_id]:
|
if value[in_id]:
|
||||||
if not force_write:
|
|
||||||
#copy Translation from Source to Destination object
|
#copy Translation from Source to Destination object
|
||||||
xlat_obj.create(cr, uid, {
|
xlat_obj.create(cr, uid, {
|
||||||
'name': out_obj._name + ',' + in_field,
|
'name': out_obj._name + ',' + in_field,
|
||||||
|
@ -75,16 +74,16 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
'src': src[in_id],
|
'src': src[in_id],
|
||||||
'value': value[in_id],
|
'value': value[in_id],
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
#replace the value in the destination object only if it's the user lang
|
|
||||||
if context.get('lang') == lang:
|
|
||||||
self.pool[out_obj._name].write(cr, uid, out_ids[j], {in_field: value[in_id]})
|
|
||||||
else:
|
else:
|
||||||
_logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
|
_logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, cr, uid, ids, context=None):
|
def execute(self, cr, uid, ids, context=None):
|
||||||
res = super(wizard_multi_charts_accounts, self).execute(cr, uid, ids, context=context)
|
if not context:
|
||||||
|
context = {}
|
||||||
|
# remove the lang to get the untranslated value
|
||||||
|
ctx = dict(context, lang=None)
|
||||||
|
res = super(wizard_multi_charts_accounts, self).execute(cr, uid, ids, context=ctx)
|
||||||
|
|
||||||
obj_multi = self.browse(cr, uid, ids[0], context=context)
|
obj_multi = self.browse(cr, uid, ids[0], context=context)
|
||||||
company_id = obj_multi.company_id.id
|
company_id = obj_multi.company_id.id
|
||||||
|
@ -125,7 +124,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
acc_root_id = obj_acc.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
|
acc_root_id = obj_acc.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
|
||||||
in_ids = obj_acc_template.search(cr, uid, [('id', 'child_of', [acc_template_root_id])], order='id')[1:]
|
in_ids = obj_acc_template.search(cr, uid, [('id', 'child_of', [acc_template_root_id])], order='id')[1:]
|
||||||
out_ids = obj_acc.search(cr, uid, [('id', 'child_of', [acc_root_id])], order='id')[1:]
|
out_ids = obj_acc.search(cr, uid, [('id', 'child_of', [acc_root_id])], order='id')[1:]
|
||||||
return self.process_translations(cr, uid, langs, obj_acc_template, field, in_ids, obj_acc, out_ids, force_write=True, context=context)
|
return self.process_translations(cr, uid, langs, obj_acc_template, field, in_ids, obj_acc, out_ids, context=context)
|
||||||
|
|
||||||
def _process_tax_codes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
def _process_tax_codes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
||||||
obj_tax_code_template = self.pool.get('account.tax.code.template')
|
obj_tax_code_template = self.pool.get('account.tax.code.template')
|
||||||
|
@ -134,21 +133,21 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
||||||
tax_code_root_id = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
|
tax_code_root_id = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', None)])[0]
|
||||||
in_ids = obj_tax_code_template.search(cr, uid, [('id', 'child_of', [tax_code_template_root_id])], order='id')[1:]
|
in_ids = obj_tax_code_template.search(cr, uid, [('id', 'child_of', [tax_code_template_root_id])], order='id')[1:]
|
||||||
out_ids = obj_tax_code.search(cr, uid, [('id', 'child_of', [tax_code_root_id])], order='id')[1:]
|
out_ids = obj_tax_code.search(cr, uid, [('id', 'child_of', [tax_code_root_id])], order='id')[1:]
|
||||||
return self.process_translations(cr, uid, langs, obj_tax_code_template, field, in_ids, obj_tax_code, out_ids, force_write=False, context=context)
|
return self.process_translations(cr, uid, langs, obj_tax_code_template, field, in_ids, obj_tax_code, out_ids, context=context)
|
||||||
|
|
||||||
def _process_taxes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
def _process_taxes_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
||||||
obj_tax_template = self.pool.get('account.tax.template')
|
obj_tax_template = self.pool.get('account.tax.template')
|
||||||
obj_tax = self.pool.get('account.tax')
|
obj_tax = self.pool.get('account.tax')
|
||||||
in_ids = sorted([x.id for x in obj_multi.chart_template_id.tax_template_ids])
|
in_ids = sorted([x.id for x in obj_multi.chart_template_id.tax_template_ids])
|
||||||
out_ids = obj_tax.search(cr, uid, [('company_id', '=', company_id)], order='id')
|
out_ids = obj_tax.search(cr, uid, [('company_id', '=', company_id)], order='id')
|
||||||
return self.process_translations(cr, uid, langs, obj_tax_template, field, in_ids, obj_tax, out_ids, force_write=False, context=context)
|
return self.process_translations(cr, uid, langs, obj_tax_template, field, in_ids, obj_tax, out_ids, context=context)
|
||||||
|
|
||||||
def _process_fiscal_pos_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
def _process_fiscal_pos_translations(self, cr, uid, obj_multi, company_id, langs, field, context=None):
|
||||||
obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
|
obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
|
||||||
obj_fiscal_position = self.pool.get('account.fiscal.position')
|
obj_fiscal_position = self.pool.get('account.fiscal.position')
|
||||||
in_ids = obj_fiscal_position_template.search(cr, uid, [('chart_template_id', '=', obj_multi.chart_template_id.id)], order='id')
|
in_ids = obj_fiscal_position_template.search(cr, uid, [('chart_template_id', '=', obj_multi.chart_template_id.id)], order='id')
|
||||||
out_ids = obj_fiscal_position.search(cr, uid, [('company_id', '=', company_id)], order='id')
|
out_ids = obj_fiscal_position.search(cr, uid, [('company_id', '=', company_id)], order='id')
|
||||||
return self.process_translations(cr, uid, langs, obj_fiscal_position_template, field, in_ids, obj_fiscal_position, out_ids, force_write=False, context=context)
|
return self.process_translations(cr, uid, langs, obj_fiscal_position_template, field, in_ids, obj_fiscal_position, out_ids, context=context)
|
||||||
|
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -3693,8 +3693,6 @@ Cuentas del plan
|
||||||
<field name="property_account_payable" ref="cuenta2122001000"/>
|
<field name="property_account_payable" ref="cuenta2122001000"/>
|
||||||
<field name="property_account_expense_categ" ref="cuenta6111001000"/>
|
<field name="property_account_expense_categ" ref="cuenta6111001000"/>
|
||||||
<field name="property_account_income_categ" ref="cuenta5111001000"/>
|
<field name="property_account_income_categ" ref="cuenta5111001000"/>
|
||||||
<field name="property_stock_account_input_categ" ref="cuenta4111003000"/>
|
|
||||||
<field name="property_stock_account_output_categ" ref="cuenta4511003000"/>
|
|
||||||
<field name="currency_id" ref="base.MXN"/>
|
<field name="currency_id" ref="base.MXN"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
<field name="property_account_income" ref="chart_711"/>
|
<field name="property_account_income" ref="chart_711"/>
|
||||||
<field name="property_account_income_categ" ref="chart_711"/>
|
<field name="property_account_income_categ" ref="chart_711"/>
|
||||||
<field name="property_account_expense_categ" ref="chart_311"/>
|
<field name="property_account_expense_categ" ref="chart_311"/>
|
||||||
<field name="property_reserve_and_surplus_account" ref="chart_811"/>
|
|
||||||
<field name="currency_id" ref="base.EUR"/>
|
<field name="currency_id" ref="base.EUR"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
<field name="name">Basic Chart of Account</field>
|
<field name="name">Basic Chart of Account</field>
|
||||||
<field name="visible" eval="False" />
|
<field name="visible" eval="False" />
|
||||||
<field name="complete_tax_set" eval="False" />
|
<field name="complete_tax_set" eval="False" />
|
||||||
<field name="currency_id" ref="base.USD"/>
|
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="account_chart_template_cogs" model="account.chart.template">
|
<record id="account_chart_template_cogs" model="account.chart.template">
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
<field name="amount">0.00000</field>
|
<field name="amount">0.00000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">all</field>
|
<field name="type_tax_use">all</field>
|
||||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
<field name="account_collected_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
<field name="account_paid_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -21,8 +21,8 @@
|
||||||
<field name="amount">0.120000</field>
|
<field name="amount">0.120000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">sale</field>
|
<field name="type_tax_use">sale</field>
|
||||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
<field name="account_collected_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
<field name="account_paid_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
<field name="amount">0.080000</field>
|
<field name="amount">0.080000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">sale</field>
|
<field name="type_tax_use">sale</field>
|
||||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
<field name="account_collected_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
<field name="account_paid_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -47,8 +47,8 @@
|
||||||
<field name="amount">0.220000</field>
|
<field name="amount">0.220000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">sale</field>
|
<field name="type_tax_use">sale</field>
|
||||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
<field name="account_collected_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
<field name="account_paid_id" ref="account_activa_account_2172003"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -60,8 +60,8 @@
|
||||||
<field name="amount">0.120000</field>
|
<field name="amount">0.120000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">purchase</field>
|
<field name="type_tax_use">purchase</field>
|
||||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
<field name="account_collected_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
<field name="account_paid_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -73,8 +73,8 @@
|
||||||
<field name="amount">0.080000</field>
|
<field name="amount">0.080000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">purchase</field>
|
<field name="type_tax_use">purchase</field>
|
||||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
<field name="account_collected_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
<field name="account_paid_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
@ -86,8 +86,8 @@
|
||||||
<field name="amount">0.220000</field>
|
<field name="amount">0.220000</field>
|
||||||
<field name="type">percent</field>
|
<field name="type">percent</field>
|
||||||
<field name="type_tax_use">purchase</field>
|
<field name="type_tax_use">purchase</field>
|
||||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
<field name="account_collected_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
<field name="account_paid_id" ref="account_activa_account_1151004"/>
|
||||||
<field name="base_code_id" ref="vat_code_base_due"/>
|
<field name="base_code_id" ref="vat_code_base_due"/>
|
||||||
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
<field name="tax_code_id" ref="vat_code_due_tva"/>
|
||||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||||
|
|
|
@ -698,8 +698,9 @@ class mail_message(osv.Model):
|
||||||
"""
|
"""
|
||||||
model_record_ids = {}
|
model_record_ids = {}
|
||||||
for id in msg_ids:
|
for id in msg_ids:
|
||||||
if msg_val[id]['model'] and msg_val[id]['res_id']:
|
vals = msg_val.get(id, {})
|
||||||
model_record_ids.setdefault(msg_val[id]['model'], dict()).setdefault(msg_val[id]['res_id'], set()).add(msg_val[id]['res_id'])
|
if vals.get('model') and vals.get('res_id'):
|
||||||
|
model_record_ids.setdefault(vals['model'], set()).add(vals['res_id'])
|
||||||
return model_record_ids
|
return model_record_ids
|
||||||
|
|
||||||
if uid == SUPERUSER_ID:
|
if uid == SUPERUSER_ID:
|
||||||
|
@ -711,7 +712,7 @@ class mail_message(osv.Model):
|
||||||
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
|
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
|
||||||
|
|
||||||
# Read mail_message.ids to have their values
|
# Read mail_message.ids to have their values
|
||||||
message_values = dict.fromkeys(ids)
|
message_values = dict.fromkeys(ids, {})
|
||||||
cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,))
|
cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,))
|
||||||
for id, rmod, rid, author_id, parent_id in cr.fetchall():
|
for id, rmod, rid, author_id, parent_id in cr.fetchall():
|
||||||
message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id}
|
message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id}
|
||||||
|
@ -745,10 +746,10 @@ class mail_message(osv.Model):
|
||||||
], context=context)
|
], context=context)
|
||||||
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
|
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
|
||||||
elif operation == 'create':
|
elif operation == 'create':
|
||||||
for doc_model, doc_dict in model_record_ids.items():
|
for doc_model, doc_ids in model_record_ids.items():
|
||||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||||
('res_model', '=', doc_model),
|
('res_model', '=', doc_model),
|
||||||
('res_id', 'in', list(doc_dict.keys())),
|
('res_id', 'in', list(doc_ids)),
|
||||||
('partner_id', '=', partner_id),
|
('partner_id', '=', partner_id),
|
||||||
], context=context)
|
], context=context)
|
||||||
fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)]
|
fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)]
|
||||||
|
@ -759,9 +760,9 @@ class mail_message(osv.Model):
|
||||||
other_ids = other_ids.difference(set(notified_ids))
|
other_ids = other_ids.difference(set(notified_ids))
|
||||||
model_record_ids = _generate_model_record_ids(message_values, other_ids)
|
model_record_ids = _generate_model_record_ids(message_values, other_ids)
|
||||||
document_related_ids = []
|
document_related_ids = []
|
||||||
for model, doc_dict in model_record_ids.items():
|
for model, doc_ids in model_record_ids.items():
|
||||||
model_obj = self.pool[model]
|
model_obj = self.pool[model]
|
||||||
mids = model_obj.exists(cr, uid, doc_dict.keys())
|
mids = model_obj.exists(cr, uid, list(doc_ids))
|
||||||
if hasattr(model_obj, 'check_mail_message_access'):
|
if hasattr(model_obj, 'check_mail_message_access'):
|
||||||
model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
|
model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -38,6 +38,7 @@ from openerp import tools
|
||||||
from openerp import SUPERUSER_ID
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.addons.mail.mail_message import decode
|
from openerp.addons.mail.mail_message import decode
|
||||||
from openerp.osv import fields, osv, orm
|
from openerp.osv import fields, osv, orm
|
||||||
|
from openerp.osv.orm import browse_record, browse_null
|
||||||
from openerp.tools.safe_eval import safe_eval as eval
|
from openerp.tools.safe_eval import safe_eval as eval
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
|
@ -355,11 +356,11 @@ class mail_thread(osv.AbstractModel):
|
||||||
if not context.get('mail_create_nosubscribe'):
|
if not context.get('mail_create_nosubscribe'):
|
||||||
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
|
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
|
||||||
# auto_subscribe: take values and defaults into account
|
# auto_subscribe: take values and defaults into account
|
||||||
create_values = set(values.keys())
|
create_values = dict(values)
|
||||||
for key, val in context.iteritems():
|
for key, val in context.iteritems():
|
||||||
if key.startswith('default_'):
|
if key.startswith('default_'):
|
||||||
create_values.add(key[8:])
|
create_values[key[8:]] = val
|
||||||
self.message_auto_subscribe(cr, uid, [thread_id], list(create_values), context=context)
|
self.message_auto_subscribe(cr, uid, [thread_id], create_values.keys(), context=context, values=create_values)
|
||||||
|
|
||||||
# track values
|
# track values
|
||||||
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context)
|
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context)
|
||||||
|
@ -380,7 +381,7 @@ class mail_thread(osv.AbstractModel):
|
||||||
|
|
||||||
# Perform write, update followers
|
# Perform write, update followers
|
||||||
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
|
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
|
||||||
self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context)
|
self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
|
||||||
|
|
||||||
# Perform the tracking
|
# Perform the tracking
|
||||||
if tracked_fields:
|
if tracked_fields:
|
||||||
|
@ -604,6 +605,7 @@ class mail_thread(osv.AbstractModel):
|
||||||
return action
|
return action
|
||||||
if msg_id and not (model and res_id):
|
if msg_id and not (model and res_id):
|
||||||
msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
|
msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
|
||||||
|
if msg.exists():
|
||||||
model, res_id = msg.model, msg.res_id
|
model, res_id = msg.model, msg.res_id
|
||||||
|
|
||||||
# if model + res_id found: try to redirect to the document or fallback on the Inbox
|
# if model + res_id found: try to redirect to the document or fallback on the Inbox
|
||||||
|
@ -1565,75 +1567,100 @@ class mail_thread(osv.AbstractModel):
|
||||||
user_field_lst.append(name)
|
user_field_lst.append(name)
|
||||||
return user_field_lst
|
return user_field_lst
|
||||||
|
|
||||||
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None):
|
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None, values=None):
|
||||||
"""
|
""" Handle auto subscription. Two methods for auto subscription exist:
|
||||||
1. fetch project subtype related to task (parent_id.res_model = 'project.task')
|
|
||||||
2. for each project subtype: subscribe the follower to the task
|
- tracked res.users relational fields, such as user_id fields. Those fields
|
||||||
|
must be relation fields toward a res.users record, and must have the
|
||||||
|
track_visilibity attribute set.
|
||||||
|
- using subtypes parent relationship: check if the current model being
|
||||||
|
modified has an header record (such as a project for tasks) whose followers
|
||||||
|
can be added as followers of the current records. Example of structure
|
||||||
|
with project and task:
|
||||||
|
|
||||||
|
- st_project_1.parent_id = st_task_1
|
||||||
|
- st_project_1.res_model = 'project.project'
|
||||||
|
- st_project_1.relation_field = 'project_id'
|
||||||
|
- st_task_1.model = 'project.task'
|
||||||
|
|
||||||
|
:param list updated_fields: list of updated fields to track
|
||||||
|
:param dict values: updated values; if None, the first record will be browsed
|
||||||
|
to get the values. Added after releasing 7.0, therefore
|
||||||
|
not merged with updated_fields argumment.
|
||||||
"""
|
"""
|
||||||
subtype_obj = self.pool.get('mail.message.subtype')
|
subtype_obj = self.pool.get('mail.message.subtype')
|
||||||
follower_obj = self.pool.get('mail.followers')
|
follower_obj = self.pool.get('mail.followers')
|
||||||
|
new_followers = dict()
|
||||||
|
|
||||||
# fetch auto_follow_fields
|
# fetch auto_follow_fields: res.users relation fields whose changes are tracked for subscription
|
||||||
user_field_lst = self._message_get_auto_subscribe_fields(cr, uid, updated_fields, context=context)
|
user_field_lst = self._message_get_auto_subscribe_fields(cr, uid, updated_fields, context=context)
|
||||||
|
|
||||||
# fetch related record subtypes
|
# fetch header subtypes
|
||||||
related_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context)
|
header_subtype_ids = subtype_obj.search(cr, uid, ['|', ('res_model', '=', False), ('parent_id.res_model', '=', self._name)], context=context)
|
||||||
subtypes = subtype_obj.browse(cr, uid, related_subtype_ids, context=context)
|
subtypes = subtype_obj.browse(cr, uid, header_subtype_ids, context=context)
|
||||||
default_subtypes = [subtype for subtype in subtypes if subtype.res_model == False]
|
|
||||||
related_subtypes = [subtype for subtype in subtypes if subtype.res_model != False]
|
# if no change in tracked field or no change in tracked relational field: quit
|
||||||
relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field != False])
|
relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field is not False])
|
||||||
if (not related_subtypes or not any(relation in updated_fields for relation in relation_fields)) and not user_field_lst:
|
if not any(relation in updated_fields for relation in relation_fields) and not user_field_lst:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for record in self.browse(cr, uid, ids, context=context):
|
# legacy behavior: if values is not given, compute the values by browsing
|
||||||
new_followers = dict()
|
# @TDENOTE: remove me in 8.0
|
||||||
parent_res_id = False
|
if values is None:
|
||||||
parent_model = False
|
record = self.browse(cr, uid, ids[0], context=context)
|
||||||
for subtype in related_subtypes:
|
for updated_field in updated_fields:
|
||||||
if not subtype.relation_field or not subtype.parent_id:
|
field_value = getattr(record, updated_field)
|
||||||
continue
|
if isinstance(field_value, browse_record):
|
||||||
if not subtype.relation_field in self._columns or not getattr(record, subtype.relation_field, False):
|
field_value = field_value.id
|
||||||
continue
|
elif isinstance(field_value, browse_null):
|
||||||
parent_res_id = getattr(record, subtype.relation_field).id
|
field_value = False
|
||||||
parent_model = subtype.res_model
|
values[updated_field] = field_value
|
||||||
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [
|
|
||||||
('res_model', '=', parent_model),
|
|
||||||
('res_id', '=', parent_res_id),
|
|
||||||
('subtype_ids', 'in', [subtype.id])
|
|
||||||
], context=context)
|
|
||||||
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
|
|
||||||
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.parent_id.id)
|
|
||||||
|
|
||||||
if parent_res_id and parent_model:
|
# find followers of headers, update structure for new followers
|
||||||
for subtype in default_subtypes:
|
headers = set()
|
||||||
follower_ids = follower_obj.search(cr, SUPERUSER_ID, [
|
for subtype in subtypes:
|
||||||
('res_model', '=', parent_model),
|
if subtype.relation_field and values.get(subtype.relation_field):
|
||||||
('res_id', '=', parent_res_id),
|
headers.add((subtype.res_model, values.get(subtype.relation_field)))
|
||||||
('subtype_ids', 'in', [subtype.id])
|
if headers:
|
||||||
], context=context)
|
header_domain = ['|'] * (len(headers) - 1)
|
||||||
for follower in follower_obj.browse(cr, SUPERUSER_ID, follower_ids, context=context):
|
for header in headers:
|
||||||
new_followers.setdefault(follower.partner_id.id, set()).add(subtype.id)
|
header_domain += ['&', ('res_model', '=', header[0]), ('res_id', '=', header[1])]
|
||||||
|
header_follower_ids = follower_obj.search(
|
||||||
|
cr, SUPERUSER_ID,
|
||||||
|
header_domain,
|
||||||
|
context=context
|
||||||
|
)
|
||||||
|
for header_follower in follower_obj.browse(cr, SUPERUSER_ID, header_follower_ids, context=context):
|
||||||
|
for subtype in header_follower.subtype_ids:
|
||||||
|
if subtype.parent_id and subtype.parent_id.res_model == self._name:
|
||||||
|
new_followers.setdefault(header_follower.partner_id.id, set()).add(subtype.parent_id.id)
|
||||||
|
elif subtype.res_model is False:
|
||||||
|
new_followers.setdefault(header_follower.partner_id.id, set()).add(subtype.id)
|
||||||
|
|
||||||
# add followers coming from res.users relational fields that are tracked
|
# add followers coming from res.users relational fields that are tracked
|
||||||
user_ids = [getattr(record, name).id for name in user_field_lst if getattr(record, name)]
|
user_ids = [values[name] for name in user_field_lst if values.get(name)]
|
||||||
user_id_partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, SUPERUSER_ID, user_ids, context=context)]
|
user_pids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, SUPERUSER_ID, user_ids, context=context)]
|
||||||
for partner_id in user_id_partner_ids:
|
for partner_id in user_pids:
|
||||||
new_followers.setdefault(partner_id, None)
|
new_followers.setdefault(partner_id, None)
|
||||||
|
|
||||||
for pid, subtypes in new_followers.items():
|
for pid, subtypes in new_followers.items():
|
||||||
subtypes = list(subtypes) if subtypes is not None else None
|
subtypes = list(subtypes) if subtypes is not None else None
|
||||||
self.message_subscribe(cr, uid, [record.id], [pid], subtypes, context=context)
|
self.message_subscribe(cr, uid, ids, [pid], subtypes, context=context)
|
||||||
|
|
||||||
# find first email message, set it as unread for auto_subscribe fields for them to have a notification
|
# find first email message, set it as unread for auto_subscribe fields for them to have a notification
|
||||||
if user_id_partner_ids:
|
if user_pids:
|
||||||
msg_ids = self.pool.get('mail.message').search(cr, uid, [
|
for record_id in ids:
|
||||||
|
message_obj = self.pool.get('mail.message')
|
||||||
|
msg_ids = message_obj.search(cr, SUPERUSER_ID, [
|
||||||
('model', '=', self._name),
|
('model', '=', self._name),
|
||||||
('res_id', '=', record.id),
|
('res_id', '=', record_id),
|
||||||
('type', '=', 'email')], limit=1, context=context)
|
('type', '=', 'email')], limit=1, context=context)
|
||||||
if not msg_ids and record.message_ids:
|
if not msg_ids:
|
||||||
msg_ids = [record.message_ids[-1].id]
|
msg_ids = message_obj.search(cr, SUPERUSER_ID, [
|
||||||
|
('model', '=', self._name),
|
||||||
|
('res_id', '=', record_id)], limit=1, context=context)
|
||||||
if msg_ids:
|
if msg_ids:
|
||||||
self.pool.get('mail.notification')._notify(cr, uid, msg_ids[0], partners_to_notify=user_id_partner_ids, context=context)
|
self.pool.get('mail.notification')._notify(cr, uid, msg_ids[0], partners_to_notify=user_pids, context=context)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -294,9 +294,9 @@ class test_mail(TestMail):
|
||||||
'notification email: link should contain the user login')
|
'notification email: link should contain the user login')
|
||||||
self.assertIn('message_id=%s' % mail.mail_message_id.id, url,
|
self.assertIn('message_id=%s' % mail.mail_message_id.id, url,
|
||||||
'notification email: link based on message should contain the mail_message id')
|
'notification email: link based on message should contain the mail_message id')
|
||||||
self.assertNotIn('model', url,
|
self.assertNotIn('model=mail.group', url,
|
||||||
'notification email: link based on message should not contain model')
|
'notification email: link based on message should not contain model')
|
||||||
self.assertNotIn('res_id', url,
|
self.assertNotIn('res_id=%s' % group_pigs.id, url,
|
||||||
'notification email: link based on message should not contain res_id')
|
'notification email: link based on message should not contain res_id')
|
||||||
|
|
||||||
@mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
@mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<field name="name">welcome new partner</field>
|
<field name="name">welcome new partner</field>
|
||||||
<field name="email_from">info@openerp.com</field>
|
<field name="email_from">info@openerp.com</field>
|
||||||
<field name="subject">Welcome to the OpenERP Partner Channel!</field>
|
<field name="subject">Welcome to the OpenERP Partner Channel!</field>
|
||||||
<field name="email_to">${object.email or ''}</field>
|
<field name="email_to">${(object.email or '')|safe}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="body_html">Hello, you will receive your welcome pack via email shortly.</field>
|
<field name="body_html">Hello, you will receive your welcome pack via email shortly.</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<field name="name">congrats silver partner</field>
|
<field name="name">congrats silver partner</field>
|
||||||
<field name="email_from">info@openerp.com</field>
|
<field name="email_from">info@openerp.com</field>
|
||||||
<field name="subject">Congratulations! You are now a Silver Partner!</field>
|
<field name="subject">Congratulations! You are now a Silver Partner!</field>
|
||||||
<field name="email_to">${object.email or ''}</field>
|
<field name="email_to">${(object.email or '')|safe}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="body_html">Hi, we are delighted to welcome you among our Silver Partners as of today!</field>
|
<field name="body_html">Hi, we are delighted to welcome you among our Silver Partners as of today!</field>
|
||||||
</record>
|
</record>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<field name="name">congrats gold partner</field>
|
<field name="name">congrats gold partner</field>
|
||||||
<field name="email_from">info@openerp.com</field>
|
<field name="email_from">info@openerp.com</field>
|
||||||
<field name="subject">Congratulations! You are now one of our Gold Partners!</field>
|
<field name="subject">Congratulations! You are now one of our Gold Partners!</field>
|
||||||
<field name="email_to">${object.email or ''}</field>
|
<field name="email_to">${(object.email or '')|safe}</field>
|
||||||
<field name="model_id" ref="base.model_res_partner"/>
|
<field name="model_id" ref="base.model_res_partner"/>
|
||||||
<field name="body_html">Hi, we are delighted to let you know that you have entered the select circle of our Gold Partners</field>
|
<field name="body_html">Hi, we are delighted to let you know that you have entered the select circle of our Gold Partners</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -965,7 +965,10 @@ class mrp_production(osv.osv):
|
||||||
partner_id = routing_loc.partner_id and routing_loc.partner_id.id or False
|
partner_id = routing_loc.partner_id and routing_loc.partner_id.id or False
|
||||||
|
|
||||||
# Take next Sequence number of shipment base on type
|
# Take next Sequence number of shipment base on type
|
||||||
|
if pick_type!='internal':
|
||||||
pick_name = ir_sequence.get(cr, uid, 'stock.picking.' + pick_type)
|
pick_name = ir_sequence.get(cr, uid, 'stock.picking.' + pick_type)
|
||||||
|
else:
|
||||||
|
pick_name = ir_sequence.get(cr, uid, 'stock.picking')
|
||||||
|
|
||||||
picking_id = stock_picking.create(cr, uid, {
|
picking_id = stock_picking.create(cr, uid, {
|
||||||
'name': pick_name,
|
'name': pick_name,
|
||||||
|
|
|
@ -80,11 +80,11 @@ class mrp_production(osv.osv):
|
||||||
_inherit= 'mrp.production'
|
_inherit= 'mrp.production'
|
||||||
|
|
||||||
|
|
||||||
def action_confirm(self, cr, uid, ids):
|
def action_confirm(self, cr, uid, ids, context=None):
|
||||||
""" Confirms production order and calculates quantity based on subproduct_type.
|
""" Confirms production order and calculates quantity based on subproduct_type.
|
||||||
@return: Newly generated picking Id.
|
@return: Newly generated picking Id.
|
||||||
"""
|
"""
|
||||||
picking_id = super(mrp_production,self).action_confirm(cr, uid, ids)
|
picking_id = super(mrp_production,self).action_confirm(cr, uid, ids, context=context)
|
||||||
product_uom_obj = self.pool.get('product.uom')
|
product_uom_obj = self.pool.get('product.uom')
|
||||||
for production in self.browse(cr, uid, ids):
|
for production in self.browse(cr, uid, ids):
|
||||||
source = production.product_id.property_stock_production.id
|
source = production.product_id.property_stock_production.id
|
||||||
|
|
|
@ -39,7 +39,11 @@ class pad_common(osv.osv_memory):
|
||||||
#if create with content
|
#if create with content
|
||||||
if "field_name" in context and "model" in context and "object_id" in context:
|
if "field_name" in context and "model" in context and "object_id" in context:
|
||||||
myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api')
|
myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api')
|
||||||
|
try:
|
||||||
myPad.createPad(path)
|
myPad.createPad(path)
|
||||||
|
except urllib2.URLError:
|
||||||
|
raise osv.except_osv(_("Error"), _("Pad creation failed, \
|
||||||
|
either there is a problem with your pad server URL or with your connection."))
|
||||||
|
|
||||||
#get attr on the field model
|
#get attr on the field model
|
||||||
model = self.pool[context["model"]]
|
model = self.pool[context["model"]]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<record id="base.main_company" model="res.company">
|
<record id="base.main_company" model="res.company">
|
||||||
<field name="pad_server">pad.openerp.com</field>
|
<field name="pad_server">https://pad.openerp.com</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="base.main_company" model="res.company">
|
<record id="base.main_company" model="res.company">
|
||||||
|
|
|
@ -694,7 +694,7 @@ class pos_order(osv.osv):
|
||||||
|
|
||||||
def create_picking(self, cr, uid, ids, context=None):
|
def create_picking(self, cr, uid, ids, context=None):
|
||||||
"""Create a picking for each order and validate it."""
|
"""Create a picking for each order and validate it."""
|
||||||
picking_obj = self.pool.get('stock.picking')
|
picking_obj = self.pool.get('stock.picking.out')
|
||||||
partner_obj = self.pool.get('res.partner')
|
partner_obj = self.pool.get('res.partner')
|
||||||
move_obj = self.pool.get('stock.move')
|
move_obj = self.pool.get('stock.move')
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<div class="oe_subtotal_footer_separator oe_inline">
|
<div class="oe_subtotal_footer_separator oe_inline">
|
||||||
<label for="amount_total" />
|
<label for="amount_total" />
|
||||||
<button name="button_dummy"
|
<button name="button_dummy"
|
||||||
states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
|
states="draft" string="(update)" class="oe_edit_only oe_link"/>
|
||||||
</div>
|
</div>
|
||||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
|
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -19,6 +19,7 @@
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.osv import osv, orm
|
from openerp.osv import osv, orm
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ class mail_message(osv.Model):
|
||||||
""" Override that adds specific access rights of mail.message, to remove
|
""" Override that adds specific access rights of mail.message, to remove
|
||||||
all internal notes if uid is a non-employee
|
all internal notes if uid is a non-employee
|
||||||
"""
|
"""
|
||||||
|
if uid == SUPERUSER_ID:
|
||||||
|
return super(mail_message, self)._search(cr, uid, args, offset=offset, limit=limit, order=order,
|
||||||
|
context=context, count=False, access_rights_uid=access_rights_uid)
|
||||||
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
|
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
|
||||||
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
|
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
|
||||||
if group_user_id not in [group.id for group in group_ids]:
|
if group_user_id not in [group.id for group in group_ids]:
|
||||||
|
@ -45,6 +49,8 @@ class mail_message(osv.Model):
|
||||||
- read:
|
- read:
|
||||||
- raise if the type is comment and subtype NULL (internal note)
|
- raise if the type is comment and subtype NULL (internal note)
|
||||||
"""
|
"""
|
||||||
|
if uid == SUPERUSER_ID:
|
||||||
|
return super(mail_message, self).check_access_rule(cr, uid, ids=ids, operation=operation, context=context)
|
||||||
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
|
group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id
|
||||||
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
|
group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_user')[1]
|
||||||
if group_user_id not in [group.id for group in group_ids]:
|
if group_user_id not in [group.id for group in group_ids]:
|
||||||
|
|
|
@ -73,6 +73,9 @@ class test_portal(TestMail):
|
||||||
for message in chell_pigs.message_ids:
|
for message in chell_pigs.message_ids:
|
||||||
trigger_read = message.subject
|
trigger_read = message.subject
|
||||||
for partner in chell_pigs.message_follower_ids:
|
for partner in chell_pigs.message_follower_ids:
|
||||||
|
if partner.id == self.partner_chell_id:
|
||||||
|
# Chell can read her own partner record
|
||||||
|
continue
|
||||||
with self.assertRaises(except_orm):
|
with self.assertRaises(except_orm):
|
||||||
trigger_read = partner.name
|
trigger_read = partner.name
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data noupdate="1">
|
<data>
|
||||||
|
|
||||||
<record id="portal_claim_rule" model="ir.rule">
|
<record id="portal_claim_rule" model="ir.rule">
|
||||||
<field name="name">Portal Personal Claims</field>
|
<field name="name">Portal Personal Claims</field>
|
||||||
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
||||||
<field name="domain_force">[('message_follower_ids','in', [user.partner_id.id])]</field>
|
<field name="domain_force">['|', ('message_follower_ids','in', [user.partner_id.id]), ('partner_id','=', user.partner_id.id)]</field>
|
||||||
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
<field name="groups" eval="[(4, ref('portal.group_portal'))]"/>
|
||||||
<field eval="1" name="perm_unlink"/>
|
<field eval="0" name="perm_unlink"/>
|
||||||
<field eval="1" name="perm_write"/>
|
<field eval="0" name="perm_write"/>
|
||||||
<field eval="1" name="perm_read"/>
|
<field eval="1" name="perm_read"/>
|
||||||
<field eval="0" name="perm_create"/>
|
<field eval="1" name="perm_create"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -24,7 +24,6 @@ from openerp.osv import fields, osv
|
||||||
class crm_contact_us(osv.TransientModel):
|
class crm_contact_us(osv.TransientModel):
|
||||||
""" Add employees list to the portal's contact page """
|
""" Add employees list to the portal's contact page """
|
||||||
_inherit = 'portal_crm.crm_contact_us'
|
_inherit = 'portal_crm.crm_contact_us'
|
||||||
_description = 'Contact form for the portal'
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'employee_ids' : fields.many2many('hr.employee', string='Employees', readonly=True),
|
'employee_ids' : fields.many2many('hr.employee', string='Employees', readonly=True),
|
||||||
}
|
}
|
||||||
|
@ -40,7 +39,6 @@ class crm_contact_us(osv.TransientModel):
|
||||||
}
|
}
|
||||||
|
|
||||||
class hr_employee(osv.osv):
|
class hr_employee(osv.osv):
|
||||||
_description = 'Portal employee'
|
|
||||||
_inherit = 'hr.employee'
|
_inherit = 'hr.employee'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<!--Email template -->
|
<!--Email template -->
|
||||||
<record id="email_template_edi_sale" model="email.template">
|
<record id="email_template_edi_sale" model="email.template">
|
||||||
<field name="name">Sales Order - Send by Email (Portal)</field>
|
<field name="name">Sales Order - Send by Email (Portal)</field>
|
||||||
<field name="email_from">${object.user_id.email or ''}</field>
|
<field name="email_from">${(object.user_id.email or '')|safe}</field>
|
||||||
<field name="subject">${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
<field name="subject">${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })</field>
|
||||||
<field name="partner_to">${object.partner_invoice_id.id}</field>
|
<field name="partner_to">${object.partner_invoice_id.id}</field>
|
||||||
<field name="model_id" ref="sale.model_sale_order"/>
|
<field name="model_id" ref="sale.model_sale_order"/>
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
<record id="email_template_edi_invoice" model="email.template">
|
<record id="email_template_edi_invoice" model="email.template">
|
||||||
<field name="name">Invoice - Send by Email (Portal)</field>
|
<field name="name">Invoice - Send by Email (Portal)</field>
|
||||||
<field name="email_from">${object.user_id.email or object.company_id.email or 'noreply@localhost'}</field>
|
<field name="email_from">${(object.user_id.email or object.company_id.email or 'noreply@localhost')|safe}</field>
|
||||||
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
|
<field name="subject">${object.company_id.name} Invoice (Ref ${object.number or 'n/a' })</field>
|
||||||
<field name="partner_to">${object.partner_id.id}</field>
|
<field name="partner_to">${object.partner_id.id}</field>
|
||||||
<field name="model_id" ref="account.model_account_invoice"/>
|
<field name="model_id" ref="account.model_account_invoice"/>
|
||||||
|
|
|
@ -181,10 +181,6 @@ class procurement_order(osv.osv):
|
||||||
"""
|
"""
|
||||||
return all(procurement.move_id.state == 'cancel' for procurement in self.browse(cr, uid, ids, context=context))
|
return all(procurement.move_id.state == 'cancel' for procurement in self.browse(cr, uid, ids, context=context))
|
||||||
|
|
||||||
#This Function is create to avoid a server side Error Like 'ERROR:tests.mrp:name 'check_move' is not defined'
|
|
||||||
def check_move(self, cr, uid, ids, context=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def check_move_done(self, cr, uid, ids, context=None):
|
def check_move_done(self, cr, uid, ids, context=None):
|
||||||
""" Checks if move is done or not.
|
""" Checks if move is done or not.
|
||||||
@return: True or False.
|
@return: True or False.
|
||||||
|
@ -297,6 +293,12 @@ class procurement_order(osv.osv):
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def check_move(self, cr, uid, ids, context=None):
|
||||||
|
""" Check whether the given procurement can be satisfied by an internal move,
|
||||||
|
typically a pulled flow. By default, it's False. Overwritten by the `stock_location` module.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
|
||||||
def check_conditions_confirm2wait(self, cr, uid, ids):
|
def check_conditions_confirm2wait(self, cr, uid, ids):
|
||||||
""" condition on the transition to go from 'confirm' activity to 'confirm_wait' activity """
|
""" condition on the transition to go from 'confirm' activity to 'confirm_wait' activity """
|
||||||
return not self.test_cancel(cr, uid, ids)
|
return not self.test_cancel(cr, uid, ids)
|
||||||
|
|
|
@ -147,13 +147,15 @@
|
||||||
|
|
||||||
<record id="trans_confirm_mto_make_done" model="workflow.transition">
|
<record id="trans_confirm_mto_make_done" model="workflow.transition">
|
||||||
<!-- This transition is there to unblock products that would be in MTO with a supply method that would be
|
<!-- This transition is there to unblock products that would be in MTO with a supply method that would be
|
||||||
produce or buy without MRP or purchase module installed. These modules overwrite the check_produce()
|
produce or buy, and without MRP or Purchase modules installed. These modules overwrite the check_produce()
|
||||||
and check_buy() methods -so that it invalidates their part of this 'bypass transition'-, and define
|
and check_buy() methods -so that it invalidates their part of this 'bypass transition'-, and define
|
||||||
their own workflow paths.
|
their own workflow paths.
|
||||||
|
The stock_location module also introduces a check_move() alternative, for pulled flows that are
|
||||||
|
satisfied with an internal product move. This yields a threefold test for the bypass transition.
|
||||||
-->
|
-->
|
||||||
<field name="act_from" ref="act_confirm_mto"/>
|
<field name="act_from" ref="act_confirm_mto"/>
|
||||||
<field name="act_to" ref="act_make_done"/>
|
<field name="act_to" ref="act_make_done"/>
|
||||||
<field name="condition">not check_produce() and not check_buy()</field>
|
<field name="condition">not check_produce() and not check_buy() and not check_move()</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="trans_make_to_stock_make_done" model="workflow.transition">
|
<record id="trans_make_to_stock_make_done" model="workflow.transition">
|
||||||
|
|
|
@ -173,6 +173,7 @@ class procurement_order(osv.osv):
|
||||||
'company_id': orderpoint.company_id.id,
|
'company_id': orderpoint.company_id.id,
|
||||||
'product_uom': orderpoint.product_uom.id,
|
'product_uom': orderpoint.product_uom.id,
|
||||||
'location_id': orderpoint.location_id.id,
|
'location_id': orderpoint.location_id.id,
|
||||||
|
'warehouse_id': orderpoint.warehouse_id.id,
|
||||||
'procure_method': 'make_to_order',
|
'procure_method': 'make_to_order',
|
||||||
'origin': orderpoint.name}
|
'origin': orderpoint.name}
|
||||||
|
|
||||||
|
|
|
@ -86,78 +86,13 @@ class sale_order_line(osv.osv):
|
||||||
pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
||||||
|
|
||||||
new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist)
|
new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist)
|
||||||
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0):
|
if len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0 and new_list_price != 0:
|
||||||
discount = (new_list_price - price) / new_list_price * 100
|
discount = (new_list_price - price) / new_list_price * 100
|
||||||
|
if discount > 0:
|
||||||
result['price_unit'] = new_list_price
|
result['price_unit'] = new_list_price
|
||||||
result['discount'] = discount
|
result['discount'] = discount
|
||||||
else:
|
else:
|
||||||
result['discount'] = 0.0
|
result['discount'] = 0.0
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
class account_invoice_line(osv.osv):
|
|
||||||
_inherit = "account.invoice.line"
|
|
||||||
|
|
||||||
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
|
||||||
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit,currency_id, context=context, company_id=company_id)
|
|
||||||
|
|
||||||
def get_real_price(res_dict, product_id, qty, uom_id, pricelist):
|
|
||||||
item_obj = self.pool.get('product.pricelist.item')
|
|
||||||
price_type_obj = self.pool.get('product.price.type')
|
|
||||||
product_obj = self.pool.get('product.product')
|
|
||||||
field_name = 'list_price'
|
|
||||||
|
|
||||||
if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False):
|
|
||||||
item = res_dict['item_id'].get(pricelist,False)
|
|
||||||
item_read = item_obj.read(cr, uid, [item], ['base'])
|
|
||||||
if item_read:
|
|
||||||
item_base = item_read[0]['base']
|
|
||||||
if item_base > 0:
|
|
||||||
field_name = price_type_obj.browse(cr, uid, item_base).field
|
|
||||||
|
|
||||||
product = product_obj.browse(cr, uid, product_id, context)
|
|
||||||
product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)
|
|
||||||
|
|
||||||
factor = 1.0
|
|
||||||
if uom_id and uom_id != product.uom_id.id:
|
|
||||||
product_uom_obj = self.pool.get('product.uom')
|
|
||||||
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
|
|
||||||
factor = uom_data.factor
|
|
||||||
return product_read[field_name] * factor
|
|
||||||
|
|
||||||
if product:
|
|
||||||
pricelist_obj = self.pool.get('product.pricelist')
|
|
||||||
partner_obj = self.pool.get('res.partner')
|
|
||||||
product = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
|
||||||
result = res['value']
|
|
||||||
pricelist = False
|
|
||||||
real_price = 0.00
|
|
||||||
if type in ('in_invoice', 'in_refund'):
|
|
||||||
if not price_unit and partner_id:
|
|
||||||
pricelist =partner_obj.browse(cr, uid, partner_id).property_product_pricelist_purchase.id
|
|
||||||
if not pricelist:
|
|
||||||
raise osv.except_osv(_('No Purchase Pricelist Found!'),_("You must first define a pricelist on the supplier form!"))
|
|
||||||
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
|
|
||||||
price_unit = price_unit_res[pricelist]
|
|
||||||
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
|
|
||||||
else:
|
else:
|
||||||
if partner_id:
|
result['discount'] = 0.0
|
||||||
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
|
|
||||||
if not pricelist:
|
|
||||||
raise osv.except_osv(_('No Sale Pricelist Found!'),_("You must first define a pricelist on the customer form!"))
|
|
||||||
price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom_id})
|
|
||||||
price_unit = price_unit_res[pricelist]
|
|
||||||
|
|
||||||
real_price = get_real_price(price_unit_res, product.id, qty, uom_id, pricelist)
|
|
||||||
if pricelist:
|
|
||||||
pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
|
||||||
if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0):
|
|
||||||
discount=(real_price-price_unit) / real_price * 100
|
|
||||||
result['price_unit'] = real_price
|
|
||||||
result['discount'] = discount
|
|
||||||
else:
|
|
||||||
result['discount']=0.0
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
||||||
|
|
|
@ -41,14 +41,13 @@ class project_task_type(osv.osv):
|
||||||
'case_default': fields.boolean('Default for New Projects',
|
'case_default': fields.boolean('Default for New Projects',
|
||||||
help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
|
help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
|
||||||
'project_ids': fields.many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', 'Projects'),
|
'project_ids': fields.many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', 'Projects'),
|
||||||
'fold': fields.boolean('Folded by Default',
|
'fold': fields.boolean('Folded in Kanban View',
|
||||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
help='This stage is folded in the kanban view when'
|
||||||
|
'there are no records in that stage to display.'),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'sequence': 1,
|
'sequence': 1,
|
||||||
'fold': False,
|
|
||||||
'case_default': False,
|
|
||||||
'project_ids': lambda self, cr, uid, ctx=None: self.pool['project.task']._get_default_project_id(cr, uid, context=ctx),
|
'project_ids': lambda self, cr, uid, ctx=None: self.pool['project.task']._get_default_project_id(cr, uid, context=ctx),
|
||||||
}
|
}
|
||||||
_order = 'sequence'
|
_order = 'sequence'
|
||||||
|
@ -189,6 +188,8 @@ class project(osv.osv):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _task_count(self, cr, uid, ids, field_name, arg, context=None):
|
def _task_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
|
""" :deprecated: this method will be removed with OpenERP v8. Use task_ids
|
||||||
|
fields instead. """
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
res = dict.fromkeys(ids, 0)
|
res = dict.fromkeys(ids, 0)
|
||||||
|
@ -265,7 +266,10 @@ class project(osv.osv):
|
||||||
}),
|
}),
|
||||||
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
|
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
|
||||||
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
|
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
|
||||||
'task_count': fields.function(_task_count, type='integer', string="Open Tasks"),
|
'task_count': fields.function(_task_count, type='integer', string="Open Tasks",
|
||||||
|
deprecated="This field will be removed in OpenERP v8. Use task_ids one2many field instead."),
|
||||||
|
'task_ids': fields.one2many('project.task', 'project_id',
|
||||||
|
domain=[('stage_id.fold', '=', False)]),
|
||||||
'color': fields.integer('Color Index'),
|
'color': fields.integer('Color Index'),
|
||||||
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
|
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
|
||||||
help="Internal email associated with this project. Incoming emails are automatically synchronized"
|
help="Internal email associated with this project. Incoming emails are automatically synchronized"
|
||||||
|
@ -556,8 +560,9 @@ class task(osv.osv):
|
||||||
_mail_post_access = 'read'
|
_mail_post_access = 'read'
|
||||||
_track = {
|
_track = {
|
||||||
'stage_id': {
|
'stage_id': {
|
||||||
'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence == 1,
|
# this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
|
||||||
'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id.sequence != 1,
|
'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence <= 1,
|
||||||
|
'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id.sequence > 1,
|
||||||
},
|
},
|
||||||
'user_id': {
|
'user_id': {
|
||||||
'project.mt_task_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id,
|
'project.mt_task_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id,
|
||||||
|
@ -582,7 +587,7 @@ class task(osv.osv):
|
||||||
def _get_default_stage_id(self, cr, uid, context=None):
|
def _get_default_stage_id(self, cr, uid, context=None):
|
||||||
""" Gives default stage_id """
|
""" Gives default stage_id """
|
||||||
project_id = self._get_default_project_id(cr, uid, context=context)
|
project_id = self._get_default_project_id(cr, uid, context=context)
|
||||||
return self.stage_find(cr, uid, [], project_id, [('sequence', '=', '1')], context=context)
|
return self.stage_find(cr, uid, [], project_id, [('fold', '=', False)], context=context)
|
||||||
|
|
||||||
def _resolve_project_id_from_context(self, cr, uid, context=None):
|
def _resolve_project_id_from_context(self, cr, uid, context=None):
|
||||||
""" Returns ID of project based on the value of 'default_project_id'
|
""" Returns ID of project based on the value of 'default_project_id'
|
||||||
|
@ -994,7 +999,7 @@ class task(osv.osv):
|
||||||
|
|
||||||
def set_remaining_time(self, cr, uid, ids, remaining_time=1.0, context=None):
|
def set_remaining_time(self, cr, uid, ids, remaining_time=1.0, context=None):
|
||||||
for task in self.browse(cr, uid, ids, context=context):
|
for task in self.browse(cr, uid, ids, context=context):
|
||||||
if (task.stage_id and task.stage_id.sequence == 1) or (task.planned_hours == 0.0):
|
if (task.stage_id and task.stage_id.sequence <= 1) or (task.planned_hours == 0.0):
|
||||||
self.write(cr, uid, [task.id], {'planned_hours': remaining_time}, context=context)
|
self.write(cr, uid, [task.id], {'planned_hours': remaining_time}, context=context)
|
||||||
self.write(cr, uid, ids, {'remaining_hours': remaining_time}, context=context)
|
self.write(cr, uid, ids, {'remaining_hours': remaining_time}, context=context)
|
||||||
return True
|
return True
|
||||||
|
@ -1127,7 +1132,8 @@ class task(osv.osv):
|
||||||
|
|
||||||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||||
""" Override to updates the document according to the email. """
|
""" Override to updates the document according to the email. """
|
||||||
if custom_values is None: custom_values = {}
|
if custom_values is None:
|
||||||
|
custom_values = {}
|
||||||
defaults = {
|
defaults = {
|
||||||
'name': msg.get('subject'),
|
'name': msg.get('subject'),
|
||||||
'planned_hours': 0.0,
|
'planned_hours': 0.0,
|
||||||
|
@ -1137,10 +1143,10 @@ class task(osv.osv):
|
||||||
|
|
||||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
||||||
""" Override to update the task according to the email. """
|
""" Override to update the task according to the email. """
|
||||||
if update_vals is None: update_vals = {}
|
if update_vals is None:
|
||||||
act = False
|
update_vals = {}
|
||||||
maps = {
|
maps = {
|
||||||
'cost':'planned_hours',
|
'cost': 'planned_hours',
|
||||||
}
|
}
|
||||||
for line in msg['body'].split('\n'):
|
for line in msg['body'].split('\n'):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
|
@ -1153,9 +1159,7 @@ class task(osv.osv):
|
||||||
update_vals[field] = float(res.group(2).lower())
|
update_vals[field] = float(res.group(2).lower())
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
if act:
|
return super(task, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
||||||
getattr(self,act)(cr, uid, ids, context=context)
|
|
||||||
return super(task,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
|
||||||
|
|
||||||
class project_work(osv.osv):
|
class project_work(osv.osv):
|
||||||
_name = "project.task.work"
|
_name = "project.task.work"
|
||||||
|
@ -1243,6 +1247,8 @@ class account_analytic_account(osv.osv):
|
||||||
return analytic_account_id
|
return analytic_account_id
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
def write(self, cr, uid, ids, vals, context=None):
|
||||||
|
if isinstance(ids, (int, long)):
|
||||||
|
ids = [ids]
|
||||||
vals_for_project = vals.copy()
|
vals_for_project = vals.copy()
|
||||||
for account in self.browse(cr, uid, ids, context=context):
|
for account in self.browse(cr, uid, ids, context=context):
|
||||||
if not vals.get('name'):
|
if not vals.get('name'):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<openerp>
|
<openerp>
|
||||||
<data>
|
<data noupdate="1">
|
||||||
<!-- This will set the unit of measure used in projects and tasks.-->
|
<!-- This will set the unit of measure used in projects and tasks.-->
|
||||||
<record id="base.main_company" model="res.company">
|
<record id="base.main_company" model="res.company">
|
||||||
<field name="project_time_mode_id" ref="product.product_uom_hour"></field>
|
<field name="project_time_mode_id" ref="product.product_uom_hour"></field>
|
||||||
|
@ -63,14 +63,18 @@
|
||||||
<field name="name">Done</field>
|
<field name="name">Done</field>
|
||||||
<field name="case_default" eval="True"/>
|
<field name="case_default" eval="True"/>
|
||||||
<field name="fold" eval="True"/>
|
<field name="fold" eval="True"/>
|
||||||
|
<field name="closed" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="project_tt_cancel" model="project.task.type">
|
<record id="project_tt_cancel" model="project.task.type">
|
||||||
<field name="sequence">30</field>
|
<field name="sequence">30</field>
|
||||||
<field name="name">Cancelled</field>
|
<field name="name">Cancelled</field>
|
||||||
<field name="case_default" eval="True"/>
|
<field name="case_default" eval="True"/>
|
||||||
<field name="fold" eval="True"/>
|
<field name="fold" eval="True"/>
|
||||||
|
<field name="closed" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<data>
|
||||||
<!-- Task-related subtypes for messaging / Chatter -->
|
<!-- Task-related subtypes for messaging / Chatter -->
|
||||||
<record id="mt_task_new" model="mail.message.subtype">
|
<record id="mt_task_new" model="mail.message.subtype">
|
||||||
<field name="name">Task Created</field>
|
<field name="name">Task Created</field>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
<!-- Users -->
|
<!-- Users -->
|
||||||
<record id="base.user_demo" model="res.users">
|
<record id="base.user_demo" model="res.users">
|
||||||
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman')),(4, ref('group_project_user'))]"/>
|
<field name="groups_id" eval="[(4, ref('base.group_sale_salesman')),(4, ref('group_project_manager'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Categories -->
|
<!-- Categories -->
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<field name="name" string="Tasks"/>
|
<field name="name" string="Tasks"/>
|
||||||
<field name="categ_ids"/>
|
<field name="categ_ids"/>
|
||||||
<filter string="Unassigned" name="unassigned" domain="[('user_id', '=', False)]"/>
|
<filter string="Unassigned" name="unassigned" domain="[('user_id', '=', False)]"/>
|
||||||
<filter string="New" name="draft" domain="[('stage_id.sequence', '=', 1)]"/>
|
<filter string="New" name="draft" domain="[('stage_id.sequence', '<=', 1)]"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="My Tasks" domain="[('user_id','=',uid)]"/>
|
<filter string="My Tasks" domain="[('user_id','=',uid)]"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
|
@ -239,6 +239,7 @@
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="color"/>
|
<field name="color"/>
|
||||||
<field name="task_count"/>
|
<field name="task_count"/>
|
||||||
|
<field name="task_ids"/>
|
||||||
<field name="alias_id"/>
|
<field name="alias_id"/>
|
||||||
<field name="doc_count"/>
|
<field name="doc_count"/>
|
||||||
<templates>
|
<templates>
|
||||||
|
@ -259,8 +260,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_kanban_project_list">
|
<div class="oe_kanban_project_list">
|
||||||
<a t-if="record.use_tasks.raw_value" name="%(act_project_project_2_project_task_all)d" type="action" style="margin-right: 10px">
|
<a t-if="record.use_tasks.raw_value" name="%(act_project_project_2_project_task_all)d" type="action" style="margin-right: 10px">
|
||||||
<span t-if="record.task_count.raw_value gt 1"><field name="task_count"/> Tasks</span>
|
<t t-raw="record.task_ids.raw_value.length"/>
|
||||||
<span t-if="record.task_count.raw_value lt 2"><field name="task_count"/> Task</span>
|
<span t-if="record.task_ids.raw_value.length == 1">Task</span>
|
||||||
|
<span t-if="record.task_ids.raw_value.length > 1">Tasks</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_kanban_project_list">
|
<div class="oe_kanban_project_list">
|
||||||
|
@ -683,10 +685,10 @@
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="case_default"/>
|
<field name="sequence"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="sequence"/>
|
<field name="case_default"/>
|
||||||
<field name="fold"/>
|
<field name="fold"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -75,7 +75,7 @@ class report_project_task_user(osv.osv):
|
||||||
date_trunc('day',t.date_last_stage_update) as date_last_stage_update,
|
date_trunc('day',t.date_last_stage_update) as date_last_stage_update,
|
||||||
to_date(to_char(t.date_deadline, 'dd-MM-YYYY'),'dd-MM-YYYY') as date_deadline,
|
to_date(to_char(t.date_deadline, 'dd-MM-YYYY'),'dd-MM-YYYY') as date_deadline,
|
||||||
-- sum(cast(to_char(date_trunc('day',t.date_end) - date_trunc('day',t.date_start),'DD') as int)) as no_of_days,
|
-- sum(cast(to_char(date_trunc('day',t.date_end) - date_trunc('day',t.date_start),'DD') as int)) as no_of_days,
|
||||||
abs((extract('epoch' from (t.date_end-t.date_start)))/(3600*24)) as no_of_days,
|
abs((extract('epoch' from (t.write_date-t.date_start)))/(3600*24)) as no_of_days,
|
||||||
t.user_id,
|
t.user_id,
|
||||||
progress as progress,
|
progress as progress,
|
||||||
t.project_id,
|
t.project_id,
|
||||||
|
@ -89,9 +89,9 @@ class report_project_task_user(osv.osv):
|
||||||
total_hours as total_hours,
|
total_hours as total_hours,
|
||||||
t.delay_hours as hours_delay,
|
t.delay_hours as hours_delay,
|
||||||
planned_hours as hours_planned,
|
planned_hours as hours_planned,
|
||||||
(extract('epoch' from (t.date_end-t.create_date)))/(3600*24) as closing_days,
|
(extract('epoch' from (t.write_date-t.create_date)))/(3600*24) as closing_days,
|
||||||
(extract('epoch' from (t.date_start-t.create_date)))/(3600*24) as opening_days,
|
(extract('epoch' from (t.date_start-t.create_date)))/(3600*24) as opening_days,
|
||||||
abs((extract('epoch' from (t.date_deadline-t.date_end)))/(3600*24)) as delay_endings_days
|
abs((extract('epoch' from (t.date_deadline-t.write_date)))/(3600*24)) as delay_endings_days
|
||||||
FROM project_task t
|
FROM project_task t
|
||||||
WHERE t.active = 'true'
|
WHERE t.active = 'true'
|
||||||
GROUP BY
|
GROUP BY
|
||||||
|
@ -106,6 +106,7 @@ class report_project_task_user(osv.osv):
|
||||||
month,
|
month,
|
||||||
day,
|
day,
|
||||||
create_date,
|
create_date,
|
||||||
|
write_date,
|
||||||
date_start,
|
date_start,
|
||||||
date_end,
|
date_end,
|
||||||
date_deadline,
|
date_deadline,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<tasks>
|
<tasks>
|
||||||
<task type="zoom" name="tasks">
|
<task type="zoom" name="tasks">
|
||||||
<task_name type="field" name="name"/>
|
<task_name type="field" name="name"/>
|
||||||
<task_status type="field" name="state" />
|
|
||||||
<task_descritpion type="field" name="description"/>
|
<task_descritpion type="field" name="description"/>
|
||||||
<task_sequence type="field" name="sequence"/>
|
<task_sequence type="field" name="sequence"/>
|
||||||
<task_priority type="field" name="priority"/>
|
<task_priority type="field" name="priority"/>
|
||||||
|
|
|
@ -415,18 +415,20 @@ class project_issue(osv.Model):
|
||||||
return stage_ids[0]
|
return stage_ids[0]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def case_escalate(self, cr, uid, ids, context=None):
|
def case_escalate(self, cr, uid, ids, context=None): # FIXME rename this method to issue_escalate
|
||||||
cases = self.browse(cr, uid, ids)
|
for issue in self.browse(cr, uid, ids, context=context):
|
||||||
for case in cases:
|
|
||||||
data = {}
|
data = {}
|
||||||
if case.project_id.project_escalation_id:
|
esc_proj = issue.project_id.project_escalation_id
|
||||||
data['project_id'] = case.project_id.project_escalation_id.id
|
if not esc_proj:
|
||||||
if case.project_id.project_escalation_id.user_id:
|
|
||||||
data['user_id'] = case.project_id.project_escalation_id.user_id.id
|
|
||||||
if case.task_id:
|
|
||||||
self.pool.get('project.task').write(cr, uid, [case.task_id.id], {'project_id': data['project_id'], 'user_id': False})
|
|
||||||
else:
|
|
||||||
raise osv.except_osv(_('Warning!'), _('You cannot escalate this issue.\nThe relevant Project has not configured the Escalation Project!'))
|
raise osv.except_osv(_('Warning!'), _('You cannot escalate this issue.\nThe relevant Project has not configured the Escalation Project!'))
|
||||||
|
|
||||||
|
data['project_id'] = esc_proj.id
|
||||||
|
if esc_proj.user_id:
|
||||||
|
data['user_id'] = esc_proj.user_id.id
|
||||||
|
issue.write(data)
|
||||||
|
|
||||||
|
if issue.task_id:
|
||||||
|
issue.task_id.write({'project_id': esc_proj.id, 'user_id': False})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
|
@ -467,40 +469,10 @@ class project_issue(osv.Model):
|
||||||
'partner_id': msg.get('author_id', False),
|
'partner_id': msg.get('author_id', False),
|
||||||
'user_id': False,
|
'user_id': False,
|
||||||
}
|
}
|
||||||
if msg.get('priority'):
|
|
||||||
defaults['priority'] = msg.get('priority')
|
|
||||||
|
|
||||||
defaults.update(custom_values)
|
defaults.update(custom_values)
|
||||||
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||||
return res_id
|
return res_id
|
||||||
|
|
||||||
def message_update(self, cr, uid, ids, msg, update_vals=None, context=None):
|
|
||||||
""" Overrides mail_thread message_update that is called by the mailgateway
|
|
||||||
through message_process.
|
|
||||||
This method updates the document according to the email.
|
|
||||||
"""
|
|
||||||
if isinstance(ids, (str, int, long)):
|
|
||||||
ids = [ids]
|
|
||||||
if update_vals is None: update_vals = {}
|
|
||||||
|
|
||||||
# Update doc values according to the message
|
|
||||||
if msg.get('priority'):
|
|
||||||
update_vals['priority'] = msg.get('priority')
|
|
||||||
# Parse 'body' to find values to update
|
|
||||||
maps = {
|
|
||||||
'cost': 'planned_cost',
|
|
||||||
'revenue': 'planned_revenue',
|
|
||||||
'probability': 'probability',
|
|
||||||
}
|
|
||||||
for line in msg.get('body', '').split('\n'):
|
|
||||||
line = line.strip()
|
|
||||||
res = tools.command_re.match(line)
|
|
||||||
if res and maps.get(res.group(1).lower(), False):
|
|
||||||
key = maps.get(res.group(1).lower())
|
|
||||||
update_vals[key] = res.group(2).lower()
|
|
||||||
|
|
||||||
return super(project_issue, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context)
|
|
||||||
|
|
||||||
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs):
|
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', subtype=None, parent_id=False, attachments=None, context=None, content_subtype='html', **kwargs):
|
||||||
""" Overrides mail_thread message_post so that we can set the date of last action field when
|
""" Overrides mail_thread message_post so that we can set the date of last action field when
|
||||||
a new message is posted on the issue.
|
a new message is posted on the issue.
|
||||||
|
@ -520,6 +492,8 @@ class project(osv.Model):
|
||||||
return [('project.task', "Tasks"), ("project.issue", "Issues")]
|
return [('project.task', "Tasks"), ("project.issue", "Issues")]
|
||||||
|
|
||||||
def _issue_count(self, cr, uid, ids, field_name, arg, context=None):
|
def _issue_count(self, cr, uid, ids, field_name, arg, context=None):
|
||||||
|
""" :deprecated: this method will be removed with OpenERP v8. Use issue_ids
|
||||||
|
fields instead. """
|
||||||
res = dict.fromkeys(ids, 0)
|
res = dict.fromkeys(ids, 0)
|
||||||
issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)])
|
issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)])
|
||||||
for issue in self.pool.get('project.issue').browse(cr, uid, issue_ids, context):
|
for issue in self.pool.get('project.issue').browse(cr, uid, issue_ids, context):
|
||||||
|
@ -531,7 +505,10 @@ class project(osv.Model):
|
||||||
'project_escalation_id': fields.many2one('project.project', 'Project Escalation',
|
'project_escalation_id': fields.many2one('project.project', 'Project Escalation',
|
||||||
help='If any issue is escalated from the current Project, it will be listed under the project selected here.',
|
help='If any issue is escalated from the current Project, it will be listed under the project selected here.',
|
||||||
states={'close': [('readonly', True)], 'cancelled': [('readonly', True)]}),
|
states={'close': [('readonly', True)], 'cancelled': [('readonly', True)]}),
|
||||||
'issue_count': fields.function(_issue_count, type='integer', string="Unclosed Issues"),
|
'issue_count': fields.function(_issue_count, type='integer', string="Unclosed Issues",
|
||||||
|
deprecated="This field will be removed in OpenERP v8. Use issue_ids one2many field instead."),
|
||||||
|
'issue_ids': fields.one2many('project.issue', 'project_id',
|
||||||
|
domain=[('stage_id.fold', '=', False)])
|
||||||
}
|
}
|
||||||
|
|
||||||
def _check_escalation(self, cr, uid, ids, context=None):
|
def _check_escalation(self, cr, uid, ids, context=None):
|
||||||
|
|
|
@ -325,13 +325,14 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="use_tasks" position="after">
|
<field name="use_tasks" position="after">
|
||||||
<field name="use_issues"/>
|
<field name="use_issues"/>
|
||||||
<field name="issue_count" invisible="1"/>
|
<field name="issue_ids" invisible="1"/>
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//div[contains(@class, 'oe_kanban_project_list')]" position="inside">
|
<xpath expr="//div[contains(@class, 'oe_kanban_project_list')]" position="inside">
|
||||||
<a t-if="record.use_issues.raw_value" style="margin-right: 10px"
|
<a t-if="record.use_issues.raw_value" style="margin-right: 10px"
|
||||||
name="%(act_project_project_2_project_issue_all)d" type="action">
|
name="%(act_project_project_2_project_issue_all)d" type="action">
|
||||||
<span t-if="record.issue_count.raw_value gt 1"><field name="issue_count"/> Issues</span>
|
<t t-raw="record.issue_ids.raw_value.length"/>
|
||||||
<span t-if="record.issue_count.raw_value lt 2"><field name="issue_count"/> Issue</span>
|
<span t-if="record.issue_ids.raw_value.length == 1">Issue</span>
|
||||||
|
<span t-if="record.issue_ids.raw_value.length > 1">Issues</span>
|
||||||
</a>
|
</a>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
@ -50,10 +50,8 @@
|
||||||
`project_mrp` implements a basic procurement system for services without actually using the
|
`project_mrp` implements a basic procurement system for services without actually using the
|
||||||
full-fledged procurement process from sale_stock, and without the dependency. So it stil
|
full-fledged procurement process from sale_stock, and without the dependency. So it stil
|
||||||
represents a "procurement system".
|
represents a "procurement system".
|
||||||
TODO: To cleanup this invalid foreign external ID, the node should probably be moved to the
|
|
||||||
`sale` module directly, and removed from both `sale_stock` and `project_mrp`.
|
|
||||||
-->
|
-->
|
||||||
<record id="sale_stock.process_node_saleprocurement0" model="process.node">
|
<record id="procurement.process_node_saleprocurement0" model="process.node">
|
||||||
<field name="menu_id" ref="procurement.menu_stock_procurement_action"/>
|
<field name="menu_id" ref="procurement.menu_stock_procurement_action"/>
|
||||||
<field name="model_id" ref="procurement.model_procurement_order"/>
|
<field name="model_id" ref="procurement.model_procurement_order"/>
|
||||||
<field name="kind">subflow</field>
|
<field name="kind">subflow</field>
|
||||||
|
@ -68,7 +66,7 @@
|
||||||
<field eval=""""Procurement Task"""" name="name"/>
|
<field eval=""""Procurement Task"""" name="name"/>
|
||||||
<field eval=""""if product type is 'service' then it creates the task."""" name="note"/>
|
<field eval=""""if product type is 'service' then it creates the task."""" name="note"/>
|
||||||
<field name="target_node_id" ref="process_node_procuretasktask0"/>
|
<field name="target_node_id" ref="process_node_procuretasktask0"/>
|
||||||
<field name="source_node_id" ref="sale_stock.process_node_saleprocurement0"/>
|
<field name="source_node_id" ref="procurement.process_node_saleprocurement0"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="process_transition_createtask0" model="process.transition">
|
<record id="process_transition_createtask0" model="process.transition">
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<!--Email template -->
|
<!--Email template -->
|
||||||
<record id="email_template_edi_purchase" model="email.template">
|
<record id="email_template_edi_purchase" model="email.template">
|
||||||
<field name="name">Purchase Order - Send by mail</field>
|
<field name="name">Purchase Order - Send by mail</field>
|
||||||
<field name="email_from">${object.validator.email or ''}</field>
|
<field name="email_from">${(object.validator.email or '')|safe}</field>
|
||||||
<field name="subject">${object.company_id.name} Order (Ref ${object.name or 'n/a' })</field>
|
<field name="subject">${object.company_id.name} Order (Ref ${object.name or 'n/a' })</field>
|
||||||
<field name="partner_to">${object.partner_id.id}</field>
|
<field name="partner_to">${object.partner_id.id}</field>
|
||||||
<field name="model_id" ref="purchase.model_purchase_order"/>
|
<field name="model_id" ref="purchase.model_purchase_order"/>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue