[MERGE] from trunk
bzr revid: fva@openerp.com-20131126142328-26gdibac45v17djm
This commit is contained in:
commit
28c074dcb2
|
@ -1447,6 +1447,8 @@ class account_move(osv.osv):
|
|||
def unlink(self, cr, uid, ids, context=None, check=True):
|
||||
if context is None:
|
||||
context = {}
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
toremove = []
|
||||
obj_move_line = self.pool.get('account.move.line')
|
||||
for move in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -1928,7 +1930,7 @@ class account_tax(osv.osv):
|
|||
'child_depend':fields.boolean('Tax on Children', help="Set if the tax computation is based on the computation of child taxes rather than on the total amount."),
|
||||
'python_compute':fields.text('Python Code'),
|
||||
'python_compute_inv':fields.text('Python Code (reverse)'),
|
||||
'python_applicable':fields.text('Python Code'),
|
||||
'python_applicable':fields.text('Applicable Code'),
|
||||
|
||||
#
|
||||
# Fields used for the Tax declaration
|
||||
|
@ -1942,8 +1944,8 @@ class account_tax(osv.osv):
|
|||
|
||||
'ref_base_code_id': fields.many2one('account.tax.code', 'Refund Base Code', help="Use this code for the tax declaration."),
|
||||
'ref_tax_code_id': fields.many2one('account.tax.code', 'Refund Tax Code', help="Use this code for the tax declaration."),
|
||||
'ref_base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
|
||||
'ref_tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
|
||||
'ref_base_sign': fields.float('Refund Base Code Sign', help="Usually 1 or -1."),
|
||||
'ref_tax_sign': fields.float('Refund Tax Code Sign', help="Usually 1 or -1."),
|
||||
'include_base_amount': fields.boolean('Included in base amount', help="Indicates if the amount of tax must be included in the base amount for the computation of the next taxes"),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'description': fields.char('Tax Code'),
|
||||
|
@ -2833,7 +2835,7 @@ class account_tax_template(osv.osv):
|
|||
'child_depend':fields.boolean('Tax on Children', help="Set if the tax computation is based on the computation of child taxes rather than on the total amount."),
|
||||
'python_compute':fields.text('Python Code'),
|
||||
'python_compute_inv':fields.text('Python Code (reverse)'),
|
||||
'python_applicable':fields.text('Python Code'),
|
||||
'python_applicable':fields.text('Applicable Code'),
|
||||
|
||||
#
|
||||
# Fields used for the Tax declaration
|
||||
|
@ -2847,8 +2849,8 @@ class account_tax_template(osv.osv):
|
|||
|
||||
'ref_base_code_id': fields.many2one('account.tax.code.template', 'Refund Base Code', help="Use this code for the tax declaration."),
|
||||
'ref_tax_code_id': fields.many2one('account.tax.code.template', 'Refund Tax Code', help="Use this code for the tax declaration."),
|
||||
'ref_base_sign': fields.float('Base Code Sign', help="Usually 1 or -1."),
|
||||
'ref_tax_sign': fields.float('Tax Code Sign', help="Usually 1 or -1."),
|
||||
'ref_base_sign': fields.float('Refund Base Code Sign', help="Usually 1 or -1."),
|
||||
'ref_tax_sign': fields.float('Refund Tax Code Sign', help="Usually 1 or -1."),
|
||||
'include_base_amount': fields.boolean('Include in Base Amount', help="Set if the amount of tax must be included in the base amount before computing the next taxes."),
|
||||
'description': fields.char('Internal Name'),
|
||||
'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Use In', required=True,),
|
||||
|
|
|
@ -311,13 +311,13 @@ class account_move_line(osv.osv):
|
|||
context = {}
|
||||
c = context.copy()
|
||||
c['initital_bal'] = True
|
||||
sql = """SELECT l2.id, SUM(l1.debit-l1.credit)
|
||||
FROM account_move_line l1, account_move_line l2
|
||||
WHERE l2.account_id = l1.account_id
|
||||
AND l1.id <= l2.id
|
||||
AND l2.id IN %s AND """ + \
|
||||
self._query_get(cr, uid, obj='l1', context=c) + \
|
||||
" GROUP BY l2.id"
|
||||
sql = """SELECT l1.id, COALESCE(SUM(l2.debit-l2.credit), 0)
|
||||
FROM account_move_line l1 LEFT JOIN account_move_line l2
|
||||
ON (l1.account_id = l2.account_id
|
||||
AND l2.id <= l1.id
|
||||
AND """ + \
|
||||
self._query_get(cr, uid, obj='l2', context=c) + \
|
||||
") WHERE l1.id IN %s GROUP BY l1.id"
|
||||
|
||||
cr.execute(sql, [tuple(ids)])
|
||||
return dict(cr.fetchall())
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
</record>
|
||||
|
||||
<record id="account_payment_term_line_immediate" model="account.payment.term.line">
|
||||
<field name="name">Immediate Payment</field>
|
||||
<field name="value">balance</field>
|
||||
<field eval="0" name="days"/>
|
||||
<field eval="0" name="days2"/>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<!--Email template -->
|
||||
<record id="email_template_edi_invoice" model="email.template">
|
||||
<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="partner_to">${object.partner_id.id}</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
|
|
|
@ -107,14 +107,15 @@ class res_partner(osv.osv):
|
|||
_description = 'Partner'
|
||||
|
||||
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)
|
||||
FROM account_move_line l
|
||||
LEFT JOIN account_account a ON (l.account_id=a.id)
|
||||
WHERE a.type IN ('receivable','payable')
|
||||
AND l.partner_id IN %s
|
||||
AND (l.reconcile_id IS NULL OR
|
||||
reconcile_id in (SELECT id FROM account_move_reconcile WHERE opening_reconciliation is TRUE))
|
||||
AND l.reconcile_id IS NULL
|
||||
AND """ + query + """
|
||||
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="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_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_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"/>
|
||||
|
|
|
@ -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)
|
||||
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 = {
|
||||
'date': lambda *a: time.strftime('%Y-%m-%d'),
|
||||
'journal_id': _get_journal,
|
||||
'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):
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
<record id="account_analytic_cron_email_template" model="email.template">
|
||||
<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="email_to">${object.email}</field>
|
||||
<field name="email_to">${object.email|safe}</field>
|
||||
<field name="lang">${object.lang}</field>
|
||||
<field name="model_id" ref="base.model_res_users"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
|
|
@ -182,19 +182,19 @@
|
|||
<blockTable colWidths="221.0,82.0,83.0,85.0,57.0" style="Table4">
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -145,19 +145,19 @@
|
|||
<blockTable colWidths="185.0,79.0,78.0,81.0,59.0" style="Table4">
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -160,19 +160,19 @@
|
|||
<blockTable colWidths="205.0,88.0,87.0,90.0,66.0" style="Table4">
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
<!--Mail template level 0-->
|
||||
<record id="email_template_account_followup_level0" model="email.template">
|
||||
<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="email_to">${object.email}</field>
|
||||
<field name="email_to">${object.email|safe}</field>
|
||||
<field name="lang">${object.lang}</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
@ -45,9 +45,9 @@ ${object.get_followup_table_html() | safe}
|
|||
<!--Mail template level 1 -->
|
||||
<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="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="email_to">${object.email}</field>
|
||||
<field name="email_to">${object.email|safe}</field>
|
||||
<field name="lang">${object.lang}</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
@ -85,9 +85,9 @@ ${object.get_followup_table_html() | safe}
|
|||
<!--Mail template level 2 -->
|
||||
<record id="email_template_account_followup_level2" model="email.template">
|
||||
<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="email_to">${object.email}</field>
|
||||
<field name="email_to">${object.email|safe}</field>
|
||||
<field name="lang">${object.lang}</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
@ -122,9 +122,9 @@ ${object.get_followup_table_html() | safe}
|
|||
<!-- Default follow up message -->
|
||||
<record id="email_template_account_followup_default" model="email.template">
|
||||
<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="email_to">${object.email}</field>
|
||||
<field name="email_to">${object.email|safe}</field>
|
||||
<field name="lang">${object.lang}</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
|
@ -162,7 +162,7 @@ ${object.get_followup_table_html() | safe}
|
|||
<field name="sequence">0</field>
|
||||
<field name="delay">15</field>
|
||||
<field name="followup_id" ref="demo_followup1"/>
|
||||
<field name="send-email">True</field>
|
||||
<field name="send_email">True</field>
|
||||
<field name="description">
|
||||
Dear %(partner_name)s,
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ _logger = logging.getLogger(__name__)
|
|||
#----------------------------------------------------------
|
||||
def fragment_to_query_string(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(self, **kw):
|
||||
def wrapper(self, *a, **kw):
|
||||
if not kw:
|
||||
return """<html><head><script>
|
||||
var l = window.location;
|
||||
|
@ -31,7 +31,7 @@ def fragment_to_query_string(func):
|
|||
}
|
||||
window.location = r;
|
||||
</script></head><body></body></html>"""
|
||||
return func(self, **kw)
|
||||
return func(self, *a, **kw)
|
||||
return wrapper
|
||||
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
<record id="reset_password_email" model="email.template">
|
||||
<field name="name">Reset Password</field>
|
||||
<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_to">${object.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|safe}</field>
|
||||
<field name="subject">Password reset</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<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">
|
||||
<field name="name">OpenERP Enterprise Connection</field>
|
||||
<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_to">${object.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|safe}</field>
|
||||
<field name="subject"><![CDATA[${object.company_id.name} invitation to connect on OpenERP]]></field>
|
||||
<field name="body_html">
|
||||
<![CDATA[
|
||||
|
|
|
@ -39,12 +39,6 @@ openerp.auth_signup = function(instance) {
|
|||
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) {
|
||||
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);
|
||||
|
||||
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.reset_password_enabled = result.reset_password;
|
||||
if (!self.signup_enabled || self.$("form input[name=login]").val()){
|
||||
|
@ -61,6 +55,13 @@ openerp.auth_signup = function(instance) {
|
|||
} else {
|
||||
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 {
|
||||
// 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
|
||||
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_lead_test,access_base_action_rule_lead_test,model_base_action_rule_lead_test,base.group_system,1,1,1,1
|
||||
|
|
|
|
@ -425,6 +425,7 @@ property or property parameter."),
|
|||
if event_obj.rrule:
|
||||
event.add('rrule').value = event_obj.rrule
|
||||
if event_obj.organizer:
|
||||
# deprecated: will be removed with OpenERP v8: use organizer_id instead
|
||||
event_org = event.add('organizer')
|
||||
event_org.params['CN'] = [event_obj.organizer]
|
||||
event_org.value = 'MAILTO:' + (event_obj.organizer)
|
||||
|
@ -1037,7 +1038,8 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
'recurrent_id_date': fields.datetime('Recurrent ID date'),
|
||||
'vtimezone': fields.selection(_tz_get, size=64, string='Timezone'),
|
||||
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
|
||||
'organizer': fields.char("Organizer", size=256, states={'done': [('readonly', True)]}), # Map with organizer attribute of VEvent.
|
||||
'organizer': fields.char("Organizer (deprecated)", size=256, states={'done': [('readonly', True)]},
|
||||
deprecated='Will be removed with OpenERP v8; use organizer_id field instead'), # Map with organizer attribute of VEvent.
|
||||
'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}),
|
||||
'end_type' : fields.selection([('count', 'Number of repetitions'), ('end_date','End date')], 'Recurrence Termination'),
|
||||
'interval': fields.integer('Repeat Every', help="Repeat every (Days/Week/Month/Year)"),
|
||||
|
@ -1112,6 +1114,10 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
return True
|
||||
|
||||
def default_organizer(self, cr, uid, context=None):
|
||||
"""
|
||||
.. deprecated:: 8.0
|
||||
Use organizer_id field and its default value instead.
|
||||
"""
|
||||
user_pool = self.pool.get('res.users')
|
||||
user = user_pool.browse(cr, uid, uid, context=context)
|
||||
res = user.name
|
||||
|
@ -1130,7 +1136,6 @@ rule or repeating pattern of time to exclude from the recurring rule."),
|
|||
'interval': 1,
|
||||
'active': 1,
|
||||
'user_id': lambda self, cr, uid, ctx: uid,
|
||||
'organizer': default_organizer,
|
||||
}
|
||||
|
||||
def _check_closing_date(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -71,7 +71,6 @@
|
|||
<field name="user_id" groups="base.group_no_one" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
|
||||
<field name="categ_ids" widget="many2many_tags"/>
|
||||
<field name="location"/>
|
||||
<field name="organizer" groups="base.group_no_one"/>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
|
|
|
@ -51,7 +51,12 @@ openerp.base_import = function (instance) {
|
|||
type: 'ir.actions.client',
|
||||
tag: 'import',
|
||||
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 () {
|
||||
|
@ -127,6 +132,7 @@ openerp.base_import = function (instance) {
|
|||
var self = this;
|
||||
this._super.apply(this, arguments);
|
||||
this.res_model = action.params.model;
|
||||
this.parent_context = action.params.context || {};
|
||||
// import object id
|
||||
this.id = null;
|
||||
this.Import = new instance.web.Model('base_import.import');
|
||||
|
@ -353,11 +359,12 @@ openerp.base_import = function (instance) {
|
|||
},
|
||||
|
||||
//- 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) {
|
||||
return $(el).select2('val') || false;
|
||||
}).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) {
|
||||
// In case of unexpected exception, convert
|
||||
// "JSON-RPC error" to an import failure, and
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# 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
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -49,6 +49,7 @@ class board_board(osv.osv):
|
|||
('value', 'in', refs),
|
||||
], 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)
|
||||
return [dict(id=m[0], name=m[1]) for m in menu_names]
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import openerp
|
||||
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):
|
||||
@openerp.http.route('/board/add_to_dashboard', type='json', auth='user')
|
||||
class Board(Controller):
|
||||
@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=''):
|
||||
req = openerp.http.request
|
||||
# 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:
|
||||
action = dashboard_action[0][2]
|
||||
if action['res_model'] == 'board.board' and action['views'][0][1] == 'form':
|
||||
# Maybe should check the content instead of model board.board ?
|
||||
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:
|
||||
xml = ElementTree.fromstring(board['arch'])
|
||||
column = xml.find('./board/column')
|
||||
|
@ -30,10 +30,10 @@ class Board(openerp.http.Controller):
|
|||
})
|
||||
column.insert(0, new_action)
|
||||
arch = ElementTree.tostring(xml, 'utf-8')
|
||||
return req.session.model('ir.ui.view.custom').create({
|
||||
'user_id': req.session._uid,
|
||||
return request.session.model('ir.ui.view.custom').create({
|
||||
'user_id': request.session.uid,
|
||||
'ref_id': view_id,
|
||||
'arch': arch
|
||||
}, req.context)
|
||||
}, request.context)
|
||||
|
||||
return False
|
||||
|
|
|
@ -20,10 +20,7 @@
|
|||
<field name="view_mode">graph,tree,form</field>
|
||||
<field name="view_id" ref="view_crm_opportunity_stage_graph"/>
|
||||
<!-- avoid done / cancelled -->
|
||||
<field name="domain">['|',
|
||||
'!', '&', ('probability', '=', 100), ('stage_id.on_change', '=', 1),
|
||||
'!', '&', ('probability', '=', 0), ('stage_id.sequence', '!=', 1),
|
||||
('type', '=', 'opportunity')]</field>
|
||||
<field name="domain">['&', ('stage_id.fold', '=', False), ('type', '=', 'opportunity')]</field>
|
||||
<field name="context">{'search_default_Stage':1}</field>
|
||||
</record>
|
||||
|
||||
|
@ -48,7 +45,7 @@
|
|||
<field name="view_mode">graph,tree,form</field>
|
||||
<field name="view_id" ref="view_crm_opportunity_user_stage_graph"/>
|
||||
<!-- 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>
|
||||
</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."),
|
||||
'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."),
|
||||
'fold': fields.boolean('Fold by Default',
|
||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
'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.'),
|
||||
'type': fields.selection([('lead', 'Lead'),
|
||||
('opportunity', 'Opportunity'),
|
||||
('both', 'Both')],
|
||||
|
@ -78,8 +79,8 @@ class crm_case_stage(osv.osv):
|
|||
}
|
||||
|
||||
_defaults = {
|
||||
'sequence': lambda *args: 1,
|
||||
'probability': lambda *args: 0.0,
|
||||
'sequence': 1,
|
||||
'probability': 0.0,
|
||||
'on_change': True,
|
||||
'fold': False,
|
||||
'type': 'both',
|
||||
|
|
|
@ -72,10 +72,11 @@ class crm_lead(format_address, osv.osv):
|
|||
|
||||
_track = {
|
||||
'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,
|
||||
'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_won': lambda self, cr, uid, obj, ctx=None: obj.probability == 100 and obj.stage_id and obj.stage_id.on_change,
|
||||
'crm.mt_lead_lost': 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_create': lambda self, cr, uid, obj, ctx=None: obj.probability == 0 and obj.stage_id and obj.stage_id.sequence <= 1,
|
||||
'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_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):
|
||||
""" Gives default stage_id """
|
||||
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):
|
||||
""" 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
|
||||
search_domain += list(domain)
|
||||
# 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:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def case_mark_lost(self, cr, uid, ids, context=None):
|
||||
""" Mark the case as lost: state=cancel and probability=0 """
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
|
||||
""" Mark the case as lost: state=cancel and probability=0
|
||||
:deprecated: this method will be removed in OpenERP v8.
|
||||
"""
|
||||
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:
|
||||
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:
|
||||
raise osv.except_osv(_('Warning!'),
|
||||
_('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'
|
||||
'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):
|
||||
""" Mark the case as won: state=done and probability=100 """
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
|
||||
""" Mark the case as won: state=done and probability=100
|
||||
:deprecated: this method will be removed in OpenERP v8.
|
||||
"""
|
||||
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:
|
||||
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:
|
||||
raise osv.except_osv(_('Warning!'),
|
||||
_('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'
|
||||
'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):
|
||||
""" 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
|
||||
for opportunity in opportunities:
|
||||
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
|
||||
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,
|
||||
}
|
||||
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
|
||||
|
||||
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)
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
# 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
|
||||
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, 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')
|
||||
phonecall_dict = {}
|
||||
if not categ_id:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
if res_id:
|
||||
try:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
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):
|
||||
if not section_id:
|
||||
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)
|
||||
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
|
||||
# ----------------------------------------
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
<record model="crm.case.stage" id="stage_lead6">
|
||||
<field name="name">Won</field>
|
||||
<field name="case_default">1</field>
|
||||
<field name="fold">1</field>
|
||||
<field name="probability">100</field>
|
||||
<field name="on_change">1</field>
|
||||
<field name="sequence">70</field>
|
||||
|
@ -203,7 +204,7 @@
|
|||
<field name="model_id" ref="crm.model_crm_lead"/>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
<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>
|
||||
</record>
|
||||
<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="auto_delete" eval="True"/>
|
||||
<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="body_html"><![CDATA[<p>This opportunity did not have any activity since at least 5 days. Here are some details:</p>
|
||||
<ul>
|
||||
|
|
|
@ -323,7 +323,7 @@
|
|||
<field name="model">crm.lead</field>
|
||||
<field name="arch" type="xml">
|
||||
<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="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
|
||||
<field name="user_id"/>
|
||||
|
@ -334,14 +334,14 @@
|
|||
<filter string="Unassigned" name="unassigned"
|
||||
domain="[('user_id','=', False)]"
|
||||
help="No salesperson"/>
|
||||
<filter string="Assigned to Me"
|
||||
<filter string="My Leads"
|
||||
domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
|
||||
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}"
|
||||
help="Leads that are assigned to any sales teams I am member of"/>
|
||||
<filter string="Dead" name="dead"
|
||||
domain="[('probability', '=', '0'), ('stage_id.sequence', '!=', 1)]"/>
|
||||
domain="[('probability', '=', '0'), ('stage_id.fold', '=', True)]"/>
|
||||
<separator />
|
||||
<filter string="Available for mass mailing"
|
||||
name='not_opt_out' domain="[('opt_out', '=', False)]"
|
||||
|
@ -379,10 +379,12 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Opportunities" version="7.0">
|
||||
<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"
|
||||
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"
|
||||
attrs="{'invisible': ['|', ('probability', '=', 0), ('probability', '=', 100)]}"/>
|
||||
invisible="True"/>
|
||||
<field name="stage_id" widget="statusbar" clickable="True"
|
||||
domain="['&', ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
|
||||
</header>
|
||||
|
@ -550,18 +552,16 @@
|
|||
<field name="stage_id" domain="[]"/>
|
||||
<field name="probability"/>
|
||||
<separator/>
|
||||
<filter string="New" name="new"
|
||||
domain="[('probability', '=', 0), ('stage_id.sequence', '=', 1)]"/>
|
||||
<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"
|
||||
domain="[('probability', '=', 0), ('stage_id.sequence', '!=', 1)]"/>
|
||||
domain="[('probability', '=', 0), ('stage_id.fold', '=', True)]"/>
|
||||
<filter string="Unassigned" name="unassigned"
|
||||
domain="[('user_id','=', False)]" help="No salesperson"/>
|
||||
<filter string="My Opportunities" name="assigned_to_me"
|
||||
domain="[('user_id', '=', uid)]" context="{'invisible_section': False}"
|
||||
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}"
|
||||
help="Opportunities that are assigned to any sales teams I am member of"/>
|
||||
<separator/>
|
||||
|
@ -600,7 +600,7 @@
|
|||
id="crm.action_lead_mass_mail"
|
||||
context="{
|
||||
'default_composition_mode': 'mass_mail',
|
||||
'default_email_to':'{$object.email or \'\'}',
|
||||
'default_email_to':'{($object.email or \'\')|safe}',
|
||||
'default_use_template': True,
|
||||
'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')
|
||||
phonecall_dict = {}
|
||||
if not categ_id:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
if res_id:
|
||||
try:
|
||||
res_id = model_data._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
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):
|
||||
if not section_id:
|
||||
section_id = call.section_id and call.section_id.id or False
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_id"
|
||||
on_change="onchange_partner_id(partner_id)"/>
|
||||
on_change="on_change_partner_id(partner_id)"/>
|
||||
<field name="partner_phone"
|
||||
invisible="1"/>
|
||||
<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="arch" type="xml">
|
||||
<form string="Stage" version="7.0">
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="probability"/>
|
||||
<field name="type"/>
|
||||
<field name="on_change"/>
|
||||
<field name="sequence"/>
|
||||
<field name="case_default" groups="base.group_multi_salesteams"/>
|
||||
<field name="fold"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="sequence"/>
|
||||
<field name="type"/>
|
||||
<field name="probability"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="fold"/>
|
||||
<field name="on_change"/>
|
||||
<field name="case_default" groups="base.group_multi_salesteams"/>
|
||||
</group>
|
||||
|
||||
</group>
|
||||
<separator string="Requirements"/>
|
||||
<field name="requirements" nolabel="1"/>
|
||||
|
|
|
@ -59,11 +59,11 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
|
||||
if partner_id:
|
||||
# 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:
|
||||
tomerge.add(id)
|
||||
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:
|
||||
tomerge.add(id)
|
||||
|
||||
|
|
|
@ -34,9 +34,11 @@ class crm_opportunity2phonecall(osv.osv_memory):
|
|||
opp_obj = self.pool.get('crm.lead')
|
||||
categ_id = False
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
if res_id:
|
||||
try:
|
||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
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 []
|
||||
res = {}
|
||||
|
|
|
@ -78,9 +78,11 @@ class crm_phonecall2phonecall(osv.osv_memory):
|
|||
|
||||
categ_id = False
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
if res_id:
|
||||
try:
|
||||
res_id = data_obj._get_id(cr, uid, 'crm', 'categ_phone2')
|
||||
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if 'name' in fields:
|
||||
res.update({'name': phonecall.name})
|
||||
|
|
|
@ -173,7 +173,8 @@ class crm_claim(osv.osv):
|
|||
through message_process.
|
||||
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 ''
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
|
@ -185,33 +186,7 @@ class crm_claim(osv.osv):
|
|||
if msg.get('priority'):
|
||||
defaults['priority'] = msg.get('priority')
|
||||
defaults.update(custom_values)
|
||||
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)
|
||||
return super(crm_claim, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
class res_partner(osv.osv):
|
||||
_inherit = 'res.partner'
|
||||
|
|
|
@ -127,7 +127,8 @@ class crm_helpdesk(osv.osv):
|
|||
through message_process.
|
||||
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 ''
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
|
@ -138,32 +139,6 @@ class crm_helpdesk(osv.osv):
|
|||
'partner_id': msg.get('author_id', False),
|
||||
}
|
||||
defaults.update(custom_values)
|
||||
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)
|
||||
return super(crm_helpdesk, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -21,20 +21,17 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Partners Geo-Localization',
|
||||
'name': 'CRM Geolocation',
|
||||
'version': '1.0',
|
||||
'category': 'Customer Relationship Management',
|
||||
'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.
|
||||
Determine the GPS coordinates according to the address of the partner.
|
||||
|
||||
The most appropriate partner can be assigned.
|
||||
You can also use the geolocalization without using the GPS coordinates.
|
||||
Once the coordinates of the Lead/Opportunity is known, they can be automatically assigned
|
||||
to an appropriate local partner, based on the distance and the weight that was assigned to the partner.
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['crm', 'account', 'portal'],
|
||||
|
|
|
@ -42,3 +42,17 @@ class crm_lead(osv.osv):
|
|||
|
||||
def case_disinterested(self, cr, uid, ids, context=None):
|
||||
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'}"/>
|
||||
|
||||
</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_assigned_id"/>
|
||||
</field>
|
||||
|
@ -131,11 +134,40 @@
|
|||
<filter string="Team" position="after">
|
||||
<filter string="Assigned Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_assigned_id'}"/>
|
||||
</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_assigned_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</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>
|
||||
</openerp>
|
||||
|
|
|
@ -179,23 +179,27 @@ class crm_lead(osv.osv):
|
|||
return res
|
||||
|
||||
def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
|
||||
# Don't pass context to browse()! We need country name in english below
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
if not lead.country_id:
|
||||
continue
|
||||
result = geo_find(geo_query_address(street=lead.street,
|
||||
zip=lead.zip,
|
||||
city=lead.city,
|
||||
state=lead.state_id.name,
|
||||
country=lead.country_id.name))
|
||||
if not latitude and result:
|
||||
latitude = result[0]
|
||||
if not longitude and result:
|
||||
longitude = result[1]
|
||||
self.write(cr, uid, [lead.id], {
|
||||
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
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
if lead.partner_latitude and lead.partner_longitude:
|
||||
continue
|
||||
if lead.country_id:
|
||||
result = geo_find(geo_query_address(street=lead.street,
|
||||
zip=lead.zip,
|
||||
city=lead.city,
|
||||
state=lead.state_id.name,
|
||||
country=lead.country_id.name))
|
||||
if result:
|
||||
self.write(cr, uid, [lead.id], {
|
||||
'partner_latitude': result[0],
|
||||
'partner_longitude': result[1]
|
||||
}, context=context)
|
||||
return True
|
||||
|
||||
def search_geo_partner(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
<record model="crm.case.stage" id="stage_portal_lead_assigned">
|
||||
<field name="name">Assigned</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="0" name="probability"/>
|
||||
<field eval="10" name="probability"/>
|
||||
<field eval="12" name="sequence"/>
|
||||
<field name="type">lead</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_portal_lead_recycle">
|
||||
<field name="name">To Recycle</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="0" name="probability"/>
|
||||
<field eval="5" name="probability"/>
|
||||
<field eval="11" name="sequence"/>
|
||||
<field name="type">lead</field>
|
||||
</record>
|
||||
|
@ -19,8 +19,8 @@
|
|||
<field name="name">Lead Mass Mail</field>
|
||||
<field name="model_id" model="ir.model" search="[('name', '=', 'crm.lead.forward.to.partner')]"></field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
<field name="email_to">${ctx['partner_id'].email}</field>
|
||||
<field name="email_from">${user.email or ''}</field>
|
||||
<field name="email_to">${ctx['partner_id'].email|safe}</field>
|
||||
<field name="email_from">${(user.email or '')|safe}</field>
|
||||
<field name="subject">Fwd: Lead: ${ctx['partner_id'].name}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
<ol>
|
||||
% 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
|
||||
</ol>
|
||||
|
||||
|
@ -56,4 +56,4 @@ PS: It looks like you do not have an account manager assigned to you, please con
|
|||
]]></field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
|
|
@ -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
|
||||
# FIXME: this is a temporary workaround because of a framework bug (ref: lp996816). It should be removed as soon as
|
||||
# the bug is fixed
|
||||
|
||||
# TODO in trunk: Remove the duplication below using a mixin class!
|
||||
|
||||
class stock_picking_out(osv.osv):
|
||||
_inherit = 'stock.picking.out'
|
||||
|
||||
|
@ -212,6 +215,7 @@ class stock_picking_out(osv.osv):
|
|||
}),
|
||||
'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",),
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
_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',
|
||||
store={
|
||||
'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.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:
|
||||
|
|
|
@ -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,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_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) {
|
||||
//to display number in name if more then one attachment which has same name.
|
||||
var self = this;
|
||||
_.chain(attachments.reverse())
|
||||
_.chain(attachments)
|
||||
.groupBy(function(attachment) { return attachment.name})
|
||||
.each(function(attachment){
|
||||
if(attachment.length > 1)
|
||||
|
|
|
@ -34,6 +34,9 @@ def start_server():
|
|||
if openerp.multi_process:
|
||||
_logger.info("FTP disabled in multiprocess mode")
|
||||
return
|
||||
if openerp.evented:
|
||||
_logger.info("FTP disabled in evented mode")
|
||||
return
|
||||
HOST = config.get('ftp_server_host', '127.0.0.1')
|
||||
PORT = int(config.get('ftp_server_port', '8021'))
|
||||
PASSIVE_PORTS = None
|
||||
|
|
|
@ -378,7 +378,7 @@ class email_template(osv.osv):
|
|||
# Ensure report is rendered using template's language
|
||||
ctx = context.copy()
|
||||
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 = base64.b64encode(result)
|
||||
if not report_name:
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
<record id="confirmation_event" model="email.template">
|
||||
<field name="name">Confirmation of the Event</field>
|
||||
<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_to" >${object.email}</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|safe}</field>
|
||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<p>Hello ${object.name},</p>
|
||||
|
@ -21,8 +21,8 @@
|
|||
<record id="confirmation_registration" model="email.template">
|
||||
<field name="name">Confirmation of the Registration</field>
|
||||
<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_to" >${object.email}</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|safe}</field>
|
||||
<field name="subject">Your registration at ${object.event_id.name}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<p>Hello ${object.name},</p>
|
||||
|
|
|
@ -160,8 +160,8 @@ class fleet_vehicle_model(osv.Model):
|
|||
'brand_id': fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
|
||||
'vendors': fields.many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors'),
|
||||
'image': fields.related('brand_id', 'image', type="binary", string="Logo"),
|
||||
'image_medium': fields.related('brand_id', 'image_medium', type="binary", string="Logo"),
|
||||
'image_small': fields.related('brand_id', 'image_small', type="binary", string="Logo"),
|
||||
'image_medium': fields.related('brand_id', 'image_medium', type="binary", string="Logo (medium)"),
|
||||
'image_small': fields.related('brand_id', 'image_small', type="binary", string="Logo (small)"),
|
||||
}
|
||||
|
||||
|
||||
|
@ -354,8 +354,8 @@ class fleet_vehicle(osv.Model):
|
|||
'power': fields.integer('Power', help='Power in kW of the vehicle'),
|
||||
'co2': fields.float('CO2 Emissions', help='CO2 emissions of the vehicle'),
|
||||
'image': fields.related('model_id', 'image', type="binary", string="Logo"),
|
||||
'image_medium': fields.related('model_id', 'image_medium', type="binary", string="Logo"),
|
||||
'image_small': fields.related('model_id', 'image_small', type="binary", string="Logo"),
|
||||
'image_medium': fields.related('model_id', 'image_medium', type="binary", string="Logo (medium)"),
|
||||
'image_small': fields.related('model_id', 'image_small', type="binary", string="Logo (small)"),
|
||||
'contract_renewal_due_soon': fields.function(_get_contract_reminder_fnc, fnct_search=_search_contract_renewal_due_soon, type="boolean", string='Has Contracts to renew', multi='contract_info'),
|
||||
'contract_renewal_overdue': fields.function(_get_contract_reminder_fnc, fnct_search=_search_get_overdue_contract_reminder, type="boolean", string='Has Contracts Overdued', multi='contract_info'),
|
||||
'contract_renewal_name': fields.function(_get_contract_reminder_fnc, type="text", string='Name of contract to renew soon', multi='contract_info'),
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!--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 id="vehicle_state_inshop" model="fleet.vehicle.state">
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model='ir.ui.view' id='fleet_vehicle_model_tree'>
|
||||
<field name="name">fleet.vehicle.model.tree</field>
|
||||
<field name="model">fleet.vehicle.model</field>
|
||||
|
@ -565,7 +566,7 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!--
|
||||
|
||||
<record model='ir.ui.view' id='fleet_vehicle_odometer_search'>
|
||||
<field name="name">fleet.vehicle.odometer.search</field>
|
||||
<field name="model">fleet.vehicle.odometer</field>
|
||||
|
@ -575,11 +576,12 @@
|
|||
<field name="value"/>
|
||||
<field name="unit"/>
|
||||
<field name="date"/>
|
||||
<filter name="groupby_vehicle" context="{'group_by' : 'vehicle_id'}" string="Vehicle"/>
|
||||
<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_odometer_graph">
|
||||
<field name="name">fleet.vehicle.odometer.graph</field>
|
||||
|
@ -671,6 +673,23 @@
|
|||
</tree>
|
||||
</field>
|
||||
</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">
|
||||
<field name="name">fleet.vehicle.log.fuel.graph</field>
|
||||
|
@ -690,6 +709,7 @@
|
|||
<field name="res_model">fleet.vehicle.log.fuel</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="context">{"search_default_groupby_vehicle" : True}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
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 = self.browse(cr, uid, employee_id, context=context)
|
||||
if employee.user_id:
|
||||
res_users = self.pool['res.users']
|
||||
# send a copy to every user of the company
|
||||
company_id = employee.user_id.partner_id.company_id.id
|
||||
partner_ids = self.pool.get('res.partner').search(cr, uid, [
|
||||
('company_id', '=', company_id),
|
||||
('user_ids', '!=', False)], context=context)
|
||||
# TODO: post to the `Whole Company` mail.group when we'll be able to link to the employee record
|
||||
_model, group_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')
|
||||
user_ids = res_users.search(cr, uid, [('company_id', '=', employee.user_id.company_id.id),
|
||||
('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:
|
||||
partner_ids = []
|
||||
self.message_post(cr, uid, [employee_id],
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
<field name="model">hr.employee</field>
|
||||
<field name="arch" type="xml">
|
||||
<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="category_ids" groups="base.group_hr_user"/>
|
||||
<group expand="0" string="Group By...">
|
||||
|
|
|
@ -157,7 +157,7 @@
|
|||
<field name="date"/>
|
||||
<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-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/>
|
||||
<filter domain="[('user_id', '=', uid)]" string="My Expenses"/>
|
||||
<field name="employee_id"/>
|
||||
|
|
|
@ -145,7 +145,9 @@ class hr_holidays(osv.osv):
|
|||
|
||||
def _check_date(self, 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:
|
||||
return False
|
||||
return True
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
<record model="workflow.activity" id="act_refuse"> <!-- refused -->
|
||||
<field name="wkf_id" ref="wkf_holidays" />
|
||||
<field name="name">refuse</field>
|
||||
<field name="flow_stop" eval="False"/>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">holidays_refuse()</field>
|
||||
</record>
|
||||
|
|
|
@ -260,7 +260,7 @@ class hr_payslip(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'struct_id': fields.many2one('hr.payroll.structure', 'Structure', readonly=True, states={'draft': [('readonly', False)]}, help='Defines the rules that have to be applied to this payslip, accordingly to the contract chosen. If you let empty the field contract, this field isn\'t mandatory anymore and thus the rules applied will be all the rules set on the structure of all contracts of the employee valid for the chosen period'),
|
||||
'name': fields.char('Description', size=64, required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'name': fields.char('Payslip Name', size=64, required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'number': fields.char('Reference', size=64, required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'employee_id': fields.many2one('hr.employee', 'Employee', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'date_from': fields.date('Date From', readonly=True, states={'draft': [('readonly', False)]}, required=True),
|
||||
|
@ -281,7 +281,7 @@ class hr_payslip(osv.osv):
|
|||
'worked_days_line_ids': fields.one2many('hr.payslip.worked_days', 'payslip_id', 'Payslip Worked Days', required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'input_line_ids': fields.one2many('hr.payslip.input', 'payslip_id', 'Payslip Inputs', required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'paid': fields.boolean('Made Payment Order ? ', required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'note': fields.text('Description', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'note': fields.text('Internal Note', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'contract_id': fields.many2one('hr.contract', 'Contract', required=False, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'details_by_salary_rule_category': fields.function(_get_lines_salary_rule_category, method=True, type='one2many', relation='hr.payslip.line', string='Details by Salary Rule Category'),
|
||||
'credit_note': fields.boolean('Credit Note', help="Indicates this payslip has a refund of another", readonly=True, states={'draft': [('readonly', False)]}),
|
||||
|
|
|
@ -52,12 +52,13 @@ class hr_recruitment_stage(osv.osv):
|
|||
'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."),
|
||||
'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'),
|
||||
'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 = {
|
||||
'sequence': 1,
|
||||
'fold': False,
|
||||
}
|
||||
|
||||
class hr_recruitment_degree(osv.osv):
|
||||
|
@ -82,8 +83,9 @@ class hr_applicant(osv.Model):
|
|||
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
||||
_track = {
|
||||
'stage_id': {
|
||||
'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,
|
||||
# this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
|
||||
'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):
|
||||
""" Gives default stage_id """
|
||||
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):
|
||||
""" 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):
|
||||
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}}
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
|
||||
|
@ -331,7 +333,8 @@ class hr_applicant(osv.Model):
|
|||
through message_process.
|
||||
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]
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
|
@ -344,38 +347,7 @@ class hr_applicant(osv.Model):
|
|||
if msg.get('priority'):
|
||||
defaults['priority'] = msg.get('priority')
|
||||
defaults.update(custom_values)
|
||||
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)
|
||||
return super(hr_applicant, self).message_new(cr, uid, msg, custom_values=defaults, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
|
|
|
@ -71,12 +71,14 @@
|
|||
<record model="hr.recruitment.stage" id="stage_job5">
|
||||
<field name="name">Contract Signed</field>
|
||||
<field name="sequence">5</field>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job6">
|
||||
<field name="name">Refused</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="survey_job_0" model="survey">
|
||||
<field name="title">Job Survey</field>
|
||||
<field name="max_response_limit">20</field>
|
||||
|
|
|
@ -342,6 +342,7 @@
|
|||
<field name="sequence" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
<field name="fold"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -90,7 +90,7 @@ class hr_recruitment_report(osv.Model):
|
|||
(sum(salary_proposed)/count(*)) as salary_prop_avg,
|
||||
sum(salary_expected) as salary_exp,
|
||||
(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
|
||||
from hr_applicant s
|
||||
group by
|
||||
|
@ -101,6 +101,7 @@ class hr_recruitment_report(osv.Model):
|
|||
date_trunc('day',s.date_closed),
|
||||
s.date_open,
|
||||
s.create_date,
|
||||
s.write_date,
|
||||
s.date_closed,
|
||||
s.date_last_stage_update,
|
||||
s.partner_id,
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
</record>
|
||||
|
||||
<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="res_model">account.analytic.line</field>
|
||||
<field name="src_model">account.analytic.account</field>
|
||||
|
|
|
@ -95,7 +95,7 @@ class timesheet_report(osv.osv):
|
|||
htss.state
|
||||
from account_analytic_line as aal
|
||||
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
|
||||
aal.account_id,
|
||||
aal.date,
|
||||
|
|
|
@ -62,16 +62,12 @@
|
|||
this.user_search_dm = new instance.web.DropMisordered();
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this.$el.css("right", -this.$el.outerWidth());
|
||||
$(window).scroll(_.bind(this.calc_box, this));
|
||||
$(window).resize(_.bind(this.calc_box, this));
|
||||
this.calc_box();
|
||||
|
||||
this.on("change:current_search", this, this.search_changed);
|
||||
this.search_changed();
|
||||
|
||||
var self = this;
|
||||
|
||||
return this.c_manager.start_polling().then(function() {
|
||||
self.c_manager.on("new_conversation", self, function(conv) {
|
||||
conv.$el.droppable({
|
||||
|
@ -80,6 +76,7 @@
|
|||
}
|
||||
});
|
||||
});
|
||||
self.search_changed();
|
||||
});
|
||||
},
|
||||
calc_box: function() {
|
||||
|
@ -174,4 +171,4 @@
|
|||
openerp.webclient.to_kitten();
|
||||
};
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -65,6 +65,7 @@ Wizards provided by this module:
|
|||
'account_pcmn_belgium.xml',
|
||||
'account_tax_code_template.xml',
|
||||
'account_chart_template.xml',
|
||||
'account_chart_template.yml',
|
||||
'account_tax_template.xml',
|
||||
'wizard/l10n_be_account_vat_declaration_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_expense_categ" ref="a_expense"/>
|
||||
<field name="property_account_income_categ" ref="a_sale"/>
|
||||
<field name="spoken_languages" eval="'nl_BE'"/>
|
||||
<field name="currency_id" ref="base.EUR"/>
|
||||
</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:
|
||||
grid_amount_data = {
|
||||
'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)
|
||||
|
||||
|
|
|
@ -177,14 +177,12 @@
|
|||
<record model="account.account.type" id="account_type_receivable">
|
||||
<field name="name">Bilan : Debiteurs</field>
|
||||
<field name="code">receivable</field>
|
||||
<field name="partner_account" eval="True"/>
|
||||
<field name="close_method">unreconciled</field>
|
||||
<field name="report_type">none</field>
|
||||
</record>
|
||||
<record model="account.account.type" id="account_type_payable">
|
||||
<field name="name">Bilan : Fournisseurs</field>
|
||||
<field name="code">payable</field>
|
||||
<field name="partner_account" eval="True"/>
|
||||
<field name="close_method">unreconciled</field>
|
||||
<field name="report_type">none</field>
|
||||
</record>
|
||||
|
@ -11809,7 +11807,6 @@
|
|||
<field name="property_account_income" ref="ch_3200"/>
|
||||
<field name="property_account_income_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="spoken_languages" eval="'it_IT;de_DE'"/>
|
||||
<field name="currency_id" ref="base.CHF"/>
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
<!-- Exentas IVA -->
|
||||
<record id="base_assoc_sop_ex" model="account.tax.code.template">
|
||||
<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="code">--</field>
|
||||
<field name="sign">1.0</field>
|
||||
|
@ -53,7 +52,6 @@
|
|||
<record id="base_assoc_rep_ex" model="account.tax.code.template">
|
||||
<field name="name">Base ventas exentas</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="sign">1.0</field>
|
||||
</record>
|
||||
|
|
|
@ -219,8 +219,8 @@
|
|||
<field name="tax_code_id" ref="tax_acq_196"/>
|
||||
<field name="tax_sign" eval="-1"/>
|
||||
|
||||
<field name="account_collected_id" ref="pcg_445662"/>
|
||||
<field name="account_paid_id" ref="pcg_445662"/>
|
||||
<field name="account_collected_id" ref="pcg_44566"/>
|
||||
<field name="account_paid_id" ref="pcg_44566"/>
|
||||
|
||||
<field name="ref_base_code_id" ref="tax_acq_196_ht"/>
|
||||
<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"
|
||||
1,"fix",1,1,,100,"Education Allowance For One Child","Allowance",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",
|
||||
3,"fix",1,1,,300,"Child Hostel Allowance For One Child","Allowance",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",
|
||||
"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",hr_payroll.ALW,23,"CHEAONE","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",hr_payroll.ALW,26,"CHOONE","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'
|
||||
|
||||
# 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):
|
||||
"""
|
||||
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 out_obj: Destination object for which translation is to be copied
|
||||
: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
|
||||
with the translation in the uid's language by doing a write (in case it's TRUE)
|
||||
:param force_write: Deprecated as of 7.0, do not use
|
||||
: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
|
||||
|
||||
|
@ -65,26 +65,25 @@ class wizard_multi_charts_accounts(osv.osv_memory):
|
|||
for j in range(len(in_ids)):
|
||||
in_id = in_ids[j]
|
||||
if value[in_id]:
|
||||
if not force_write:
|
||||
#copy Translation from Source to Destination object
|
||||
xlat_obj.create(cr, uid, {
|
||||
'name': out_obj._name + ',' + in_field,
|
||||
'type': 'model',
|
||||
'res_id': out_ids[j],
|
||||
'lang': lang,
|
||||
'src': src[in_id],
|
||||
'value': value[in_id],
|
||||
#copy Translation from Source to Destination object
|
||||
xlat_obj.create(cr, uid, {
|
||||
'name': out_obj._name + ',' + in_field,
|
||||
'type': 'model',
|
||||
'res_id': out_ids[j],
|
||||
'lang': lang,
|
||||
'src': src[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:
|
||||
_logger.info('Language: %s. Translation from template: there is no translation available for %s!' %(lang, src[in_id]))#out_obj._name))
|
||||
return True
|
||||
|
||||
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)
|
||||
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]
|
||||
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:]
|
||||
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):
|
||||
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]
|
||||
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:]
|
||||
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):
|
||||
obj_tax_template = self.pool.get('account.tax.template')
|
||||
obj_tax = self.pool.get('account.tax')
|
||||
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')
|
||||
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):
|
||||
obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
|
||||
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')
|
||||
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:
|
||||
|
|
|
@ -3693,8 +3693,6 @@ Cuentas del plan
|
|||
<field name="property_account_payable" ref="cuenta2122001000"/>
|
||||
<field name="property_account_expense_categ" ref="cuenta6111001000"/>
|
||||
<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"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<field name="property_account_income" ref="chart_711"/>
|
||||
<field name="property_account_income_categ" ref="chart_711"/>
|
||||
<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"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<field name="name">Basic Chart of Account</field>
|
||||
<field name="visible" eval="False" />
|
||||
<field name="complete_tax_set" eval="False" />
|
||||
<field name="currency_id" ref="base.USD"/>
|
||||
</record>
|
||||
|
||||
<record id="account_chart_template_cogs" model="account.chart.template">
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
<field name="amount">0.00000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">all</field>
|
||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -21,8 +21,8 @@
|
|||
<field name="amount">0.120000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -34,8 +34,8 @@
|
|||
<field name="amount">0.080000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -47,8 +47,8 @@
|
|||
<field name="amount">0.220000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">sale</field>
|
||||
<field name="collected_id" ref="account_activa_account_2172003"/>
|
||||
<field name="paid_id" ref="account_activa_account_2172003"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -60,8 +60,8 @@
|
|||
<field name="amount">0.120000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -73,8 +73,8 @@
|
|||
<field name="amount">0.080000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
@ -86,8 +86,8 @@
|
|||
<field name="amount">0.220000</field>
|
||||
<field name="type">percent</field>
|
||||
<field name="type_tax_use">purchase</field>
|
||||
<field name="collected_id" ref="account_activa_account_1151004"/>
|
||||
<field name="paid_id" ref="account_activa_account_1151004"/>
|
||||
<field name="account_collected_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="tax_code_id" ref="vat_code_due_tva"/>
|
||||
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
|
||||
|
|
|
@ -64,7 +64,7 @@ class mail_alias(osv.Model):
|
|||
return dict.fromkeys(ids, domain or "")
|
||||
|
||||
_columns = {
|
||||
'alias_name': fields.char('Alias',
|
||||
'alias_name': fields.char('Alias Name',
|
||||
help="The name of the email alias, e.g. 'jobs' if you want to catch emails for <jobs@example.my.openerp.com>",),
|
||||
'alias_model_id': fields.many2one('ir.model', 'Aliased Model', required=True, ondelete="cascade",
|
||||
help="The model (OpenERP Document Kind) to which this alias "
|
||||
|
|
|
@ -698,8 +698,9 @@ class mail_message(osv.Model):
|
|||
"""
|
||||
model_record_ids = {}
|
||||
for id in msg_ids:
|
||||
if msg_val[id]['model'] and msg_val[id]['res_id']:
|
||||
model_record_ids.setdefault(msg_val[id]['model'], dict()).setdefault(msg_val[id]['res_id'], set()).add(msg_val[id]['res_id'])
|
||||
vals = msg_val.get(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
|
||||
|
||||
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
|
||||
|
||||
# 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,))
|
||||
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}
|
||||
|
@ -745,10 +746,10 @@ class mail_message(osv.Model):
|
|||
], context=context)
|
||||
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
|
||||
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, [
|
||||
('res_model', '=', doc_model),
|
||||
('res_id', 'in', list(doc_dict.keys())),
|
||||
('res_id', 'in', list(doc_ids)),
|
||||
('partner_id', '=', partner_id),
|
||||
], 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))
|
||||
model_record_ids = _generate_model_record_ids(message_values, other_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]
|
||||
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'):
|
||||
model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
|
||||
else:
|
||||
|
|
|
@ -23,6 +23,11 @@ import base64
|
|||
import datetime
|
||||
import dateutil
|
||||
import email
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
from lxml import etree
|
||||
import logging
|
||||
import pytz
|
||||
import time
|
||||
|
@ -33,6 +38,7 @@ from openerp import tools
|
|||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.mail.mail_message import decode
|
||||
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.translate import _
|
||||
|
||||
|
@ -306,6 +312,28 @@ class mail_thread(osv.AbstractModel):
|
|||
"be inserted in kanban views."),
|
||||
}
|
||||
|
||||
def _get_user_chatter_options(self, cr, uid, context=None):
|
||||
options = {
|
||||
'display_log_button': False
|
||||
}
|
||||
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]
|
||||
is_employee = group_user_id in [group.id for group in group_ids]
|
||||
if is_employee:
|
||||
options['display_log_button'] = True
|
||||
return options
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
res = super(mail_thread, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
|
||||
if view_type == 'form':
|
||||
doc = etree.XML(res['arch'])
|
||||
for node in doc.xpath("//field[@name='message_ids']"):
|
||||
options = json.loads(node.get('options', '{}'))
|
||||
options.update(self._get_user_chatter_options(cr, uid, context=context))
|
||||
node.set('options', json.dumps(options))
|
||||
res['arch'] = etree.tostring(doc)
|
||||
return res
|
||||
|
||||
#------------------------------------------------------
|
||||
# CRUD overrides for automatic subscription and logging
|
||||
#------------------------------------------------------
|
||||
|
@ -328,11 +356,11 @@ class mail_thread(osv.AbstractModel):
|
|||
if not context.get('mail_create_nosubscribe'):
|
||||
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
|
||||
# auto_subscribe: take values and defaults into account
|
||||
create_values = set(values.keys())
|
||||
create_values = dict(values)
|
||||
for key, val in context.iteritems():
|
||||
if key.startswith('default_'):
|
||||
create_values.add(key[8:])
|
||||
self.message_auto_subscribe(cr, uid, [thread_id], list(create_values), context=context)
|
||||
create_values[key[8:]] = val
|
||||
self.message_auto_subscribe(cr, uid, [thread_id], create_values.keys(), context=context, values=create_values)
|
||||
|
||||
# track values
|
||||
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context)
|
||||
|
@ -353,7 +381,7 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
# Perform write, update followers
|
||||
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
|
||||
if tracked_fields:
|
||||
|
@ -577,7 +605,8 @@ class mail_thread(osv.AbstractModel):
|
|||
return action
|
||||
if msg_id and not (model and res_id):
|
||||
msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
|
||||
model, res_id = msg.model, msg.res_id
|
||||
if msg.exists():
|
||||
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 and res_id:
|
||||
|
@ -1538,75 +1567,100 @@ class mail_thread(osv.AbstractModel):
|
|||
user_field_lst.append(name)
|
||||
return user_field_lst
|
||||
|
||||
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None):
|
||||
"""
|
||||
1. fetch project subtype related to task (parent_id.res_model = 'project.task')
|
||||
2. for each project subtype: subscribe the follower to the task
|
||||
def message_auto_subscribe(self, cr, uid, ids, updated_fields, context=None, values=None):
|
||||
""" Handle auto subscription. Two methods for auto subscription exist:
|
||||
|
||||
- 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')
|
||||
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)
|
||||
|
||||
# fetch related record subtypes
|
||||
related_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)
|
||||
default_subtypes = [subtype for subtype in subtypes if subtype.res_model == False]
|
||||
related_subtypes = [subtype for subtype in subtypes if subtype.res_model != False]
|
||||
relation_fields = set([subtype.relation_field for subtype in subtypes if subtype.relation_field != False])
|
||||
if (not related_subtypes or not any(relation in updated_fields for relation in relation_fields)) and not user_field_lst:
|
||||
# fetch header subtypes
|
||||
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, header_subtype_ids, context=context)
|
||||
|
||||
# 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 is not False])
|
||||
if not any(relation in updated_fields for relation in relation_fields) and not user_field_lst:
|
||||
return True
|
||||
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
new_followers = dict()
|
||||
parent_res_id = False
|
||||
parent_model = False
|
||||
for subtype in related_subtypes:
|
||||
if not subtype.relation_field or not subtype.parent_id:
|
||||
continue
|
||||
if not subtype.relation_field in self._columns or not getattr(record, subtype.relation_field, False):
|
||||
continue
|
||||
parent_res_id = getattr(record, subtype.relation_field).id
|
||||
parent_model = subtype.res_model
|
||||
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)
|
||||
# legacy behavior: if values is not given, compute the values by browsing
|
||||
# @TDENOTE: remove me in 8.0
|
||||
if values is None:
|
||||
record = self.browse(cr, uid, ids[0], context=context)
|
||||
for updated_field in updated_fields:
|
||||
field_value = getattr(record, updated_field)
|
||||
if isinstance(field_value, browse_record):
|
||||
field_value = field_value.id
|
||||
elif isinstance(field_value, browse_null):
|
||||
field_value = False
|
||||
values[updated_field] = field_value
|
||||
|
||||
if parent_res_id and parent_model:
|
||||
for subtype in default_subtypes:
|
||||
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.id)
|
||||
# find followers of headers, update structure for new followers
|
||||
headers = set()
|
||||
for subtype in subtypes:
|
||||
if subtype.relation_field and values.get(subtype.relation_field):
|
||||
headers.add((subtype.res_model, values.get(subtype.relation_field)))
|
||||
if headers:
|
||||
header_domain = ['|'] * (len(headers) - 1)
|
||||
for header in headers:
|
||||
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
|
||||
user_ids = [getattr(record, name).id for name in user_field_lst if getattr(record, 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)]
|
||||
for partner_id in user_id_partner_ids:
|
||||
new_followers.setdefault(partner_id, None)
|
||||
# add followers coming from res.users relational fields that are tracked
|
||||
user_ids = [values[name] for name in user_field_lst if values.get(name)]
|
||||
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_pids:
|
||||
new_followers.setdefault(partner_id, None)
|
||||
|
||||
for pid, subtypes in new_followers.items():
|
||||
subtypes = list(subtypes) if subtypes is not None else None
|
||||
self.message_subscribe(cr, uid, [record.id], [pid], subtypes, context=context)
|
||||
for pid, subtypes in new_followers.items():
|
||||
subtypes = list(subtypes) if subtypes is not None else None
|
||||
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
|
||||
if user_id_partner_ids:
|
||||
msg_ids = self.pool.get('mail.message').search(cr, uid, [
|
||||
('model', '=', self._name),
|
||||
('res_id', '=', record.id),
|
||||
('type', '=', 'email')], limit=1, context=context)
|
||||
if not msg_ids and record.message_ids:
|
||||
msg_ids = [record.message_ids[-1].id]
|
||||
# find first email message, set it as unread for auto_subscribe fields for them to have a notification
|
||||
if user_pids:
|
||||
for record_id in ids:
|
||||
message_obj = self.pool.get('mail.message')
|
||||
msg_ids = message_obj.search(cr, SUPERUSER_ID, [
|
||||
('model', '=', self._name),
|
||||
('res_id', '=', record_id),
|
||||
('type', '=', 'email')], limit=1, context=context)
|
||||
if not msg_ids:
|
||||
msg_ids = message_obj.search(cr, SUPERUSER_ID, [
|
||||
('model', '=', self._name),
|
||||
('res_id', '=', record_id)], limit=1, context=context)
|
||||
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
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
border: solid 1px rgba(0,0,0,0.03);
|
||||
}
|
||||
.openerp .oe_mail .oe_msg.oe_msg_nobody{
|
||||
background: #F8F8F8;
|
||||
background: #E4E4E4;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg.oe_msg_notification{
|
||||
background: #F8F8F8;
|
||||
|
|
|
@ -1800,15 +1800,17 @@ openerp.mail = function (session) {
|
|||
'read_action': 'unread',
|
||||
'show_record_name': false,
|
||||
'show_compact_message': 1,
|
||||
'display_log_button' : true,
|
||||
}, this.node.params);
|
||||
|
||||
if (this.node.attrs.placeholder) {
|
||||
this.node.params.compose_placeholder = this.node.attrs.placeholder;
|
||||
}
|
||||
if (this.node.attrs.readonly) {
|
||||
this.node.params.readonly = this.node.attrs.readonly;
|
||||
}
|
||||
|
||||
if ('display_log_button' in this.options) {
|
||||
this.node.params.display_log_button = this.options.display_log_button;
|
||||
}
|
||||
this.domain = this.node.params && this.node.params.domain || [];
|
||||
|
||||
if (!this.ParentViewManager.is_action_enabled('edit')) {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="oe_msg_attachment_list"></div>
|
||||
<button class="oe_post">
|
||||
<t t-if="!widget.is_log">Send</t>
|
||||
<t t-if="widget.is_log">Log a note</t>
|
||||
<t t-if="widget.is_log">Log an internal note</t>
|
||||
</button>
|
||||
<t t-call="mail.compose_message.add_attachment"/>
|
||||
</div>
|
||||
|
@ -51,8 +51,10 @@
|
|||
<div class="field_text oe_compact oe_compact_record">
|
||||
<a class="oe_compose_post" t-if="widget.options.compose_placeholder"><t t-raw="widget.options.compose_placeholder"/></a>
|
||||
<a class="oe_compose_post" t-if="!widget.options.compose_placeholder and !widget.options.view_mailbox">Send a message</a>
|
||||
<span class="oe_grey oe_sep_word">or</span>
|
||||
<a class="oe_compose_log">Log a note</a>
|
||||
<t t-if="widget.options.display_log_button">
|
||||
<span class="oe_grey oe_sep_word">or</span>
|
||||
<a class="oe_compose_log">Log an internal note</a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
@ -155,7 +157,7 @@
|
|||
</t>
|
||||
</div>
|
||||
<div t-if="widget.is_log">
|
||||
<span>Attach a note that will not be sent to the followers</span>
|
||||
<span>Add an internal note that will not be sent to the followers</span>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
@ -293,9 +295,9 @@
|
|||
logged a note
|
||||
</t>
|
||||
<t t-if="(widget.type == 'comment' or widget.type == 'email') and (widget.subtype or widget.partner_ids.length > 0)">
|
||||
to
|
||||
<t t-if="widget.partner_ids.length == 0">
|
||||
nobody
|
||||
<!-- Remove nobody if user have no rights on partner that will display 'portal to nobody 5 minutes ago' that will confuse to end user, now it display 'portal 5 minutes ago' if no rights.-->
|
||||
<t t-if="widget.partner_ids.length > 0">
|
||||
to
|
||||
</t>
|
||||
</t>
|
||||
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
|
||||
|
|
|
@ -294,9 +294,9 @@ class test_mail(TestMail):
|
|||
'notification email: link should contain the user login')
|
||||
self.assertIn('message_id=%s' % mail.mail_message_id.id, url,
|
||||
'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')
|
||||
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')
|
||||
|
||||
@mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm')
|
||||
|
|
|
@ -60,6 +60,10 @@ class invite_wizard(osv.osv_memory):
|
|||
help="If checked, the partners will receive an email warning they have been "
|
||||
"added in the document's followers."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'send_mail' : True,
|
||||
}
|
||||
|
||||
def add_followers(self, cr, uid, ids, context=None):
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<field name="name">welcome new partner</field>
|
||||
<field name="email_from">info@openerp.com</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="body_html">Hello, you will receive your welcome pack via email shortly.</field>
|
||||
</record>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<field name="name">congrats silver partner</field>
|
||||
<field name="email_from">info@openerp.com</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="body_html">Hi, we are delighted to welcome you among our Silver Partners as of today!</field>
|
||||
</record>
|
||||
|
@ -22,7 +22,7 @@
|
|||
<field name="name">congrats gold partner</field>
|
||||
<field name="email_from">info@openerp.com</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="body_html">Hi, we are delighted to let you know that you have entered the select circle of our Gold Partners</field>
|
||||
</record>
|
||||
|
|
|
@ -965,7 +965,10 @@ class mrp_production(osv.osv):
|
|||
partner_id = routing_loc.partner_id and routing_loc.partner_id.id or False
|
||||
|
||||
# Take next Sequence number of shipment base on type
|
||||
pick_name = ir_sequence.get(cr, uid, 'stock.picking.' + pick_type)
|
||||
if pick_type!='internal':
|
||||
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, {
|
||||
'name': pick_name,
|
||||
|
|
|
@ -80,11 +80,11 @@ class mrp_production(osv.osv):
|
|||
_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.
|
||||
@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')
|
||||
for production in self.browse(cr, uid, ids):
|
||||
source = production.product_id.property_stock_production.id
|
||||
|
|
|
@ -39,7 +39,11 @@ class pad_common(osv.osv_memory):
|
|||
#if create with content
|
||||
if "field_name" in context and "model" in context and "object_id" in context:
|
||||
myPad = EtherpadLiteClient( pad["key"], pad["server"]+'/api')
|
||||
myPad.createPad(path)
|
||||
try:
|
||||
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
|
||||
model = self.pool[context["model"]]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<data>
|
||||
|
||||
<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 id="base.main_company" model="res.company">
|
||||
|
|
|
@ -695,7 +695,7 @@ class pos_order(osv.osv):
|
|||
|
||||
def create_picking(self, cr, uid, ids, context=None):
|
||||
"""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')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<div class="oe_subtotal_footer_separator oe_inline">
|
||||
<label for="amount_total" />
|
||||
<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>
|
||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
|
||||
</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.tools.translate import _
|
||||
|
||||
|
@ -32,6 +33,9 @@ class mail_message(osv.Model):
|
|||
""" Override that adds specific access rights of mail.message, to remove
|
||||
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_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]:
|
||||
|
@ -45,6 +49,8 @@ class mail_message(osv.Model):
|
|||
- read:
|
||||
- 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_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]:
|
||||
|
|
|
@ -73,6 +73,9 @@ class test_portal(TestMail):
|
|||
for message in chell_pigs.message_ids:
|
||||
trigger_read = message.subject
|
||||
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):
|
||||
trigger_read = partner.name
|
||||
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<data>
|
||||
<record id="portal_claim_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Claims</field>
|
||||
<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 eval="1" name="perm_unlink"/>
|
||||
<field eval="1" name="perm_write"/>
|
||||
<field eval="0" name="perm_unlink"/>
|
||||
<field eval="0" name="perm_write"/>
|
||||
<field eval="1" name="perm_read"/>
|
||||
<field eval="0" name="perm_create"/>
|
||||
<field eval="1" name="perm_create"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -24,7 +24,6 @@ from openerp.osv import fields, osv
|
|||
class crm_contact_us(osv.TransientModel):
|
||||
""" Add employees list to the portal's contact page """
|
||||
_inherit = 'portal_crm.crm_contact_us'
|
||||
_description = 'Contact form for the portal'
|
||||
_columns = {
|
||||
'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):
|
||||
_description = 'Portal employee'
|
||||
_inherit = 'hr.employee'
|
||||
|
||||
"""
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<!--Email template -->
|
||||
<record id="email_template_edi_sale" model="email.template">
|
||||
<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="partner_to">${object.partner_invoice_id.id}</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
|
@ -95,7 +95,7 @@
|
|||
|
||||
<record id="email_template_edi_invoice" model="email.template">
|
||||
<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="partner_to">${object.partner_id.id}</field>
|
||||
<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))
|
||||
|
||||
#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):
|
||||
""" Checks if move is done or not.
|
||||
@return: True or False.
|
||||
|
@ -297,6 +293,12 @@ class procurement_order(osv.osv):
|
|||
"""
|
||||
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):
|
||||
""" condition on the transition to go from 'confirm' activity to 'confirm_wait' activity """
|
||||
return not self.test_cancel(cr, uid, ids)
|
||||
|
|
|
@ -147,13 +147,15 @@
|
|||
|
||||
<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
|
||||
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
|
||||
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_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 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,
|
||||
'product_uom': orderpoint.product_uom.id,
|
||||
'location_id': orderpoint.location_id.id,
|
||||
'warehouse_id': orderpoint.warehouse_id.id,
|
||||
'procure_method': 'make_to_order',
|
||||
'origin': orderpoint.name}
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ class product_uom(osv.osv):
|
|||
'1 * (reference unit) = ratio * (this unit)'),
|
||||
'factor_inv': fields.function(_factor_inv, digits=(12,12),
|
||||
fnct_inv=_factor_inv_write,
|
||||
string='Ratio',
|
||||
string='Bigger Ratio',
|
||||
help='How many times this Unit of Measure is bigger than the reference Unit of Measure in this category:\n'\
|
||||
'1 * (this unit) = ratio * (reference unit)', required=True),
|
||||
'rounding': fields.float('Rounding Precision', digits_compute=dp.get_precision('Product Unit of Measure'), required=True,
|
||||
|
|
|
@ -86,78 +86,13 @@ class sale_order_line(osv.osv):
|
|||
pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount'])
|
||||
|
||||
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
|
||||
result['price_unit'] = new_list_price
|
||||
result['discount'] = discount
|
||||
if discount > 0:
|
||||
result['price_unit'] = new_list_price
|
||||
result['discount'] = discount
|
||||
else:
|
||||
result['discount'] = 0.0
|
||||
else:
|
||||
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:
|
||||
if partner_id:
|
||||
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
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue