[Merge]with: lp:openobject-addons
bzr revid: dbr@tinyerp.com-20111207112300-4j977lu9ue76ssyb
This commit is contained in:
commit
4390c7e497
|
@ -19,11 +19,11 @@
|
|||
#
|
||||
##############################################################################
|
||||
{
|
||||
"name" : "Accounting and Financial Management",
|
||||
"name" : "eInvoicing",
|
||||
"version" : "1.1",
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "normal",
|
||||
'complexity': "easy",
|
||||
"description": """
|
||||
Accounting and Financial Management.
|
||||
====================================
|
||||
|
|
|
@ -880,7 +880,7 @@ class account_fiscalyear(osv.osv):
|
|||
for fy in self.browse(cr, uid, ids, context=context):
|
||||
ds = datetime.strptime(fy.date_start, '%Y-%m-%d')
|
||||
period_obj.create(cr, uid, {
|
||||
'name': _('Opening Period'),
|
||||
'name': "%s %s" % (_('Opening Period'), ds.strftime('%Y')),
|
||||
'code': ds.strftime('00/%Y'),
|
||||
'date_start': ds,
|
||||
'date_stop': ds,
|
||||
|
|
|
@ -30,10 +30,12 @@ class account_bank_statement(osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
seq = 0
|
||||
if 'line_ids' in vals:
|
||||
new_line_ids = []
|
||||
for line in vals['line_ids']:
|
||||
seq += 1
|
||||
line[2]['sequence'] = seq
|
||||
vals[seq - 1] = line
|
||||
new_line_ids += tuple(line)
|
||||
vals['line_ids'] = new_line_ids
|
||||
return super(account_bank_statement, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
|
|
|
@ -207,7 +207,7 @@ class account_invoice(osv.osv):
|
|||
help=' * The \'Draft\' state is used when a user is encoding a new and unconfirmed Invoice. \
|
||||
\n* The \'Pro-forma\' when invoice is in Pro-forma state,invoice does not have an invoice number. \
|
||||
\n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \
|
||||
\n* The \'Paid\' state is set automatically when invoice is paid.\
|
||||
\n* The \'Paid\' state is set automatically when the invoice is paid. Its related journal entries may or may not be reconciled. \
|
||||
\n* The \'Cancelled\' state is used when user cancel invoice.'),
|
||||
'date_invoice': fields.date('Invoice Date', readonly=True, states={'draft':[('readonly',False)]}, select=True, help="Keep empty to use the current date"),
|
||||
'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True,
|
||||
|
@ -257,7 +257,7 @@ class account_invoice(osv.osv):
|
|||
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50), # Check if we can remove ?
|
||||
'account.move.line': (_get_invoice_from_line, None, 50),
|
||||
'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
|
||||
}, help="The Journal Entry of the invoice have been totally reconciled with one or several Journal Entries of payment."),
|
||||
}, help="It indicates that the invoice has been paid and the journal entry of the invoice has been reconciled with one or several journal entries of payment."),
|
||||
'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',
|
||||
help='Bank Account Number, Company bank account if Invoice is customer or supplier refund, otherwise Partner bank account number.', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'move_lines':fields.function(_get_lines, type='many2many', relation='account.move.line', string='Entry Lines'),
|
||||
|
|
|
@ -171,8 +171,8 @@
|
|||
<field name="user_type" select="1"/>
|
||||
<field name="active" groups="base.group_extended" />
|
||||
<newline/>
|
||||
<field name="debit" invisible="context.get('config_invisible', True)"/>
|
||||
<field name="credit" invisible="context.get('config_invisible', True)"/>
|
||||
<field name="debit" invisible="context.get('config_invisible', True)" attrs="{'readonly':[('type','=','view')]}"/>
|
||||
<field name="credit" invisible="context.get('config_invisible', True)" attrs="{'readonly':[('type','=','view')]}"/>
|
||||
<field name="balance" invisible="context.get('config_invisible', True)"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -103,6 +103,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="state">open</field>
|
||||
<field name="partner_id" ref="base.res_partner_seagate"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_seagate"/>
|
||||
</record>
|
||||
<record id="analytic_seagate_p2" model="account.analytic.account">
|
||||
<field name="name">Seagate P2</field>
|
||||
|
@ -111,6 +112,7 @@
|
|||
<field name="parent_id" ref="analytic_integration"/>
|
||||
<field name="state">open</field>
|
||||
<field name="partner_id" ref="base.res_partner_seagate"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_seagate"/>
|
||||
</record>
|
||||
<record id="analytic_magasin_bml_1" model="account.analytic.account">
|
||||
<field name="name">Magasin BML 1</field>
|
||||
|
@ -118,6 +120,7 @@
|
|||
<field name="parent_id" ref="analytic_integration"/>
|
||||
<field name="type">normal</field>
|
||||
<field name="partner_id" ref="base.res_partner_15"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_14"/>
|
||||
</record>
|
||||
<record id="analytic_integration_c2c" model="account.analytic.account">
|
||||
<field name="name">CampToCamp</field>
|
||||
|
@ -127,6 +130,7 @@
|
|||
<field eval="time.strftime('%Y-12-31')" name="date"/>
|
||||
<field name="parent_id" ref="analytic_integration"/>
|
||||
<field name="partner_id" ref="base.res_partner_c2c"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_Camptocamp"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
<record id="analytic_agrolait" model="account.analytic.account">
|
||||
|
@ -135,13 +139,15 @@
|
|||
<field name="parent_id" ref="analytic_customers"/>
|
||||
<field name="type">normal</field>
|
||||
<field name="partner_id" ref="base.res_partner_agrolait"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_8"/>
|
||||
</record>
|
||||
<record id="analytic_asustek" model="account.analytic.account">
|
||||
<field name="name">Asustek</field>
|
||||
<field name="code">4</field>
|
||||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_customers"/>
|
||||
<field name="parent_id" ref="analytic_customers"/>
|
||||
<field name="partner_id" ref="base.res_partner_asus"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_tang"/>
|
||||
</record>
|
||||
<record id="analytic_distripc" model="account.analytic.account">
|
||||
<field name="name">DistriPC</field>
|
||||
|
@ -149,6 +155,7 @@
|
|||
<field name="parent_id" ref="analytic_customers"/>
|
||||
<field name="type">normal</field>
|
||||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_7"/>
|
||||
</record>
|
||||
<record id="analytic_sednacom" model="account.analytic.account">
|
||||
<field name="name">Sednacom</field>
|
||||
|
@ -158,6 +165,7 @@
|
|||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="type">normal</field>
|
||||
<field name="partner_id" ref="base.res_partner_sednacom"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_11"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
<record id="analytic_thymbra" model="account.analytic.account">
|
||||
|
@ -168,6 +176,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="partner_id" ref="base.res_partner_thymbra"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_thymbra"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
<record id="analytic_leclerc" model="account.analytic.account">
|
||||
|
@ -178,6 +187,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="partner_id" ref="base.res_partner_11"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_15"/>
|
||||
</record>
|
||||
<record id="analytic_desertic_hispafuentes" model="account.analytic.account">
|
||||
<field name="name">Desertic - Hispafuentes</field>
|
||||
|
@ -187,6 +197,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="partner_id" ref="base.res_partner_desertic_hispafuentes"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_3000"/>
|
||||
</record>
|
||||
<record id="analytic_tiny_at_work" model="account.analytic.account">
|
||||
<field name="name">OpenERP SA AT Work</field>
|
||||
|
@ -194,6 +205,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="partner_id" ref="base.res_partner_tinyatwork"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_tinyatwork"/>
|
||||
</record>
|
||||
<record id="analytic_partners_camp_to_camp" model="account.analytic.account">
|
||||
<field name="name">Camp to Camp</field>
|
||||
|
@ -203,6 +215,7 @@
|
|||
<field name="type">normal</field>
|
||||
<field name="parent_id" ref="analytic_partners"/>
|
||||
<field name="partner_id" ref="base.res_partner_c2c"/>
|
||||
<field name="contact_id" ref="base.res_partner_address_Camptocamp"/>
|
||||
<field name="state">open</field>
|
||||
</record>
|
||||
<record id="analytic_project_2_support" model="account.analytic.account">
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
<field name="type">tree</field>
|
||||
<field eval="8" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree toolbar="1" colors="red:(date<current_date);black:(date>=current_date);black:(date==False)" string="Analytic Accounts">
|
||||
<tree toolbar="1" colors="red:state=='pending';grey:state=='done';blue:type=='view'" string="Analytic Accounts">
|
||||
<field name="code"/>
|
||||
<field name="complete_name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="quantity_max"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="parent_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -57,11 +57,10 @@
|
|||
<field name="type">tree</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:type == 'view';red:(date<current_date);black:(date>=current_date);black:(date==False)" string="Analytic account" toolbar="1">
|
||||
<tree colors="red:state=='pending';grey:state=='done';blue:type=='view'" string="Analytic account" toolbar="1">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="quantity"/>
|
||||
<field name="quantity_max"/>
|
||||
<field name="debit"/>
|
||||
<field name="credit"/>
|
||||
<field name="balance"/>
|
||||
|
@ -85,7 +84,7 @@
|
|||
<group colspan="4" col="6">
|
||||
<field name="name" select="1" colspan="4"/>
|
||||
<field name="code" select="1"/>
|
||||
<field name="parent_id" on_change="on_change_parent(parent_id)" groups="base.group_extended" domain="[('type','=','view')]"/>
|
||||
<field name="parent_id" on_change="on_change_parent(parent_id)" groups="base.group_extended"/>
|
||||
<field name="company_id" on_change="on_change_company(company_id)" select="2" widget="selection" groups="base.group_multi_company" attrs="{'required': [('type','<>','view')]}"/>
|
||||
<field name="type" select="2"/>
|
||||
</group>
|
||||
|
@ -194,7 +193,7 @@
|
|||
<field name="journal_id" invisible="context.get('to_invoice', False)"/>
|
||||
<field name="amount" sum="Total" invisible="context.get('to_invoice', False)"/>
|
||||
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id, journal_id)" invisible="not context.get('to_invoice', False)"/>
|
||||
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" sum="Total Quantity" invisible="not context.get('to_invoice', False)"/>
|
||||
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" sum="Total Quantity"/>
|
||||
<field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" invisible="not context.get('to_invoice', False)"/>
|
||||
<field domain="[('type','=','normal')]" name="account_id"/>
|
||||
<field name="general_account_id" invisible="context.get('to_invoice', False)"/>
|
||||
|
|
|
@ -162,11 +162,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<para style="terp_default_8">[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street2) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.zip) or '' ]] [[ (o.address_invoice_id and o.address_invoice_id.city) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.state_id and o.address_invoice_id.state_id.name) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.country_id and o.address_invoice_id.country_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ display_address(o.address_invoice_id) ]]</para>
|
||||
<para style="terp_default_8">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
@ -198,7 +194,7 @@
|
|||
<para style="terp_tblheader_General_Centre">Origin</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Your Reference</para>
|
||||
<para style="terp_tblheader_General_Centre">Customer Code</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -49,13 +49,6 @@
|
|||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="analytic_journal_comp_rule_false" model="ir.rule">
|
||||
<field name="name">Analytic journal multi-company</field>
|
||||
<field model="ir.model" name="model_id" ref="model_account_analytic_journal"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="period_comp_rule" model="ir.rule">
|
||||
<field name="name">Period multi-company</field>
|
||||
<field model="ir.model" name="model_id" ref="model_account_period"/>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#
|
||||
##############################################################################
|
||||
{
|
||||
"name" : "Accountant Access",
|
||||
"name" : "Accounting and Finance",
|
||||
"version" : "1.1",
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "normal",
|
||||
"description": """
|
||||
Accounting Access Rights.
|
||||
|
@ -45,6 +45,7 @@ user rights to Demo user.
|
|||
'test': [],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'core': True,
|
||||
'certificate': '00395091383933390541',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# Azerbaijani translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
|
||||
"PO-Revision-Date: 2011-12-06 05:22+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Azerbaijani <az@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-12-07 04:52+0000\n"
|
||||
"X-Generator: Launchpad (build 14435)\n"
|
||||
|
||||
#. module: account_accountant
|
||||
#: model:ir.module.module,description:account_accountant.module_meta_information
|
||||
msgid ""
|
||||
"\n"
|
||||
"This module gives the admin user the access to all the accounting features "
|
||||
"like the journal\n"
|
||||
"items and the chart of accounts.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Bu modul jurnal yazıları, hesab qrafikləri kimi mühasibat uçotu "
|
||||
"funksiyalarına idarəçilik imkanı verir.\n"
|
||||
" "
|
||||
|
||||
#. module: account_accountant
|
||||
#: model:ir.module.module,shortdesc:account_accountant.module_meta_information
|
||||
msgid "Accountant"
|
||||
msgstr "Mühasib"
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
|
||||
{
|
||||
'name' : 'Sales Contract Management',
|
||||
'name' : 'Contracts Management',
|
||||
'version' : '1.1',
|
||||
'category' : 'Sales Management',
|
||||
'complexity': "normal",
|
||||
|
@ -46,6 +46,7 @@ user-wise as well as month wise.
|
|||
],
|
||||
'demo_xml' : [],
|
||||
'installable': True,
|
||||
'core': True,
|
||||
'active' : False,
|
||||
'certificate': '0042927202589',
|
||||
}
|
||||
|
|
|
@ -406,25 +406,25 @@ class account_analytic_account(osv.osv):
|
|||
'ca_theorical': fields.function(_analysis_all, multi='analytic_analysis', type='float', string='Theoretical Revenue',
|
||||
help="Based on the costs you had on the project, what would have been the revenue if all these costs have been invoiced at the normal sale price provided by the pricelist.",
|
||||
digits_compute=dp.get_precision('Account')),
|
||||
'hours_quantity': fields.function(_analysis_all, multi='analytic_analysis', type='float', string='Hours Tot',
|
||||
help="Number of hours you spent on the analytic account (from timesheet). It computes on all journal of type 'general'."),
|
||||
'hours_quantity': fields.function(_analysis_all, multi='analytic_analysis', type='float', string='Total Duration',
|
||||
help="Number of time you spent on the analytic account (from timesheet). It computes quantities on all journal of type 'general'."),
|
||||
'last_invoice_date': fields.function(_analysis_all, multi='analytic_analysis', type='date', string='Last Invoice Date',
|
||||
help="If invoice from the costs, this is the date of the latest invoiced."),
|
||||
'last_worked_invoiced_date': fields.function(_analysis_all, multi='analytic_analysis', type='date', string='Date of Last Invoiced Cost',
|
||||
help="If invoice from the costs, this is the date of the latest work or cost that have been invoiced."),
|
||||
'last_worked_date': fields.function(_analysis_all, multi='analytic_analysis', type='date', string='Date of Last Cost/Work',
|
||||
help="Date of the latest work done on this account."),
|
||||
'hours_qtt_non_invoiced': fields.function(_analysis_all, multi='analytic_analysis', type='float', string='Uninvoiced Hours',
|
||||
help="Number of hours (from journal of type 'general') that can be invoiced if you invoice based on analytic account."),
|
||||
'hours_qtt_invoiced': fields.function(_hours_qtt_invoiced_calc, type='float', string='Invoiced Hours',
|
||||
help="Number of hours that can be invoiced plus those that already have been invoiced."),
|
||||
'remaining_hours': fields.function(_remaining_hours_calc, type='float', string='Remaining Hours',
|
||||
help="Computed using the formula: Maximum Quantity - Hours Tot."),
|
||||
'hours_qtt_non_invoiced': fields.function(_analysis_all, multi='analytic_analysis', type='float', string='Uninvoiced Time',
|
||||
help="Number of time (hours/days) (from journal of type 'general') that can be invoiced if you invoice based on analytic account."),
|
||||
'hours_qtt_invoiced': fields.function(_hours_qtt_invoiced_calc, type='float', string='Invoiced Time',
|
||||
help="Number of time (hours/days) that can be invoiced plus those that already have been invoiced."),
|
||||
'remaining_hours': fields.function(_remaining_hours_calc, type='float', string='Remaining Time',
|
||||
help="Computed using the formula: Maximum Duration - Total Time"),
|
||||
'remaining_ca': fields.function(_remaining_ca_calc, type='float', string='Remaining Revenue',
|
||||
help="Computed using the formula: Max Invoice Price - Invoiced Amount.",
|
||||
digits_compute=dp.get_precision('Account')),
|
||||
'revenue_per_hour': fields.function(_revenue_per_hour_calc, type='float', string='Revenue per Hours (real)',
|
||||
help="Computed using the formula: Invoiced Amount / Hours Tot.",
|
||||
'revenue_per_hour': fields.function(_revenue_per_hour_calc, type='float', string='Revenue per Time (real)',
|
||||
help="Computed using the formula: Invoiced Amount / Total Duration",
|
||||
digits_compute=dp.get_precision('Account')),
|
||||
'real_margin': fields.function(_real_margin_calc, type='float', string='Real Margin',
|
||||
help="Computed using the formula: Invoiced Amount - Total Costs.",
|
||||
|
|
|
@ -117,8 +117,8 @@
|
|||
<field eval="20" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Analytic accounts">
|
||||
<field name="code"/>
|
||||
<field name="complete_name"/>
|
||||
<field name="code"/>
|
||||
<field name="hours_qtt_non_invoiced"/>
|
||||
<field name="remaining_hours"/>
|
||||
<field name="ca_to_invoice"/>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name' : 'Account Analytic Defaults',
|
||||
'version' : '1.0',
|
||||
'category' : 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "normal",
|
||||
'description': """Set default values for your analytic accounts
|
||||
Allows to automatically select analytic accounts based on criterions:
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
],
|
||||
"active": False,
|
||||
"installable": True,
|
||||
"core": True,
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
<field name="prorata"/>
|
||||
<field name="open_asset"/>
|
||||
</group>
|
||||
<group col="2" colspan="2" groups="analytic.group_analytic_accounting">
|
||||
<separator string="Analytic information" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="account_analytic_id"/>
|
||||
</group>
|
||||
<group col="2" colspan="2" groups="analytic.group_analytic_accounting">
|
||||
<separator string="Analytic information" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="account_analytic_id"/>
|
||||
</group>
|
||||
<separator string="Notes" colspan="4"/>
|
||||
<field name="note" colspan="4" nolabel="1"/>
|
||||
</form>
|
||||
|
@ -317,7 +317,7 @@
|
|||
<field name="name">Review Asset Categories</field>
|
||||
<field name="res_model">account.asset.category</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="asset_category_form_view_todo" model="ir.actions.todo">
|
||||
|
|
|
@ -0,0 +1,529 @@
|
|||
# Spanish (Argentina) translation for openobject-addons
|
||||
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-11-24 12:54+0000\n"
|
||||
"PO-Revision-Date: 2011-11-30 23:41+0000\n"
|
||||
"Last-Translator: Gustavo Earnshaw <gustavoear@gmail.com>\n"
|
||||
"Language-Team: Spanish (Argentina) <es_AR@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-12-02 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 14414)\n"
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_list_normal
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_list_normal
|
||||
msgid "Open Assets"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,method_end:0
|
||||
#: field:account.asset.property.history,method_end:0
|
||||
msgid "Ending date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Depreciation board"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
#: field:account.asset.asset,name:0
|
||||
#: field:account.asset.board,asset_id:0
|
||||
#: field:account.asset.property,asset_id:0
|
||||
#: field:account.invoice.line,asset_id:0
|
||||
#: field:account.move.line,asset_id:0
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_form
|
||||
#: model:ir.model,name:account_asset.model_account_asset_asset
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_form
|
||||
msgid "Asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: constraint:ir.actions.act_window:0
|
||||
msgid "Invalid model name in the action definition."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,method:0
|
||||
msgid "Linear"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Change duration"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,child_ids:0
|
||||
msgid "Child assets"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.board,value_asset:0
|
||||
msgid "Asset Value"
|
||||
msgstr "valor de activos"
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_field:account.asset.modify,init,name:0
|
||||
msgid "Reason"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
#: field:account.asset.asset,entry_ids:0
|
||||
#: wizard_field:account.asset.compute,asset_compute,move_ids:0
|
||||
msgid "Entries"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.compute,asset_compute:0
|
||||
msgid "Generated entries"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_field:account.asset.modify,init,method_delay:0
|
||||
#: field:account.asset.property,method_delay:0
|
||||
#: field:account.asset.property.history,method_delay:0
|
||||
msgid "Number of interval"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_button:account.asset.compute,asset_compute,asset_open:0
|
||||
msgid "Open entries"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_list
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_list
|
||||
#: model:ir.ui.menu,name:account_asset.menu_finance_Assets
|
||||
#: model:ir.ui.menu,name:account_asset.menu_finance_config_Assets
|
||||
msgid "Assets"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,method:0
|
||||
msgid "Progressive"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_list_draft
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_list_draft
|
||||
msgid "Draft Assets"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.modify,init:0
|
||||
#: wizard_field:account.asset.modify,init,note:0
|
||||
#: view:account.asset.property.history:0
|
||||
msgid "Notes"
|
||||
msgstr "Notas"
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Change history"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Depreciation entries"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Methods"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.modify,init:0
|
||||
msgid "Asset properties to modify"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,partner_id:0
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_field:account.asset.modify,init,method_period:0
|
||||
#: field:account.asset.property,method_period:0
|
||||
#: field:account.asset.property.history,method_period:0
|
||||
msgid "Period per interval"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Depreciation duration"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,account_analytic_id:0
|
||||
msgid "Analytic account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,state:0
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Depreciation methods"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Other information"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.board,value_asset_cumul:0
|
||||
msgid "Cumul. value"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.property:0
|
||||
msgid "Assets methods"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: constraint:ir.ui.view:0
|
||||
msgid "Invalid XML for View Architecture!"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.model,name:account_asset.model_account_asset_property
|
||||
msgid "Asset property"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.compute,asset_compute:0
|
||||
#: wizard_view:account.asset.compute,init:0
|
||||
#: wizard_button:account.asset.compute,init,asset_compute:0
|
||||
#: model:ir.actions.wizard,name:account_asset.wizard_asset_compute
|
||||
#: model:ir.ui.menu,name:account_asset.menu_wizard_asset_compute
|
||||
msgid "Compute assets"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.modify,init:0
|
||||
#: wizard_button:account.asset.modify,init,asset_modify:0
|
||||
#: model:ir.actions.wizard,name:account_asset.wizard_asset_modify
|
||||
msgid "Modify asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Confirm asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.property.history:0
|
||||
#: model:ir.model,name:account_asset.model_account_asset_property_history
|
||||
msgid "Asset history"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,date:0
|
||||
msgid "Date created"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.module.module,description:account_asset.module_meta_information
|
||||
msgid ""
|
||||
"Financial and accounting asset management.\n"
|
||||
" Allows to define\n"
|
||||
" * Asset category. \n"
|
||||
" * Assets.\n"
|
||||
" *Asset usage period and property.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.board,value_gross:0
|
||||
#: field:account.asset.property,value_total:0
|
||||
msgid "Gross value"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,method_time:0
|
||||
msgid "Ending period"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.board,name:0
|
||||
msgid "Asset name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Accounts information"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,note:0
|
||||
#: field:account.asset.category,note:0
|
||||
#: field:account.asset.property.history,note:0
|
||||
msgid "Note"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.asset,state:0
|
||||
#: selection:account.asset.property,state:0
|
||||
msgid "Draft"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,type:0
|
||||
msgid "Depr. method type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,account_asset_id:0
|
||||
msgid "Asset account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property.history,asset_property_id:0
|
||||
msgid "Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.asset,state:0
|
||||
msgid "Normal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,method_progress_factor:0
|
||||
msgid "Progressif factor"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,localisation:0
|
||||
msgid "Localisation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,method:0
|
||||
msgid "Computation method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,method_time:0
|
||||
msgid "Time method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,active:0
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property.history,user_id:0
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,property_ids:0
|
||||
msgid "Asset method name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,date:0
|
||||
#: field:account.asset.property.history,date:0
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.board,value_net:0
|
||||
msgid "Net value"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.close,init:0
|
||||
#: model:ir.actions.wizard,name:account_asset.wizard_asset_close
|
||||
msgid "Close asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,history_ids:0
|
||||
msgid "History"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,account_actif_id:0
|
||||
msgid "Depreciation account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,period_id:0
|
||||
#: wizard_field:account.asset.compute,init,period_id:0
|
||||
msgid "Period"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_category_form
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_category_form
|
||||
msgid "Asset Category"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_button:account.asset.close,init,end:0
|
||||
#: wizard_button:account.asset.compute,init,end:0
|
||||
#: wizard_button:account.asset.modify,init,end:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.asset,state:0
|
||||
#: wizard_button:account.asset.compute,asset_compute,end:0
|
||||
#: selection:account.asset.property,state:0
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,state:0
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: constraint:ir.model:0
|
||||
msgid ""
|
||||
"The Object name must start with x_ and not contain any special character !"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.module.module,shortdesc:account_asset.module_meta_information
|
||||
msgid "Asset management"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.board:0
|
||||
#: field:account.asset.property,board_ids:0
|
||||
#: model:ir.model,name:account_asset.model_account_asset_board
|
||||
msgid "Asset board"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,state:0
|
||||
msgid "Global state"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,method_time:0
|
||||
msgid "Delay"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_view:account.asset.close,init:0
|
||||
msgid "General information"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,journal_analytic_id:0
|
||||
msgid "Analytic journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,name:0
|
||||
msgid "Method name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,journal_id:0
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property.history,name:0
|
||||
msgid "History name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Close method"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,entry_asset_ids:0
|
||||
msgid "Asset Entries"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,category_id:0
|
||||
#: view:account.asset.category:0
|
||||
#: field:account.asset.category,name:0
|
||||
#: model:ir.model,name:account_asset.model_account_asset_category
|
||||
msgid "Asset category"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "Depreciation"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,code:0
|
||||
#: field:account.asset.category,code:0
|
||||
msgid "Asset code"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,value_total:0
|
||||
msgid "Total value"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.asset,state:0
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: view:account.asset.asset:0
|
||||
msgid "General info"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.property,value_residual:0
|
||||
msgid "Residual value"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: wizard_button:account.asset.close,init,asset_close:0
|
||||
msgid "End of asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,type:0
|
||||
msgid "Direct"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: selection:account.asset.property,type:0
|
||||
msgid "Indirect"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: field:account.asset.asset,parent_id:0
|
||||
msgid "Parent asset"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_asset
|
||||
#: model:ir.actions.act_window,name:account_asset.action_account_asset_asset_tree
|
||||
#: model:ir.ui.menu,name:account_asset.menu_action_account_asset_asset_tree
|
||||
msgid "Asset Hierarchy"
|
||||
msgstr ""
|
|
@ -23,7 +23,7 @@
|
|||
"name" : "Cancel Entries",
|
||||
"version" : "1.1",
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "normal",
|
||||
"description": """
|
||||
Allows cancelling accounting entries.
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Charts of Accounts',
|
||||
'name': 'Template of Charts of Accounts',
|
||||
'version': '1.1',
|
||||
'category': 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'description': """
|
||||
Remove minimal account chart.
|
||||
=============================
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
"name" : "Account CODA - import bank statements from coda file",
|
||||
"name" : "CODA Bank Statements",
|
||||
"version" : "1.0",
|
||||
"author" : "OpenERP SA",
|
||||
"category" : "Hidden",
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "normal",
|
||||
"description": """
|
||||
Module provides functionality to import bank statements from coda files.
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Improve Invoice Layout',
|
||||
'name': 'Invoice Layouts',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
This module provides some features to improve the layout of the invoices.
|
||||
|
|
|
@ -193,11 +193,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<para style="terp_default_8">[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street2) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.zip) or '' ]] [[ (o.address_invoice_id and o.address_invoice_id.city) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.state_id and o.address_invoice_id.state_id.name) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.country_id and o.address_invoice_id.country_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ display_address(o.address_invoice_id) ]]</para>
|
||||
<para style="terp_default_8">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
@ -235,7 +231,7 @@
|
|||
<para style="terp_tblheader_General_Centre">Origin</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Your Reference</para>
|
||||
<para style="terp_tblheader_General_Centre">Customer Code</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -197,11 +197,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<para style="terp_default_8">[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.street2) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.zip) or '' ]] [[ (o.address_invoice_id and o.address_invoice_id.city) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.state_id and o.address_invoice_id.state_id.name) or removeParentNode('para') ]]</para>
|
||||
<para style="terp_default_8">[[ (o.address_invoice_id and o.address_invoice_id.country_id and o.address_invoice_id.country_id.name) or '' ]]</para>
|
||||
<para style="terp_default_8">[[ display_address(o.address_invoice_id) ]]</para>
|
||||
<para style="terp_default_8">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name': 'Entries Sequence Numbering',
|
||||
'version': '1.1',
|
||||
'category': 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
This module maintains internal sequence number for accounting entries.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
"name" : "Accounting Voucher Entries",
|
||||
"name" : "eInvoicing & Payments",
|
||||
"version" : "1.0",
|
||||
"author" : 'OpenERP SA',
|
||||
'complexity': "normal",
|
||||
|
@ -32,7 +32,7 @@ Account Voucher module includes all the basic requirements of Voucher Entries fo
|
|||
* Voucher Receipt
|
||||
* Cheque Register
|
||||
""",
|
||||
"category" : "Hidden",
|
||||
"category": 'Accounting & Finance',
|
||||
"website" : "http://tinyerp.com",
|
||||
"images" : ["images/customer_payment.jpeg","images/journal_voucher.jpeg","images/sales_receipt.jpeg","images/supplier_voucher.jpeg"],
|
||||
"depends" : ["account"],
|
||||
|
@ -68,6 +68,7 @@ Account Voucher module includes all the basic requirements of Voucher Entries fo
|
|||
],
|
||||
'certificate': '0037580727101',
|
||||
"active": False,
|
||||
"core": True,
|
||||
"installable": True,
|
||||
}
|
||||
|
||||
|
|
|
@ -958,6 +958,7 @@ class account_voucher(osv.osv):
|
|||
'debit': diff < 0 and -diff or 0.0,
|
||||
'amount_currency': company_currency <> current_currency and voucher_brw.writeoff_amount or False,
|
||||
'currency_id': company_currency <> current_currency and current_currency or False,
|
||||
'analytic_account_id': voucher_brw.analytic_id and voucher_brw.analytic_id.id or False,
|
||||
}
|
||||
|
||||
return move_line
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"version": "1.1",
|
||||
"author" : "OpenERP SA",
|
||||
"website" : "http://www.openerp.com",
|
||||
"category" : "Hidden",
|
||||
"category": 'Accounting & Finance',
|
||||
"depends" : ["base", "decimal_precision"],
|
||||
"description": """
|
||||
Module for defining analytic accounting object.
|
||||
|
|
|
@ -161,7 +161,7 @@ class account_analytic_account(osv.osv):
|
|||
'debit': fields.function(_debit_credit_bal_qtty, type='float', string='Debit', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')),
|
||||
'credit': fields.function(_debit_credit_bal_qtty, type='float', string='Credit', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')),
|
||||
'quantity': fields.function(_debit_credit_bal_qtty, type='float', string='Quantity', multi='debit_credit_bal_qtty'),
|
||||
'quantity_max': fields.float('Maximum Quantity', help='Sets the higher limit of quantity of hours.'),
|
||||
'quantity_max': fields.float('Maximum Time', help='Sets the higher limit of quantity of hours.'),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'contact_id': fields.many2one('res.partner.address', 'Contact'),
|
||||
'user_id': fields.many2one('res.users', 'Account Manager'),
|
||||
|
@ -242,6 +242,13 @@ class account_analytic_account(osv.osv):
|
|||
res['value']['partner_id'] = partner
|
||||
return res
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, partner, context=None):
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
if not partner:
|
||||
return {'value':{'contact_id': False}}
|
||||
address = partner_obj.address_get(cr, uid, [partner], ['contact'])
|
||||
return {'value':{'contact_id': address['contact']}}
|
||||
|
||||
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
|
||||
if not args:
|
||||
args=[]
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Analytic Journal Billing Rate, Define the default invoicing rate for a specific journal',
|
||||
'name': 'Billing Rates on Contracts',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Sales Management',
|
||||
'description': """
|
||||
This module allows you to define what is the default invoicing rate for a specific journal on a given account.
|
||||
==============================================================================================================
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Human Resources',
|
||||
'name': 'Jobs on Contracts',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Sales Management',
|
||||
'description': """
|
||||
This module allows you to define what is the default function of a specific user on a given account.
|
||||
====================================================================================================
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
{
|
||||
'name': 'Database Anonymization',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
This module allows you to anonymize a database.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Association profile',
|
||||
'name': 'Associations Management',
|
||||
'version': '0.1',
|
||||
'category': 'Specific Industry Applications',
|
||||
'complexity': "normal",
|
||||
|
@ -37,6 +37,7 @@ It installs the profile for associations to manage events, registrations, member
|
|||
'demo_xml': [],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'core': True,
|
||||
'certificate': '0078696047261',
|
||||
'images': ['images/association1.jpeg'],
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
id="base.menu_association"
|
||||
icon="terp-calendar"
|
||||
sequence="9"
|
||||
groups="base.group_extended"
|
||||
web_icon="images/association.png"
|
||||
web_icon_hover="images/association-hover.png"/>
|
||||
<menuitem name="Configuration" id="base.menu_event_config" parent="base.menu_association" sequence="30" groups="base.group_extended"/>
|
||||
|
|
|
@ -68,6 +68,7 @@ The dashboard for auction includes:
|
|||
],
|
||||
|
||||
'installable': True,
|
||||
'auction': True,
|
||||
'active': False,
|
||||
'certificate': '0039333102717',
|
||||
'images': ['images/auction1.jpeg','images/auction2.jpeg','images/auction3.jpeg'],
|
||||
|
|
|
@ -99,9 +99,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<para style="Addressee">[[ o['partner'] and o['partner'].name or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address[0].street or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address[0].zip or False]][[o['partner'] and o['partner'].address[0].city or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address[0].country_id.name or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address and display_address(o['partner'].address[0]) ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
|
|
@ -84,9 +84,7 @@
|
|||
</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.title]]</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.name]]</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.address[0].street]]</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.address[0].zip]],[[o.bord_vnd_id.partner_id.address[0].city]]</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.address[0].country_id.name]]</para>
|
||||
<para style="P5">[[o.bord_vnd_id.partner_id.address and display_address(o.bord_vnd_id.partner_id.address[0]) ]] </para>
|
||||
<para style="P6">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
|
|
@ -74,9 +74,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<para style="Addressee">[[ o['partner'] and o['partner'].name or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address[0].street or False]]</para>
|
||||
<para style="Addressee">[[o['partner'] and o['partner'].address[0].zip or False]][[o['partner'] and o['partner'].address[0].city or False]]</para>
|
||||
<para style="P11">[[o['partner'] and o['partner'].address[0].country_id.name or False]]</para>
|
||||
<para style="Addressee">[[ o['partner'] and o['partner'].address and display_address(o['partner'].address[0]) </para>
|
||||
<para style="P4">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
{
|
||||
'name': 'Audit Trail',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
This module lets administrator track every user operation on all the objects of the system.
|
||||
===========================================================================================
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'OpenID',
|
||||
'name': 'OpenID Authentification',
|
||||
'version': '2.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'description': """Allow users to login through OpenID.""",
|
||||
'author': 'OpenERP s.a.',
|
||||
'maintainer': 'OpenERP s.a.',
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name': 'Action Rule',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Sales Management',
|
||||
'description': """
|
||||
This module allows to implement action rules for any object.
|
||||
============================================================
|
||||
|
|
|
@ -34,7 +34,7 @@ It supports:
|
|||
- Recurring events
|
||||
- Invitations to people""",
|
||||
"author" : "OpenERP SA",
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'website': 'http://www.openerp.com',
|
||||
"init_xml" : [
|
||||
'base_calendar_data.xml'
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
{
|
||||
'name': 'Base Contact',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Sales Management',
|
||||
'complexity': "expert",
|
||||
'description': """
|
||||
This module allows you to manage your contacts entirely.
|
||||
|
|
|
@ -7,104 +7,104 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.4\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
|
||||
"PO-Revision-Date: 2009-02-03 06:25+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"PO-Revision-Date: 2011-12-03 15:19+0000\n"
|
||||
"Last-Translator: kifcaliph <kifcaliph@hotmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-11-05 05:04+0000\n"
|
||||
"X-Generator: Launchpad (build 14231)\n"
|
||||
"X-Launchpad-Export-Date: 2011-12-04 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 14418)\n"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,title:0
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
msgstr "اللقب"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.address:0
|
||||
msgid "# of Contacts"
|
||||
msgstr ""
|
||||
msgstr "عدد جهات الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,fax:0
|
||||
msgid "Fax"
|
||||
msgstr ""
|
||||
msgstr "فاكس"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
msgstr "الاسم"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,date_start:0
|
||||
msgid "Start date of job(Joining Date)"
|
||||
msgstr ""
|
||||
msgstr "تاريخ الالتحاق بالوظيفة"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
msgid "Select the Option for Addresses Migration"
|
||||
msgstr ""
|
||||
msgstr "حدد الخيار لنقل العناوين"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,function:0
|
||||
msgid "Function of this contact with this partner"
|
||||
msgstr ""
|
||||
msgstr "مهمة جهة الاتصال هذه عند هذا الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,state:0
|
||||
msgid "Status of Address"
|
||||
msgstr ""
|
||||
msgstr "حالة العنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,name:0
|
||||
msgid ""
|
||||
"You may enter Address first,Partner will be linked "
|
||||
"automatically if any."
|
||||
msgstr ""
|
||||
msgstr "يمكنك إدخال العنوان أولاً، وسيتمّ ربط الشريك تلقائياً إن وُجِد."
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,fax:0
|
||||
msgid "Job FAX no."
|
||||
msgstr ""
|
||||
msgstr "فاكس العمل"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,mobile:0
|
||||
msgid "Mobile"
|
||||
msgstr ""
|
||||
msgstr "الجوال"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
#: field:res.partner.contact,comment:0
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
msgstr "ملاحظات"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.node,note:base_contact.process_node_contacts0
|
||||
msgid "People you work with."
|
||||
msgstr ""
|
||||
msgstr "أشخاص تعمل معهم."
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,note:base_contact.process_transition_functiontoaddress0
|
||||
msgid "Define functions and address."
|
||||
msgstr ""
|
||||
msgstr "تعريف المهام والعنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,date_stop:0
|
||||
msgid "Last date of job"
|
||||
msgstr ""
|
||||
msgstr "تاريخ ترك الوظيفة"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
#: field:base.contact.installer,migrate:0
|
||||
msgid "Migrate"
|
||||
msgstr ""
|
||||
msgstr "نقل"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
#: field:res.partner.job,name:0
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
msgstr "الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.node,note:base_contact.process_node_function0
|
||||
|
@ -114,12 +114,12 @@ msgstr ""
|
|||
#. module: base_contact
|
||||
#: model:process.node,name:base_contact.process_node_partners0
|
||||
msgid "Partners"
|
||||
msgstr ""
|
||||
msgstr "الشركاء"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,state:0
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
msgstr "المحافظة"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.contact,active:0
|
||||
|
@ -151,27 +151,42 @@ msgid ""
|
|||
"an other object.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" تمكنك هذه الوحدة البرمجية من إدارة جهات الاتصال بشكل كامل.\n"
|
||||
" فهي تسمح لك بـتعرف:\n"
|
||||
" * جهات اتصال غير ذات صلة بشريك،\n"
|
||||
" * جهات اتصال ذات عناوين عمل متعددة (ربما لارتباطها بشركاء مختلفين)،\n"
|
||||
" * جهات اتصال ذات مهام مختلفة لكل عنوان من عناوين وظائفها\n"
|
||||
"\n"
|
||||
" كذلك تضيف هذه الوحدة البرمجية عناصر جديدة إلى القائمة تحت\n"
|
||||
" الشركاء / جهات الاتصال\n"
|
||||
" الشركاء / المهام\n"
|
||||
"\n"
|
||||
" تنبه إلى أن هذه الوحدة البرمجية تقوم بتحويل العناوين الموجودة مسبقاً إلى "
|
||||
"\"عناوين\" و \"جهات اتصال\"، مما يعني أن بعض حقول العناوين سيتم حذفها (مثل "
|
||||
"اسم جهة الاتصال) لأنه من المفترض أن يتم تعريفها في كائن آخر.\n"
|
||||
" "
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.module.module,shortdesc:base_contact.module_meta_information
|
||||
#: model:process.process,name:base_contact.process_process_basecontactprocess0
|
||||
msgid "Base Contact"
|
||||
msgstr ""
|
||||
msgstr "جهة الاتصال الأساسية"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,date_stop:0
|
||||
msgid "Date Stop"
|
||||
msgstr ""
|
||||
msgstr "تاريخ التوقف"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.actions.act_window,name:base_contact.action_res_partner_job
|
||||
msgid "Contact's Jobs"
|
||||
msgstr ""
|
||||
msgstr "الوظائف"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner:0
|
||||
msgid "Categories"
|
||||
msgstr ""
|
||||
msgstr "الفئات"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,sequence_partner:0
|
||||
|
@ -179,70 +194,72 @@ msgid ""
|
|||
"Order of importance of this job title in the list of job "
|
||||
"title of the linked partner"
|
||||
msgstr ""
|
||||
"ترتيب المسمى الوظيفي هذا حسب الأهمية بين المسميات الوظيغية المستخدمة لدى "
|
||||
"الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,extension:0
|
||||
msgid "Extension"
|
||||
msgstr ""
|
||||
msgstr "الامتداد"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,extension:0
|
||||
msgid "Internal/External extension phone number"
|
||||
msgstr ""
|
||||
msgstr "امتداد رقم الهاتف الداخلي/الخارجي"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,phone:0
|
||||
msgid "Job Phone no."
|
||||
msgstr ""
|
||||
msgstr "هاتف العمل"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
#: field:res.partner.contact,job_ids:0
|
||||
msgid "Functions and Addresses"
|
||||
msgstr ""
|
||||
msgstr "المهام والعناوين"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.model,name:base_contact.model_res_partner_contact
|
||||
#: field:res.partner.job,contact_id:0
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
msgstr "جهة الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,email:0
|
||||
msgid "Job E-Mail"
|
||||
msgstr ""
|
||||
msgstr "البريد الإلكتروني للعمل"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,sequence_partner:0
|
||||
msgid "Partner Seq."
|
||||
msgstr ""
|
||||
msgstr "رقم الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,name:base_contact.process_transition_functiontoaddress0
|
||||
msgid "Function to address"
|
||||
msgstr ""
|
||||
msgstr "مهمة إلى عنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:base.contact.installer,progress:0
|
||||
msgid "Configuration Progress"
|
||||
msgstr ""
|
||||
msgstr "سير الإعدادات"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,name:0
|
||||
msgid "Last Name"
|
||||
msgstr ""
|
||||
msgstr "اسم العائلة"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner:0
|
||||
#: view:res.partner.contact:0
|
||||
msgid "Communication"
|
||||
msgstr ""
|
||||
msgstr "التواصل"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:base.contact.installer,config_logo:0
|
||||
#: field:res.partner.contact,photo:0
|
||||
msgid "Image"
|
||||
msgstr ""
|
||||
msgstr "صورة"
|
||||
|
||||
#. module: base_contact
|
||||
#: selection:res.partner.job,state:0
|
||||
|
@ -252,7 +269,7 @@ msgstr ""
|
|||
#. module: base_contact
|
||||
#: model:ir.model,name:base_contact.model_res_partner_address
|
||||
msgid "Partner Addresses"
|
||||
msgstr ""
|
||||
msgstr "عناوين الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
|
@ -262,12 +279,12 @@ msgstr ""
|
|||
#. module: base_contact
|
||||
#: field:res.partner.job,sequence_contact:0
|
||||
msgid "Contact Seq."
|
||||
msgstr ""
|
||||
msgstr "رقم جهة الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.address:0
|
||||
msgid "Search Contact"
|
||||
msgstr ""
|
||||
msgstr "بحث جهة الإتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.actions.act_window,name:base_contact.action_partner_contact_form
|
||||
|
@ -277,7 +294,7 @@ msgstr ""
|
|||
#: view:res.partner:0
|
||||
#: field:res.partner.address,job_ids:0
|
||||
msgid "Contacts"
|
||||
msgstr ""
|
||||
msgstr "جهات الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
|
@ -289,58 +306,58 @@ msgstr ""
|
|||
#. module: base_contact
|
||||
#: model:process.node,note:base_contact.process_node_addresses0
|
||||
msgid "Working and private addresses."
|
||||
msgstr ""
|
||||
msgstr "عناوين العمل والعناوين الخاصة"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,address_id:0
|
||||
msgid "Address which is linked to the Partner"
|
||||
msgstr ""
|
||||
msgstr "العنوان المرتبط بالشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,function:0
|
||||
msgid "Partner Function"
|
||||
msgstr ""
|
||||
msgstr "مهمة الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,other:0
|
||||
msgid "Additional phone field"
|
||||
msgstr ""
|
||||
msgstr "حقل هاتف إضافي"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,website:0
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
msgstr "الموقع الإلكتروني"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
msgid "Otherwise these details will not be visible from address/contact."
|
||||
msgstr ""
|
||||
msgstr "وإلا فلن تظهر هذه التفاصيل في العنوان/جهة الاتصال."
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
msgid "Configure"
|
||||
msgstr ""
|
||||
msgstr "ضبط الإعدادات"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,email:0
|
||||
#: field:res.partner.job,email:0
|
||||
msgid "E-Mail"
|
||||
msgstr ""
|
||||
msgstr "البريد الإلكتروني"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.model,name:base_contact.model_base_contact_installer
|
||||
msgid "base.contact.installer"
|
||||
msgstr ""
|
||||
msgstr "base.contact.installer"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.job:0
|
||||
msgid "Contact Functions"
|
||||
msgstr ""
|
||||
msgstr "مهام جهة الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,phone:0
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
msgstr "هاتف"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
|
@ -350,164 +367,164 @@ msgstr ""
|
|||
#. module: base_contact
|
||||
#: field:res.partner.contact,active:0
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "نشِط"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,function:0
|
||||
msgid "Main Function"
|
||||
msgstr ""
|
||||
msgstr "المهمة الرئيسية"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,note:base_contact.process_transition_partnertoaddress0
|
||||
msgid "Define partners and their addresses."
|
||||
msgstr ""
|
||||
msgstr "تعريف الشركاء وعناوينهم"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
msgid "Seq."
|
||||
msgstr ""
|
||||
msgstr "رقم"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,lang_id:0
|
||||
msgid "Language"
|
||||
msgstr ""
|
||||
msgstr "اللغة"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
msgid "Extra Information"
|
||||
msgstr ""
|
||||
msgstr "معلومات إضافية"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.node,note:base_contact.process_node_partners0
|
||||
msgid "Companies you work with."
|
||||
msgstr ""
|
||||
msgstr "الشركات التي تتعامل معها."
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
msgid "Partner Contact"
|
||||
msgstr ""
|
||||
msgstr "جهة الاتصال بالشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
msgstr "عام"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner.contact:0
|
||||
msgid "Photo"
|
||||
msgstr ""
|
||||
msgstr "صورة"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,birthdate:0
|
||||
msgid "Birth Date"
|
||||
msgstr ""
|
||||
msgstr "تاريخ الميلاد"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:base.contact.installer,migrate:0
|
||||
msgid "If you select this, all addresses will be migrated."
|
||||
msgstr ""
|
||||
msgstr "إذا اخترت هذا الخيار، سيتم نقل جميع العناوين."
|
||||
|
||||
#. module: base_contact
|
||||
#: selection:res.partner.job,state:0
|
||||
msgid "Current"
|
||||
msgstr ""
|
||||
msgstr "الحالي"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,first_name:0
|
||||
msgid "First Name"
|
||||
msgstr ""
|
||||
msgstr "الاسم الأول"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.model,name:base_contact.model_res_partner_job
|
||||
msgid "Contact Partner Function"
|
||||
msgstr ""
|
||||
msgstr "مهمة الشريك"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,other:0
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
msgstr "غير ذلك"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.node,name:base_contact.process_node_function0
|
||||
msgid "Function"
|
||||
msgstr ""
|
||||
msgstr "المهمة"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.address,job_id:0
|
||||
#: field:res.partner.contact,job_id:0
|
||||
msgid "Main Job"
|
||||
msgstr ""
|
||||
msgstr "الوظيفة الرئيسية"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,note:base_contact.process_transition_contacttofunction0
|
||||
msgid "Defines contacts and functions."
|
||||
msgstr ""
|
||||
msgstr "تعريف جهات الاتصال والمهام."
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,name:base_contact.process_transition_contacttofunction0
|
||||
msgid "Contact to function"
|
||||
msgstr ""
|
||||
msgstr "جهة اتصال إلى مهمة"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner:0
|
||||
#: field:res.partner.job,address_id:0
|
||||
msgid "Address"
|
||||
msgstr ""
|
||||
msgstr "العنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,country_id:0
|
||||
msgid "Nationality"
|
||||
msgstr ""
|
||||
msgstr "الجنسية"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.actions.act_window,name:base_contact.act_res_partner_jobs
|
||||
msgid "Open Jobs"
|
||||
msgstr ""
|
||||
msgstr "الوظائف المفتوحة"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:base.contact.installer,name:0
|
||||
msgid "Name"
|
||||
msgstr ""
|
||||
msgstr "الاسم"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:base.contact.installer:0
|
||||
msgid "You can migrate Partner's current addresses to the contact."
|
||||
msgstr ""
|
||||
msgstr "يمكنك نقل العناوين الحالية للشريك إلى جهة الاتصال"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.contact,partner_id:0
|
||||
msgid "Main Employer"
|
||||
msgstr ""
|
||||
msgstr "صاحب العمل الرئيسي"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:ir.actions.act_window,name:base_contact.action_base_contact_installer
|
||||
msgid "Address Migration"
|
||||
msgstr ""
|
||||
msgstr "نقل العنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: view:res.partner:0
|
||||
msgid "Postal Address"
|
||||
msgstr ""
|
||||
msgstr "العنوان البريدي"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.node,name:base_contact.process_node_addresses0
|
||||
#: view:res.partner:0
|
||||
msgid "Addresses"
|
||||
msgstr ""
|
||||
msgstr "العناوين"
|
||||
|
||||
#. module: base_contact
|
||||
#: model:process.transition,name:base_contact.process_transition_partnertoaddress0
|
||||
msgid "Partner to address"
|
||||
msgstr ""
|
||||
msgstr "شريك إلى عنوان"
|
||||
|
||||
#. module: base_contact
|
||||
#: field:res.partner.job,date_start:0
|
||||
msgid "Date Start"
|
||||
msgstr ""
|
||||
msgstr "تاريخ البدء"
|
||||
|
||||
#. module: base_contact
|
||||
#: help:res.partner.job,sequence_contact:0
|
||||
msgid ""
|
||||
"Order of importance of this address in the list of "
|
||||
"addresses of the linked contact"
|
||||
msgstr ""
|
||||
msgstr "ترتيب هذا العنوان حسب الأهمية بين عناوين جهة الاتصال"
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
#
|
||||
##############################################################################
|
||||
{
|
||||
"name" : "Base - Password Encryption",
|
||||
"name" : "DB Password Encryption",
|
||||
"version" : "1.1",
|
||||
"author" : ['OpenERP SA', "FS3"],
|
||||
"maintainer" : "OpenERP SA",
|
||||
"website" : "http://www.openerp.com",
|
||||
"category" : "Hidden",
|
||||
"category" : "Tools",
|
||||
'complexity': "easy",
|
||||
"description": """
|
||||
Replaces cleartext passwords in the database with a secure hash
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
#
|
||||
##############################################################################
|
||||
{
|
||||
'name': 'Create IBAN bank accounts',
|
||||
'name': 'IBAN Bank Accounts',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
This module installs the base for IBAN (International Bank Account Number) bank accounts and checks for its validity.
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Module Technical Guide in Restructured Text ',
|
||||
'name': 'Generate Docs of Modules',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
This module generates the Technical Guides of selected modules in Restructured Text format (RST).
|
||||
=================================================================================================
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Base module quality - To check the quality of other modules' ,
|
||||
'name': 'Analyse Module Quality' ,
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
The aim of this module is to check the quality of other modules.
|
||||
================================================================
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
{
|
||||
'name': 'Module Record',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'description': """
|
||||
This module allows you to create a new module without any development.
|
||||
======================================================================
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Base Setup',
|
||||
'name': 'Initial Setup Tools',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
This module helps to configure the system at the installation of a new database.
|
||||
|
|
|
@ -28,290 +28,6 @@ from osv import fields, osv
|
|||
from tools.translate import _
|
||||
from lxml import etree
|
||||
|
||||
#Application and feature chooser, this could be done by introspecting ir.modules
|
||||
DEFAULT_MODULES = {
|
||||
'Customer Relationship Management' : ['crm',],
|
||||
'Sales Management' : ['sale',],
|
||||
'Project Management' : ['project',],
|
||||
'Knowledge Management' : ['document',],
|
||||
'Warehouse Management' : ['stock',],
|
||||
'Manufacturing' : ['mrp'],
|
||||
'Accounting & Finance' : ['account'],
|
||||
'Purchase Management' : ['purchase'],
|
||||
'Human Resources' : ['hr',],
|
||||
'Point of Sale' : ['point_of_sale',],
|
||||
'Marketing' : ['marketing',],
|
||||
}
|
||||
|
||||
class base_setup_installer(osv.osv_memory):
|
||||
_name = 'base.setup.installer'
|
||||
_inherit = 'res.config.installer'
|
||||
|
||||
_columns = {
|
||||
'selection' : fields.text('Selection'),
|
||||
}
|
||||
|
||||
def fields_get(self, cr, uid, fields=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if fields is None:
|
||||
fields = {}
|
||||
|
||||
fields = {}
|
||||
category_proxy = self.pool.get('ir.module.category')
|
||||
domain = [('parent_id', '=', False),
|
||||
('name', '!=', 'Uncategorized'),
|
||||
('visible', '=', True)]
|
||||
category_ids = category_proxy.search(cr, uid, domain, context=context)
|
||||
for category in category_proxy.browse(cr, uid, category_ids, context=context):
|
||||
category_name = 'category_%d' % (category.id,)
|
||||
fields[category_name] = {
|
||||
'type' : 'boolean',
|
||||
'string' : category.name,
|
||||
'name' : category_name,
|
||||
'help' : category.description,
|
||||
}
|
||||
|
||||
module_proxy = self.pool.get('ir.module.module')
|
||||
module_ids = module_proxy.search(cr, uid, [], context=context)
|
||||
for module in module_proxy.browse(cr, uid, module_ids, context=context):
|
||||
module_name = 'module_%d' % (module.id,)
|
||||
module_is_installed = module.state == 'installed'
|
||||
|
||||
fields[module_name] = {
|
||||
'type' : 'boolean',
|
||||
'string' : module.shortdesc,
|
||||
'name' : module_name,
|
||||
'help' : module.description,
|
||||
}
|
||||
|
||||
return fields
|
||||
|
||||
def default_get(self, cr, uid, fields=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if fields is None:
|
||||
fields = {}
|
||||
|
||||
result = {}
|
||||
|
||||
if 'dont_compute_virtual_attributes' not in context:
|
||||
module_proxy = self.pool.get('ir.module.module')
|
||||
module_ids = module_proxy.search(cr, uid, [], context=context)
|
||||
for module in module_proxy.browse(cr, uid, module_ids, context=context):
|
||||
result['module_%d' % (module.id,)] = module.state == 'installed'
|
||||
|
||||
cat_proxy = self.pool.get('ir.module.category')
|
||||
cat_ids = cat_proxy.search(cr, uid, [], context=context)
|
||||
for cat in cat_proxy.browse(cr, uid, cat_ids, context=context):
|
||||
m = DEFAULT_MODULES.get(cat.name,[])
|
||||
r = module_proxy.search(cr, uid, [('state','=','installed'),('name','in',m)])
|
||||
|
||||
result['category_%d' % (cat.id,)] = bool(r) and (len(r) == len(m))
|
||||
|
||||
return result
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='from', context=None, toolbar=False, submenu=False):
|
||||
def in_extended_view_group(cr, uid, context=None):
|
||||
try:
|
||||
model, group_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'group_extended')
|
||||
except ValueError:
|
||||
return False
|
||||
return group_id in self.pool.get('res.users').read(cr, uid, uid, ['groups_id'], context=context)['groups_id']
|
||||
|
||||
result = super(base_setup_installer, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
|
||||
|
||||
module_category_proxy = self.pool.get('ir.module.category')
|
||||
domain = [('parent_id', '=', False),
|
||||
('name', '!=', 'Uncategorized'),
|
||||
('visible', '=', True)]
|
||||
module_category_ids = module_category_proxy.search(cr, uid, domain, context=context, order='sequence asc')
|
||||
|
||||
arch = ['<form string="%s">' % _('Automatic Base Setup')]
|
||||
arch.append('<separator string="%s" colspan="4" />' % _('Install Applications'))
|
||||
module_proxy = self.pool.get('ir.module.module')
|
||||
|
||||
extended_view = in_extended_view_group(cr, uid, context=context)
|
||||
|
||||
for module_category in module_category_proxy.browse(cr, uid, module_category_ids, context=context):
|
||||
domain = [('category_id', '=', module_category.id)]
|
||||
if not extended_view:
|
||||
domain.append(('complexity', '!=', 'expert'))
|
||||
|
||||
modules = module_proxy.browse(cr, uid, module_proxy.search(cr, uid, domain, context=context), context=context)
|
||||
if not modules:
|
||||
continue
|
||||
|
||||
m = DEFAULT_MODULES.get(module_category.name, [])
|
||||
r = module_proxy.search(cr, uid, [('state', '=', 'installed'),('name', 'in', m)], context=context)
|
||||
readonly = bool(r)
|
||||
|
||||
attributes = {
|
||||
'name' : 'category_%d' % (module_category.id,),
|
||||
'on_change' : 'on_change_%s_%d(category_%d)' % ('category', module_category.id, module_category.id,),
|
||||
}
|
||||
if readonly:
|
||||
attributes['modifiers'] = simplejson.dumps({'readonly' : True})
|
||||
|
||||
arch.append("""<field %s />""" % (" ".join(["%s='%s'" % (key, value,)
|
||||
for key, value in attributes.iteritems()]),))
|
||||
|
||||
# Compute the modules to show
|
||||
for module_category in module_category_proxy.browse(cr, uid, module_category_ids, context=context):
|
||||
domain = [('category_id', '=', module_category.id)]
|
||||
|
||||
if not extended_view:
|
||||
domain.append(('complexity', '!=', 'expert'))
|
||||
|
||||
default_modules = DEFAULT_MODULES.get(module_category.name, False)
|
||||
if default_modules:
|
||||
domain.append(('name', 'not in', default_modules))
|
||||
|
||||
modules = module_proxy.browse(cr, uid, module_proxy.search(cr, uid, domain, context=context), context=context)
|
||||
|
||||
if not modules:
|
||||
continue
|
||||
|
||||
modifiers = {
|
||||
'invisible' : [('category_%d' % (module_category.id), '=', False)],
|
||||
}
|
||||
module_modifiers = dict(modifiers)
|
||||
|
||||
arch.append("""<separator string="%s Features" colspan="4" modifiers='%s'/>""" % (
|
||||
cgi.escape(module_category.name),
|
||||
simplejson.dumps(modifiers))
|
||||
)
|
||||
|
||||
for module in modules:
|
||||
#module_modifiers['readonly'] = module.state == 'installed'
|
||||
|
||||
arch.append("""<field name="module_%d" modifiers='%s' />""" % (
|
||||
module.id,
|
||||
simplejson.dumps(module_modifiers))
|
||||
)
|
||||
|
||||
arch.append(
|
||||
'<separator colspan="4" />'
|
||||
'<group colspan="4" col="2">'
|
||||
'<button special="cancel" string="Cancel" icon="gtk-cancel" />'
|
||||
'<button string="Install Modules" type="object" name="apply_cb" icon="gtk-apply" />'
|
||||
'</group>'
|
||||
)
|
||||
|
||||
arch.append('</form>')
|
||||
|
||||
result['arch'] = ''.join(arch)
|
||||
return result
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith('on_change_category_'):
|
||||
def proxy(cr, uid, ids, value, context=None):
|
||||
item = 'category_%s' % name[len('on_change_category_'):]
|
||||
return self._on_change_selection(cr, uid, ids, item, value, context=context)
|
||||
return proxy
|
||||
return getattr(super(base_setup_installer, self), name)
|
||||
|
||||
def _on_change_selection(self, cr, uid, ids, item, value, context=None):
|
||||
if not isinstance(item, basestring) or not value:
|
||||
return {}
|
||||
|
||||
if item.startswith('category_') or item.startswith('module_'):
|
||||
object_name, identifier = item.split('_')
|
||||
else:
|
||||
return {}
|
||||
|
||||
values = {
|
||||
}
|
||||
|
||||
#if object_name == 'category':
|
||||
# module_ids = self.pool.get('ir.module.module').search(cr, uid, [('category_id', '=', int(identifier))], context=context)
|
||||
# for module_id in module_ids:
|
||||
# values['module_%d' % module_id] = 1
|
||||
|
||||
return {'value': values}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
to_install = {'categories' : [], 'modules' : []}
|
||||
|
||||
for key, value in values.iteritems():
|
||||
if value == 1 and (key.startswith('module_') or key.startswith('category_')):
|
||||
kind, identifier = key.split('_')
|
||||
if kind == 'category':
|
||||
to_install['categories'].append(long(identifier))
|
||||
if kind == 'module':
|
||||
to_install['modules'].append(long(identifier))
|
||||
|
||||
values = {
|
||||
'selection' : simplejson.dumps(to_install),
|
||||
}
|
||||
context.update(dont_compute_virtual_attributes=True)
|
||||
return super(base_setup_installer, self).create(cr, uid, values, context=context)
|
||||
|
||||
def apply_cb(self, cr, uid, ids, context=None):
|
||||
category_proxy = self.pool.get('ir.module.category')
|
||||
for installer in self.browse(cr, uid, ids, context=context):
|
||||
to_install = simplejson.loads(installer.selection)
|
||||
|
||||
proxy = self.pool.get('ir.module.module')
|
||||
|
||||
module_ids = proxy.search(cr, uid, [('id', 'in', to_install['modules'])], context=context)
|
||||
modules = set(record['name']
|
||||
for record in proxy.read(cr, uid, module_ids, ['name'], context=context))
|
||||
|
||||
category_ids = category_proxy.search(cr, uid, [('id', 'in', to_install['categories'])], context=context)
|
||||
selected_categories = set(record['name']
|
||||
for record in category_proxy.read(cr, uid, category_ids, ['name'], context=context))
|
||||
|
||||
# FIXME: Use a workaround, but can do better
|
||||
for category_name, default_modules in DEFAULT_MODULES.iteritems():
|
||||
if category_name in selected_categories:
|
||||
modules.update(default_modules)
|
||||
|
||||
# Special Cases:
|
||||
# * project_mrp: the dependencies are sale, project, procurement, mrp_jit
|
||||
if 'sale' in modules and 'project' in modules:
|
||||
modules.add('project_mrp')
|
||||
|
||||
need_update = False
|
||||
module_ids = proxy.search(cr, uid, [('name', 'in', list(modules))], context=context)
|
||||
if module_ids:
|
||||
proxy.state_update(cr, uid, module_ids, 'to install', ['uninstalled'], context=context)
|
||||
need_update = True
|
||||
|
||||
category_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'module_category_hidden_link')
|
||||
while True and category_id:
|
||||
cr.execute("select id, name from ir_module_module m where category_id = %s \
|
||||
and (select count(d.id) from ir_module_module_dependency d \
|
||||
where d.module_id = m.id) = (select count(d.id) from \
|
||||
ir_module_module_dependency d inner join ir_module_module m2 on d.name = m2.name \
|
||||
where d.module_id=m.id and m2.state in %s ) and state = %s",
|
||||
(category_id[1], ('installed', 'to install', 'to upgrade', ), 'uninstalled',))
|
||||
inner_modules = [name for _, name in cr.fetchall()]
|
||||
|
||||
module_ids = proxy.search(cr, uid, [('name', 'in', inner_modules)], context=context)
|
||||
if not module_ids:
|
||||
break
|
||||
|
||||
modules.update(inner_modules)
|
||||
|
||||
proxy.state_update(cr, uid, module_ids, 'to install', ['uninstalled'], context=context)
|
||||
need_update = True
|
||||
|
||||
|
||||
domain = [('name', 'in', list(modules)),
|
||||
('state', '=', 'installed')]
|
||||
for module in proxy.browse(cr, uid, proxy.search(cr, uid, domain, context=context), context):
|
||||
cr.execute("update ir_actions_todo set state='open' \
|
||||
from ir_model_data as data where data.res_id = ir_actions_todo.id \
|
||||
and ir_actions_todo.type='special'\
|
||||
and data.model = 'ir.actions.todo' and data.module=%s", (module.name, ))
|
||||
|
||||
if need_update:
|
||||
cr.commit()
|
||||
self.pool = pooler.restart_pool(cr.dbname, update_module=True)[1]
|
||||
|
||||
return self.pool.get('res.config').next(cr, uid, [], context=context)
|
||||
|
||||
#Migrate data from another application Conf wiz
|
||||
|
||||
class migrade_application_installer_modules(osv.osv_memory):
|
||||
|
|
|
@ -1,36 +1,6 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_base_setup_installer_beta">
|
||||
<field name="name">Install Applications</field>
|
||||
<field name="res_model">base.setup.installer</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="base_setup_installer_todo" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_base_setup_installer_beta" />
|
||||
<field name="category_id" ref="base.category_administration_config"/>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
|
||||
<record id="action_start_configurator" model="ir.actions.server">
|
||||
<field name="name">Start Configuration</field>
|
||||
<field name="model_id" ref="base.model_ir_actions_todo"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code" eval="'# obj is a browse_record and will provide stupid ids to method\n' 'action = pool.get(\'ir.actions.todo\').action_launch(cr, uid, ' + str([ref('base_setup_installer_todo')]) + ', context=context)'"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Add More Features" action="action_start_configurator" id="menu_view_base_module_configuration" parent="base.menu_config" type="server" icon="STOCK_EXECUTE" sequence="1"/>
|
||||
<record id="ir_ui_view_sc_configuration" model="ir.ui.view_sc">
|
||||
<field name="name">Add More Features</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="menu_view_base_module_configuration" />
|
||||
</record>
|
||||
|
||||
<!-- Import or create customers configartion view -->
|
||||
<record id="action_import_create_installer" model="ir.actions.act_window">
|
||||
<field name="name">Create or Import Customers</field>
|
||||
|
@ -162,6 +132,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="context">{'res_id': user.company_id.id}</field>
|
||||
<field name="help">Fill in your company data (address, logo, bank accounts) so that it's printed on your reports. You can click on the button 'Preview Header' in order to check the header/footer of PDF documents.</field>
|
||||
</record>
|
||||
<record id="base_setup_company_todo" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_base_setup_company"/>
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
"name":"Server Object Synchronization",
|
||||
"name":"Multi-DB Synchronization",
|
||||
"version":"0.1",
|
||||
"author":"OpenERP SA",
|
||||
"category":"Hidden",
|
||||
"category":"Tools",
|
||||
"description": """
|
||||
Synchronization with all objects.
|
||||
=================================
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"author": "OpenERP SA",
|
||||
"version": "1.0",
|
||||
"depends": ["base"],
|
||||
"category" : "Hidden",
|
||||
"category" : "Tools",
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
Common base for tools modules.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{
|
||||
'name': 'VAT Number Validation',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
"category": 'Accounting & Finance',
|
||||
'complexity': "easy",
|
||||
'description': """
|
||||
VAT validation for Partners' VAT numbers
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Dashboard Creator',
|
||||
'name': 'Dashboards',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
'complexity': "normal",
|
||||
'description': """
|
||||
Lets the user create a custom dashboard.
|
||||
|
|
|
@ -49,7 +49,7 @@ To access OpenERP Calendar using WebCal to remote site use the URL like:
|
|||
DATABASE_NAME: Name of database on which OpenERP Calendar is created
|
||||
CALENDAR_NAME: Name of calendar to access
|
||||
""",
|
||||
'category': 'Hidden',
|
||||
'category': 'Tools',
|
||||
"author" : "OpenERP SA",
|
||||
'website': 'http://www.openerp.com',
|
||||
"init_xml" : ["caldav_data.xml"],
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"name" : "Claim from Delivery",
|
||||
"version" : "1.0",
|
||||
"author" : "OpenERP SA",
|
||||
"category" : "Hidden",
|
||||
'category': 'Sales Management',
|
||||
"depends" : ["base", "crm_claim", "stock"],
|
||||
"init_xml" : [],
|
||||
"demo_xml" : [],
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
|
||||
{
|
||||
'name': 'Customer & Supplier Relationship Management',
|
||||
'name': 'Customer Relationship Management',
|
||||
'version': '1.0',
|
||||
'category': 'Customer Relationship Management',
|
||||
'complexity': "easy",
|
||||
|
@ -61,7 +61,8 @@ Creates a dashboard for CRM that includes:
|
|||
'mail',
|
||||
'base_calendar',
|
||||
'resource',
|
||||
'board'
|
||||
'board',
|
||||
'fetchmail'
|
||||
],
|
||||
'init_xml': [
|
||||
'crm_data.xml',
|
||||
|
@ -118,20 +119,17 @@ Creates a dashboard for CRM that includes:
|
|||
'crm_phonecall_demo.xml',
|
||||
],
|
||||
'test': [
|
||||
'test/test_crm_lead.yml',
|
||||
'test/test_crm_meeting.yml',
|
||||
'test/test_crm_opportunity.yml',
|
||||
'test/test_crm_phonecall.yml',
|
||||
'test/test_crm_recurrent_meeting.yml',
|
||||
'test/test_crm_stage_changes.yml',
|
||||
'test/test_crm_recurrent_meeting_case2.yml',
|
||||
'test/test_crm_lead_case2.yml',
|
||||
'test/test_crm_opportunity_case2.yml',
|
||||
'test/test_crm_phonecall_case2.yml',
|
||||
'test/test_crm_partner2opportunity.yml',
|
||||
'test/test_crm_segmentation.yml',
|
||||
'test/process/communication_with_customer.yml',
|
||||
'test/process/lead2opportunity2win.yml',
|
||||
'test/process/merge_opportunity.yml',
|
||||
'test/process/cancel_lead.yml',
|
||||
'test/process/segmentation.yml',
|
||||
'test/ui/crm_demo.yml',
|
||||
'test/ui/duplicate_lead.yml',
|
||||
'test/ui/delete_lead.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'core': True,
|
||||
'active': False,
|
||||
'certificate': '0079056041421',
|
||||
'images': ['images/sale_crm_crm_dashboard.png', 'images/crm_dashboard.jpeg','images/leads.jpeg','images/meetings.jpeg','images/opportunities.jpeg','images/outbound_calls.jpeg','images/stages.jpeg'],
|
||||
|
|
|
@ -468,10 +468,12 @@ class crm_case(crm_base):
|
|||
self._action(cr, uid, cases, state)
|
||||
return True
|
||||
|
||||
#DEAD Code
|
||||
def remind_partner(self, cr, uid, ids, context=None, attach=False):
|
||||
return self.remind_user(cr, uid, ids, context, attach,
|
||||
destination=False)
|
||||
|
||||
#DEAD Code
|
||||
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
|
||||
mail_message = self.pool.get('mail.message')
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<data>
|
||||
<record id="base.user_demo" model="res.users">
|
||||
<field name="groups_id" eval="[(4,ref('base.group_sale_salesman'))]"/>
|
||||
</record>
|
||||
|
@ -12,5 +12,17 @@
|
|||
<field name="res_id" ref="crm.menu_crm_case_categ_meet"/>
|
||||
</record>
|
||||
|
||||
<record model="crm.case.section" id="section_sales_marketing_department">
|
||||
<field name="name">Sales Marketing Department</field>
|
||||
<field name="code">Sales Marketing</field>
|
||||
<field name="parent_id" ref="crm.section_sales_department"></field>
|
||||
</record>
|
||||
|
||||
<record model="crm.segmentation" id="crm_segmentation0">
|
||||
<field name="name">OpenERP partners</field>
|
||||
<field name="exclusif">True</field>
|
||||
<field name="categ_id" ref="base.res_partner_category_2"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -27,7 +27,7 @@ from tools.translate import _
|
|||
from crm import crm_case
|
||||
import binascii
|
||||
import tools
|
||||
|
||||
from mail.mail_message import to_email
|
||||
|
||||
CRM_LEAD_PENDING_STATES = (
|
||||
crm.AVAILABLE_STATES[2][0], # Cancelled
|
||||
|
@ -352,36 +352,380 @@ class crm_lead(crm_case, osv.osv):
|
|||
"""
|
||||
return self.set_priority(cr, uid, ids, '3')
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, context=None):
|
||||
""" Precomputation for converting lead to opportunity
|
||||
|
||||
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
|
||||
# prepare opportunity data into dictionary for merging
|
||||
opportunities = self.browse(cr, uid, ids, context=context)
|
||||
def _get_first_not_null(attr):
|
||||
if hasattr(oldest, attr):
|
||||
return getattr(oldest, attr)
|
||||
for opportunity in opportunities:
|
||||
if hasattr(opportunity, attr):
|
||||
return getattr(opportunity, attr)
|
||||
return False
|
||||
|
||||
def _get_first_not_null_id(attr):
|
||||
res = _get_first_not_null(attr)
|
||||
return res and res.id or False
|
||||
|
||||
def _concat_all(attr):
|
||||
return ', '.join(filter(lambda x: x, [getattr(opportunity, attr) or '' for opportunity in opportunities if hasattr(opportunity, attr)]))
|
||||
|
||||
data = {}
|
||||
for field_name in fields:
|
||||
field_info = self._all_columns.get(field_name)
|
||||
if field_info is None:
|
||||
continue
|
||||
field = field_info.column
|
||||
if field._type in ('many2many', 'one2many'):
|
||||
continue
|
||||
elif field._type == 'many2one':
|
||||
data[field_name] = _get_first_not_null_id(field_name) # !!
|
||||
elif field._type == 'text':
|
||||
data[field_name] = _concat_all(field_name) #not lost
|
||||
else:
|
||||
data[field_name] = _get_first_not_null(field_name) #not lost
|
||||
return data
|
||||
|
||||
def _merge_find_oldest(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
#TOCHECK: where pass 'convert' in context ?
|
||||
if context.get('convert'):
|
||||
ids = list(set(ids) - set(context.get('lead_ids', False)) )
|
||||
|
||||
#search opportunities order by create date
|
||||
opportunity_ids = self.search(cr, uid, [('id', 'in', ids)], order='create_date' , context=context)
|
||||
oldest_id = opportunity_ids[0]
|
||||
return self.browse(cr, uid, oldest_id, context=context)
|
||||
|
||||
def _mail_body_text(self, cr, uid, lead, fields, title=False, context=None):
|
||||
body = []
|
||||
if title:
|
||||
body.append("%s\n" % (title))
|
||||
for field_name in fields:
|
||||
field_info = self._all_columns.get(field_name)
|
||||
if field_info is None:
|
||||
continue
|
||||
field = field_info.column
|
||||
value = None
|
||||
|
||||
if field._type == 'selection':
|
||||
if hasattr(field.selection, '__call__'):
|
||||
key = field.selection(self, cr, uid, context=context)
|
||||
else:
|
||||
key = field.selection
|
||||
value = dict(key).get(lead[field_name], lead[field_name])
|
||||
elif field._type == 'many2one':
|
||||
if lead[field_name]:
|
||||
value = lead[field_name].name_get()[0][1]
|
||||
else:
|
||||
value = lead[field_name]
|
||||
|
||||
body.append("%s: %s" % (field.string, value or ''))
|
||||
return "\n".join(body + ['---'])
|
||||
|
||||
def _merge_notification(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
#TOFIX: mail template should be used instead of fix body, subject text
|
||||
details = []
|
||||
merge_message = _('Merged opportunities')
|
||||
subject = [merge_message]
|
||||
fields = ['name', 'partner_id', 'stage_id', 'section_id', 'user_id', 'categ_id', 'channel_id', 'company_id', 'contact_name',
|
||||
'email_from', 'phone', 'fax', 'mobile', 'state_id', 'description', 'probability', 'planned_revenue',
|
||||
'country_id', 'city', 'street', 'street2', 'zip']
|
||||
for opportunity in opportunities:
|
||||
subject.append(opportunity.name)
|
||||
title = "%s : %s" % (merge_message, opportunity.name)
|
||||
details.append(self._mail_body_text(cr, uid, opportunity, fields, title=title, context=context))
|
||||
|
||||
subject = subject[0] + ", ".join(subject[1:])
|
||||
details = "\n\n".join(details)
|
||||
return self.message_append(cr, uid, [opportunity_id], subject, body_text=details, context=context)
|
||||
|
||||
def _merge_opportunity_history(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
message = self.pool.get('mail.message')
|
||||
for opportunity in opportunities:
|
||||
for history in opportunity.message_ids:
|
||||
message.write(cr, uid, history.id, {
|
||||
'res_id': opportunity_id,
|
||||
'subject' : _("From %s : %s") % (opportunity.name, history.subject)
|
||||
}, context=context)
|
||||
|
||||
return True
|
||||
|
||||
def _merge_opportunity_attachments(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
attachment = self.pool.get('ir.attachment')
|
||||
|
||||
# return attachments of opportunity
|
||||
def _get_attachments(opportunity_id):
|
||||
attachment_ids = attachment.search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', opportunity_id)], context=context)
|
||||
return attachment.browse(cr, uid, attachment_ids, context=context)
|
||||
|
||||
count = 1
|
||||
first_attachments = _get_attachments(opportunity_id)
|
||||
for opportunity in opportunities:
|
||||
attachments = _get_attachments(opportunity.id)
|
||||
for first in first_attachments:
|
||||
for attachment in attachments:
|
||||
if attachment.name == first.name:
|
||||
values = dict(
|
||||
name = "%s (%s)" % (attachment.name, count,),
|
||||
res_id = opportunity_id,
|
||||
)
|
||||
attachment.write(values)
|
||||
count+=1
|
||||
|
||||
return True
|
||||
|
||||
def merge_opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
To merge opportunities
|
||||
:param ids: list of opportunities ids to merge
|
||||
"""
|
||||
if context is None: context = {}
|
||||
|
||||
#TOCHECK: where pass lead_ids in context?
|
||||
lead_ids = context and context.get('lead_ids', []) or []
|
||||
|
||||
if len(ids) <= 1:
|
||||
raise osv.except_osv(_('Warning !'),_('Please select more than one opportunities.'))
|
||||
|
||||
ctx_opportunities = self.browse(cr, uid, lead_ids, context=context)
|
||||
opportunities = self.browse(cr, uid, ids, context=context)
|
||||
opportunities_list = list(set(opportunities) - set(ctx_opportunities))
|
||||
oldest = self._merge_find_oldest(cr, uid, ids, context=context)
|
||||
if ctx_opportunities :
|
||||
first_opportunity = ctx_opportunities[0]
|
||||
tail_opportunities = opportunities_list
|
||||
else:
|
||||
first_opportunity = opportunities_list[0]
|
||||
tail_opportunities = opportunities_list[1:]
|
||||
|
||||
fields = ['partner_id', 'title', 'name', 'categ_id', 'channel_id', 'city', 'company_id', 'contact_name', 'country_id',
|
||||
'partner_address_id', 'type_id', 'user_id', 'section_id', 'state_id', 'description', 'email', 'fax', 'mobile',
|
||||
'partner_name', 'phone', 'probability', 'planned_revenue', 'street', 'street2', 'zip', 'create_date', 'date_action_last',
|
||||
'date_action_next', 'email_from', 'email_cc', 'partner_name']
|
||||
|
||||
data = self._merge_data(cr, uid, ids, oldest, fields, context=context)
|
||||
|
||||
# merge data into first opportunity
|
||||
self.write(cr, uid, [first_opportunity.id], data, context=context)
|
||||
|
||||
#copy message and attachements into the first opportunity
|
||||
self._merge_opportunity_history(cr, uid, first_opportunity.id, tail_opportunities, context=context)
|
||||
self._merge_opportunity_attachments(cr, uid, first_opportunity.id, tail_opportunities, context=context)
|
||||
|
||||
#Notification about loss of information
|
||||
self._merge_notification(cr, uid, first_opportunity, opportunities, context=context)
|
||||
#delete tail opportunities
|
||||
self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
|
||||
|
||||
#open first opportunity
|
||||
self.case_open(cr, uid, [first_opportunity.id])
|
||||
return first_opportunity.id
|
||||
|
||||
def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
|
||||
crm_stage = self.pool.get('crm.case.stage')
|
||||
contact_id = False
|
||||
if customer:
|
||||
contact_id = self.pool.get('res.partner').address_get(cr, uid, [customer.id])['default']
|
||||
if not section_id:
|
||||
section_id = lead.section_id and lead.section_id.id or False
|
||||
if section_id:
|
||||
stage_ids = crm_stage.search(cr, uid, [('sequence','>=',1), ('section_ids','=', section_id)])
|
||||
else:
|
||||
stage_ids = crm_stage.search(cr, uid, [('sequence','>=',1)])
|
||||
stage_id = stage_ids and stage_ids[0] or False
|
||||
return {
|
||||
'planned_revenue': lead.planned_revenue,
|
||||
'probability': lead.probability,
|
||||
'name': lead.name,
|
||||
'partner_id': customer and customer.id or False,
|
||||
'user_id': (lead.user_id and lead.user_id.id),
|
||||
'type': 'opportunity',
|
||||
'stage_id': stage_id or False,
|
||||
'date_action': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'partner_address_id': contact_id
|
||||
}
|
||||
def _convert_opportunity_notification(self, cr, uid, lead, context=None):
|
||||
success_message = _("Lead '%s' has been converted to an opportunity.") % lead.name
|
||||
self.message_append(cr, uid, [lead.id], success_message, body_text=success_message, context=context)
|
||||
self.log(cr, uid, lead.id, success_message)
|
||||
self._send_mail_to_salesman(cr, uid, lead, context=context)
|
||||
return True
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
mail_message = self.pool.get('mail.message')
|
||||
customer = False
|
||||
if partner_id:
|
||||
customer = partner.browse(cr, uid, partner_id, context=context)
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
if lead.state in ('done', 'cancel'):
|
||||
continue
|
||||
if user_ids or section_id:
|
||||
self.allocate_salesman(cr, uid, [lead.id], user_ids, section_id, context=context)
|
||||
|
||||
vals = self._convert_opportunity_data(cr, uid, lead, customer, section_id, context=context)
|
||||
self.write(cr, uid, [lead.id], vals, context=context)
|
||||
|
||||
self._convert_opportunity_notification(cr, uid, lead, context=context)
|
||||
#TOCHECK: why need to change partner details in all messages of lead ?
|
||||
if lead.partner_id:
|
||||
msg_ids = [ x.id for x in lead.message_ids]
|
||||
mail_message.write(cr, uid, msg_ids, {
|
||||
'partner_id': lead.partner_id.id
|
||||
}, context=context)
|
||||
return True
|
||||
|
||||
def _lead_create_partner(self, cr, uid, lead, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
partner_id = partner.create(cr, uid, {
|
||||
'name': lead.partner_name or lead.contact_name or lead.name,
|
||||
'user_id': lead.user_id.id,
|
||||
'comment': lead.description,
|
||||
'section_id': lead.section_id.id or False,
|
||||
'address': []
|
||||
})
|
||||
return partner_id
|
||||
|
||||
def _lead_set_partner(self, cr, uid, lead, partner_id, context=None):
|
||||
res = False
|
||||
res_partner = self.pool.get('res.partner')
|
||||
if partner_id:
|
||||
res_partner.write(cr, uid, partner_id, {'section_id': lead.section_id.id or False})
|
||||
contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
|
||||
res = lead.write({'partner_id' : partner_id, 'partner_address_id': contact_id}, context=context)
|
||||
|
||||
return res
|
||||
|
||||
def _lead_create_partner_address(self, cr, uid, lead, partner_id, context=None):
|
||||
address = self.pool.get('res.partner.address')
|
||||
return address.create(cr, uid, {
|
||||
'partner_id': partner_id,
|
||||
'name': lead.contact_name,
|
||||
'phone': lead.phone,
|
||||
'mobile': lead.mobile,
|
||||
'email': lead.email_from and to_email(lead.email_from)[0],
|
||||
'fax': lead.fax,
|
||||
'title': lead.title and lead.title.id or False,
|
||||
'function': lead.function,
|
||||
'street': lead.street,
|
||||
'street2': lead.street2,
|
||||
'zip': lead.zip,
|
||||
'city': lead.city,
|
||||
'country_id': lead.country_id and lead.country_id.id or False,
|
||||
'state_id': lead.state_id and lead.state_id.id or False,
|
||||
})
|
||||
|
||||
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
"""
|
||||
This function convert partner based on action.
|
||||
if action is 'create', create new partner with contact and assign lead to new partner_id.
|
||||
otherwise assign lead to specified partner_id
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
context.update({'active_ids': ids})
|
||||
partner_ids = {}
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
if action == 'create':
|
||||
if not partner_id:
|
||||
partner_id = self._lead_create_partner(cr, uid, lead, context=context)
|
||||
self._lead_create_partner_address(cr, uid, lead, partner_id, context=context)
|
||||
self._lead_set_partner(cr, uid, lead, partner_id, context=context)
|
||||
partner_ids[lead.id] = partner_id
|
||||
return partner_ids
|
||||
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
value = {}
|
||||
def _send_mail_to_salesman(self, cr, uid, lead, context=None):
|
||||
"""
|
||||
Send mail to salesman with updated Lead details.
|
||||
@ lead: browse record of 'crm.lead' object.
|
||||
"""
|
||||
#TOFIX: mail template should be used here instead of fix subject, body text.
|
||||
message = self.pool.get('mail.message')
|
||||
email_to = lead.user_id and lead.user_id.user_email
|
||||
if not email_to:
|
||||
return False
|
||||
|
||||
email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.user_email or email_to
|
||||
partner = lead.partner_id and lead.partner_id.name or lead.partner_name
|
||||
subject = "lead %s converted into opportunity" % lead.name
|
||||
body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description)
|
||||
return message.schedule_with_attach(cr, uid, email_from, [email_to], subject, body)
|
||||
|
||||
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
context.update({'active_id': case.id})
|
||||
data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_partner')
|
||||
view_id1 = False
|
||||
if data_id:
|
||||
view_id1 = data_obj.browse(cr, uid, data_id, context=context).res_id
|
||||
value = {
|
||||
'name': _('Create Partner'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form,tree',
|
||||
'res_model': 'crm.lead2opportunity.partner',
|
||||
'view_id': False,
|
||||
'context': context,
|
||||
'views': [(view_id1, 'form')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
'nodestroy': True
|
||||
def allocate_salesman(self, cr, uid, ids, user_ids, team_id=False, context=None):
|
||||
index = 0
|
||||
for lead_id in ids:
|
||||
value = {}
|
||||
if team_id:
|
||||
value['section_id'] = team_id
|
||||
if index < len(user_ids):
|
||||
value['user_id'] = user_ids[index]
|
||||
index += 1
|
||||
if value:
|
||||
self.write(cr, uid, [lead_id], value, context=context)
|
||||
return True
|
||||
|
||||
def schedule_phonecall(self, cr, uid, ids, schedule_time, call_summary, desc, phone, contact_name, user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
|
||||
"""
|
||||
action :('schedule','Schedule a call'), ('log','Log a call')
|
||||
"""
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
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:
|
||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||
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
|
||||
if not user_id:
|
||||
user_id = lead.user_id and lead.user_id.id or False
|
||||
vals = {
|
||||
'name' : call_summary,
|
||||
'opportunity_id' : lead.id,
|
||||
'user_id' : user_id or False,
|
||||
'categ_id' : categ_id or False,
|
||||
'description' : desc or '',
|
||||
'date' : schedule_time,
|
||||
'section_id' : section_id or False,
|
||||
'partner_id': lead.partner_id and lead.partner_id.id or False,
|
||||
'partner_address_id': lead.partner_address_id and lead.partner_address_id.id or False,
|
||||
'partner_phone' : phone or lead.phone or (lead.partner_address_id and lead.partner_address_id.phone or False),
|
||||
'partner_mobile' : lead.partner_address_id and lead.partner_address_id.mobile or False,
|
||||
'priority': lead.priority,
|
||||
}
|
||||
return value
|
||||
|
||||
new_id = phonecall.create(cr, uid, vals, context=context)
|
||||
phonecall.case_open(cr, uid, [new_id])
|
||||
if action == 'log':
|
||||
phonecall.case_close(cr, uid, [new_id])
|
||||
phonecall_dict[lead.id] = new_id
|
||||
return phonecall_dict
|
||||
|
||||
|
||||
def redirect_opportunity_view(self, cr, uid, opportunity_id, context=None):
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
# Get Opportunity views
|
||||
form_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
tree_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree, form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity')],
|
||||
'res_id': int(opportunity_id),
|
||||
'view_id': False,
|
||||
'views': [(form_view and form_view[1] or False, 'form'),
|
||||
(tree_view and tree_view[1] or False, 'tree'),
|
||||
(False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
|
||||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||
"""Automatically calls when new email message arrives"""
|
||||
|
@ -447,17 +791,10 @@ class crm_lead(crm_case, osv.osv):
|
|||
data_obj = self.pool.get('ir.model.data')
|
||||
for opp in self.browse(cr, uid, ids, context=context):
|
||||
# Get meeting views
|
||||
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
|
||||
res = data_obj.read(cr, uid, result, ['res_id'])
|
||||
id1 = data_obj._get_id(cr, uid, 'crm', 'crm_case_calendar_view_meet')
|
||||
id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_form_view_meet')
|
||||
id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_tree_view_meet')
|
||||
if id1:
|
||||
id1 = data_obj.browse(cr, uid, id1, context=context).res_id
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
if id3:
|
||||
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
|
||||
tree_view = data_obj.get_object_reference(cr, uid, 'crm', 'crm_case_tree_view_meet')
|
||||
form_view = data_obj.get_object_reference(cr, uid, 'crm', 'crm_case_form_view_meet')
|
||||
calander_view = data_obj.get_object_reference(cr, uid, 'crm', 'crm_case_calendar_view_meet')
|
||||
search_view = data_obj.get_object_reference(cr, uid, 'crm', 'view_crm_case_meetings_filter')
|
||||
context.update({
|
||||
'default_opportunity_id': opp.id,
|
||||
'default_partner_id': opp.partner_id and opp.partner_id.id or False,
|
||||
|
@ -474,9 +811,9 @@ class crm_lead(crm_case, osv.osv):
|
|||
'view_mode': 'calendar,form,tree',
|
||||
'res_model': 'crm.meeting',
|
||||
'view_id': False,
|
||||
'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
|
||||
'views': [(calander_view and calander_view[1] or False, 'calendar'), (form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': res['res_id'],
|
||||
'search_view_id': search_view and search_view[1] or False,
|
||||
'nodestroy': True
|
||||
}
|
||||
return value
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<data>
|
||||
<!-- Demo Leads -->
|
||||
<record id="crm_case_itisatelesalescampaign0" model="crm.lead">
|
||||
<field name="type_id" ref="crm.type_lead1"/>
|
||||
|
@ -9,8 +9,8 @@
|
|||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'The Oil Company'" name="partner_name"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'Luc Latour'" name="contact_name"/>
|
||||
<field name="section_id" ref="crm.section_sales_marketing_department"/>
|
||||
<field eval="'Luc Latour'" name="contact_name"/>
|
||||
<field name="title" ref="base.res_partner_title_sir"/>
|
||||
<field eval="'Training Manager'" name="function"/>
|
||||
<field eval="'Paris'" name="city"/>
|
||||
|
@ -92,7 +92,7 @@
|
|||
<field eval="'Bruxelles'" name="city"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="section_id" ref="crm.section_sales_marketing_department"/>
|
||||
<field eval="'(333) 715-1450'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
|
|
|
@ -60,16 +60,23 @@
|
|||
<record model="ir.actions.act_window" id="crm_case_category_act_oppor11">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="res_model">crm.lead</field>
|
||||
<field name="view_mode">tree,form,graph,calendar,kanban</field>
|
||||
<field name="view_mode">kanban,tree,form,graph,calendar</field>
|
||||
<field name="domain">[('type','=','opportunity')]</field>
|
||||
<field name="context">{'search_default_user_id':uid,'search_default_new':1, 'search_default_open':1, 'search_default_section_id':section_id, 'stage_type': 'opportunity', 'default_type': 'opportunity'}</field>
|
||||
<field name="view_id" ref="crm_case_tree_view_oppor"/>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
|
||||
<field name="help">With opportunities you can manage and keep track of your sales pipeline by creating specific customer- or prospect-related sales documents to follow up potential sales. Information such as expected revenue, opportunity stage, expected closing date, communication history and much more can be stored. Opportunities can be connected to the email gateway: new emails may create opportunities, each of them automatically gets the history of the conversation with the customer.
|
||||
|
||||
You and your team(s) will be able to plan meetings and phone calls from opportunities, convert them into quotations, manage related documents, track all customer related activities, and much more.</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_kanban_view_oppor11">
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="crm_case_kanban_view_leads"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_view_oppor11">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
|
|
|
@ -59,10 +59,11 @@
|
|||
widget="selection"
|
||||
domain="[('object_id.model','=','crm.lead')]"/>
|
||||
<button
|
||||
name="convert_opportunity"
|
||||
name="%(crm.action_crm_lead2opportunity_partner)d"
|
||||
string="Convert to Opportunity"
|
||||
help="Convert to Opportunity" icon="gtk-go-forward"
|
||||
type="object"/>
|
||||
type="action"
|
||||
/>
|
||||
<newline />
|
||||
<field name="user_id" />
|
||||
<field name="section_id" widget="selection" />
|
||||
|
@ -142,6 +143,29 @@
|
|||
type="object" icon="gtk-convert" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Communication & History" groups="base.group_extended">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" widget="char" size="512"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
<button
|
||||
string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
context="{'model': 'crm.lead' }"
|
||||
icon="terp-document-new" type="action" />
|
||||
<button string="Send New Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
icon="terp-mail-message-new" type="action"/>
|
||||
</page>
|
||||
<page string="Extra Info" groups="base.group_extended">
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Categorization" colspan="2" col="2"/>
|
||||
|
@ -170,58 +194,6 @@
|
|||
<field name="day_close"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Communication & History" groups="base.group_extended">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" widget="char" size="512"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree,form" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
<button
|
||||
string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
<form string="History">
|
||||
<group col="4" colspan="4">
|
||||
<group col="2" colspan="2" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="email_from"/>
|
||||
<field name="email_to" size="512"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<field name="date"/>
|
||||
<field name="email_cc" size="512" attrs="{'invisible': [('email_from', '=', False)]}"/>
|
||||
</group>
|
||||
<field name="subject" colspan="4" widget="char" attrs="{'invisible': [('email_from', '=', False)]}" size="512"/>
|
||||
<field name="display_text" colspan="4" attrs="{'invisible': [('email_from', '!=', False)]}"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="body_text" colspan="4" nolabel="1"/>
|
||||
<group attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<button colspan="4" string="Reply"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply'}"
|
||||
icon="terp-mail-replied" type="action"/>
|
||||
</group>
|
||||
|
||||
</page>
|
||||
<page string="Attachments" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
context="{'model': 'crm.lead' }"
|
||||
icon="terp-document-new" type="action" />
|
||||
<button string="Send New Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
icon="terp-mail-message-new" type="action"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -325,7 +297,7 @@
|
|||
<a t-if="record.priority.raw_value == 1" icon="star-on" type="object" name="set_normal_priority"/>
|
||||
<a t-if="record.priority.raw_value != 1" icon="star-off" type="object" name="set_high_priority" style="opacity:0.6; filter:alpha(opacity=60);"/>
|
||||
</td>
|
||||
<td align="left" valign="middle" class="oe_kanban_title3" tooltip="lead_details">
|
||||
<td align="left" valign="middle" class="oe_kanban_title" tooltip="lead_details">
|
||||
<field name="partner_id"/>
|
||||
<t t-if="record.planned_revenue.raw_value">
|
||||
- <t t-esc="Math.round(record.planned_revenue.value)"/>
|
||||
|
@ -459,7 +431,7 @@
|
|||
<field name="name">Opportunities</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">form</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Opportunities">
|
||||
<group colspan="4" col="7">
|
||||
|
@ -577,7 +549,7 @@
|
|||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" widget="char" size="512"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree,form" readonly="1">
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
|
@ -587,34 +559,6 @@
|
|||
context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
<form string="History">
|
||||
<group col="4" colspan="4">
|
||||
<group col="2" colspan="2" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="email_from"/>
|
||||
<field name="email_to" size="512"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<field name="date"/>
|
||||
<field name="email_cc" size="512" attrs="{'invisible': [('email_from', '=', False)]}"/>
|
||||
</group>
|
||||
<field name="subject" colspan="4" widget="char" attrs="{'invisible': [('email_from', '=', False)]}" size="512"/>
|
||||
<field name="display_text" colspan="4" attrs="{'invisible': [('email_from', '!=', False)]}"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="body_text" colspan="4" nolabel="1"/>
|
||||
<group attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<button colspan="4" string="Reply"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply'}"
|
||||
icon="terp-mail-replied" type="action"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Attachments" attrs="{'invisible': [('email_from', '=', False)]}">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
|
@ -705,6 +649,7 @@
|
|||
domain="[('state','=','pending')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" string="Opportunity / Customer" filter_domain="['|','|','|',('partner_id','ilike',self),('partner_name','ilike',self),('email_from','ilike',self),('name', 'ilike', self)]"/>
|
||||
<field name="partner_id" string="Customer / Email" filter_domain="['|','|',('partner_id','ilike',self),('partner_name','ilike',self),('email_from','ilike',self)]"/>
|
||||
<field name="user_id">
|
||||
<filter icon="terp-personal-"
|
||||
domain="[('user_id','=', False)]"
|
||||
|
|
|
@ -102,11 +102,6 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
|
||||
def case_close(self, cr, uid, ids, *args):
|
||||
"""Overrides close for crm_case for setting close date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of case Ids
|
||||
@param *args: Tuple Value for additional Params
|
||||
"""
|
||||
res = True
|
||||
for phone in self.browse(cr, uid, ids):
|
||||
|
@ -121,11 +116,6 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
|
||||
def case_reset(self, cr, uid, ids, *args):
|
||||
"""Resets case as Todo
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of case Ids
|
||||
@param *args: Tuple Value for additional Params
|
||||
"""
|
||||
res = super(crm_phonecall, self).case_reset(cr, uid, ids, args, 'crm.phonecall')
|
||||
self.write(cr, uid, ids, {'duration': 0.0})
|
||||
|
@ -134,25 +124,147 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
|
||||
def case_open(self, cr, uid, ids, *args):
|
||||
"""Overrides cancel for crm_case for setting Open Date
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of case's Ids
|
||||
@param *args: Give Tuple Value
|
||||
"""
|
||||
res = super(crm_phonecall, self).case_open(cr, uid, ids, *args)
|
||||
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
return res
|
||||
|
||||
def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
|
||||
user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
|
||||
"""
|
||||
action :('schedule','Schedule a call'), ('log','Log a call')
|
||||
"""
|
||||
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:
|
||||
categ_id = model_data.browse(cr, uid, res_id, context=context).res_id
|
||||
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
|
||||
if not user_id:
|
||||
user_id = call.user_id and call.user_id.id or False
|
||||
vals = {
|
||||
'name' : call_summary,
|
||||
'user_id' : user_id or False,
|
||||
'categ_id' : categ_id or False,
|
||||
'description' : call.description or False,
|
||||
'date' : schedule_time,
|
||||
'section_id' : section_id or False,
|
||||
'partner_id': call.partner_id and call.partner_id.id or False,
|
||||
'partner_address_id': call.partner_address_id and call.partner_address_id.id or False,
|
||||
'partner_phone' : call.partner_phone,
|
||||
'partner_mobile' : call.partner_mobile,
|
||||
'priority': call.priority,
|
||||
}
|
||||
|
||||
new_id = self.create(cr, uid, vals, context=context)
|
||||
self.case_open(cr, uid, [new_id])
|
||||
if action == 'log':
|
||||
self.case_close(cr, uid, [new_id])
|
||||
phonecall_dict[call.id] = new_id
|
||||
return phonecall_dict
|
||||
|
||||
def _call_create_partner(self, cr, uid, phonecall, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
partner_id = partner.create(cr, uid, {
|
||||
'name': phonecall.name,
|
||||
'user_id': phonecall.user_id.id,
|
||||
'comment': phonecall.description,
|
||||
'address': []
|
||||
})
|
||||
return partner_id
|
||||
|
||||
def _call_set_partner(self, cr, uid, ids, partner_id, context=None):
|
||||
return self.write(cr, uid, ids, {'partner_id' : partner_id}, context=context)
|
||||
|
||||
def _call_create_partner_address(self, cr, uid, phonecall, partner_id, context=None):
|
||||
address = self.pool.get('res.partner.address')
|
||||
return address.create(cr, uid, {
|
||||
'partner_id': partner_id,
|
||||
'name': phonecall.name,
|
||||
'phone': phonecall.partner_phone,
|
||||
})
|
||||
|
||||
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
"""
|
||||
This function convert partner based on action.
|
||||
if action is 'create', create new partner with contact and assign lead to new partner_id.
|
||||
otherwise assign lead to specified partner_id
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
partner_ids = {}
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
if action == 'create':
|
||||
if not partner_id:
|
||||
partner_id = self._call_create_partner(cr, uid, call, context=context)
|
||||
self._call_create_partner_address(cr, uid, call, partner_id, context=context)
|
||||
self._call_set_partner(cr, uid, [call.id], partner_id, context=context)
|
||||
partner_ids[call.id] = partner_id
|
||||
return partner_ids
|
||||
|
||||
|
||||
def redirect_phonecall_view(self, cr, uid, phonecall_id, context=None):
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
# Select the view
|
||||
tree_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_tree_view')
|
||||
form_view = model_data.get_object_reference(cr, uid, 'crm', 'crm_case_phone_form_view')
|
||||
search_view = model_data.get_object_reference(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
|
||||
value = {
|
||||
'name': _('Phone Call'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'crm.phonecall',
|
||||
'res_id' : int(phonecall_id),
|
||||
'views': [(form_view and form_view[1] or False, 'form'), (tree_view and tree_view[1] or False, 'tree'), (False, 'calendar')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': search_view and search_view[1] or False,
|
||||
}
|
||||
return value
|
||||
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
address = self.pool.get('res.partner.address')
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
opportunity_dict = {}
|
||||
default_contact = False
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
if not partner_id:
|
||||
partner_id = call.partner_id and call.partner_id.id or False
|
||||
if partner_id:
|
||||
address_id = partner.address_get(cr, uid, [partner_id])['default']
|
||||
if address_id:
|
||||
default_contact = address.browse(cr, uid, address_id, context=context)
|
||||
opportunity_id = opportunity.create(cr, uid, {
|
||||
'name': opportunity_summary or call.name,
|
||||
'planned_revenue': planned_revenue,
|
||||
'probability': probability,
|
||||
'partner_id': partner_id or False,
|
||||
'partner_address_id': default_contact and default_contact.id,
|
||||
'phone': default_contact and default_contact.phone,
|
||||
'mobile': default_contact and default_contact.mobile,
|
||||
'section_id': call.section_id and call.section_id.id or False,
|
||||
'description': call.description or False,
|
||||
'priority': call.priority,
|
||||
'type': 'opportunity',
|
||||
'phone': call.partner_phone or False,
|
||||
})
|
||||
vals = {
|
||||
'partner_id': partner_id,
|
||||
'opportunity_id' : opportunity_id,
|
||||
}
|
||||
self.write(cr, uid, [call.id], vals)
|
||||
self.case_close(cr, uid, [call.id])
|
||||
opportunity.case_open(cr, uid, [opportunity_id])
|
||||
opportunity_dict[call.id] = opportunity_id
|
||||
return opportunity_dict
|
||||
|
||||
def action_make_meeting(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This opens Meeting's calendar view to schedule meeting on current Phonecall
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Phonecall to Meeting IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : Dictionary value for created Meeting view
|
||||
"""
|
||||
value = {}
|
||||
|
|
|
@ -83,9 +83,6 @@
|
|||
<field eval="2.08" name="duration"/>
|
||||
</record>
|
||||
<record id="crm_case_phone06" model="crm.phonecall">
|
||||
<field name="partner_address_id" ref="base.res_partner_address_1"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Bad time"" name="name"/>
|
||||
|
|
|
@ -33,6 +33,44 @@ class res_partner(osv.osv):
|
|||
'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id',\
|
||||
'Phonecalls'),
|
||||
}
|
||||
|
||||
def redirect_partner_form(self, cr, uid, partner_id, context=None):
|
||||
search_view = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'view_res_partner_filter')
|
||||
value = {
|
||||
'domain': "[]",
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form,tree',
|
||||
'res_model': 'res.partner',
|
||||
'res_id': int(partner_id),
|
||||
'view_id': False,
|
||||
'context': context,
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': search_view and search_view[1] or False
|
||||
}
|
||||
return value
|
||||
|
||||
def make_opportunity(self, cr, uid, ids, opportunity_summary, planned_revenue=0.0, probability=0.0, partner_id=None, context=None):
|
||||
categ = self.pool.get('crm.case.categ')
|
||||
address = self.address_get(cr, uid, ids)
|
||||
categ_ids = categ.search(cr, uid, [('object_id.model','=','crm.lead')])
|
||||
lead = self.pool.get('crm.lead')
|
||||
opportunity_ids = {}
|
||||
for partner in self.browse(cr, uid, ids, context=context):
|
||||
address = self.address_get(cr, uid, [partner.id])['default']
|
||||
if not partner_id:
|
||||
partner_id = partner.id
|
||||
opportunity_id = lead.create(cr, uid, {
|
||||
'name' : opportunity_summary,
|
||||
'planned_revenue' : planned_revenue,
|
||||
'probability' : probability,
|
||||
'partner_id' : partner_id,
|
||||
'partner_address_id' : address,
|
||||
'categ_id' : categ_ids and categ_ids[0] or '',
|
||||
'state' :'draft',
|
||||
'type': 'opportunity'
|
||||
})
|
||||
opportunity_ids[partner_id] = opportunity_id
|
||||
return opportunity_ids
|
||||
res_partner()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
Return-Path: <info@customer.com>
|
||||
X-Original-To: info@customer.com
|
||||
Delivered-To: sales@my.com
|
||||
Received: by mail.my.com (Postfix, from userid xxx)
|
||||
id 822ECBFB67; Mon, 24 Oct 2011 07:36:51 +0200 (CEST)
|
||||
X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.my.com
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED autolearn=ham
|
||||
version=3.3.1
|
||||
Received: from [192.168.1.146]
|
||||
(Authenticated sender: info@mail.customer.com)
|
||||
by mail.customer.com (Postfix) with ESMTPSA id 07A30BFAB4
|
||||
for <sales@my.com>; Mon, 24 Oct 2011 07:36:50 +0200 (CEST)
|
||||
Message-ID: <4EA4F95D.904@customer.com>
|
||||
Date: Mon, 24 Oct 2011 11:06:29 +0530
|
||||
From: Mr. John Right <info@customer.com>
|
||||
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8
|
||||
MIME-Version: 1.0
|
||||
To: sales@my.com
|
||||
Subject: Fournir votre devis avec le meilleur prix.
|
||||
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Bonjour l'équipe de vente,
|
||||
|
||||
Je veux acheter vos produits et services.
|
||||
|
||||
S'il vous plaît fournir votre cotation avec le meilleur prix.
|
||||
|
||||
Merci
|
|
@ -0,0 +1,53 @@
|
|||
-
|
||||
I cancel unqualified lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_cancel(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check cancelled lead.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in cancel state}:
|
||||
- state == "cancel"
|
||||
-
|
||||
I reset cancelled lead into unqualified lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_reset(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check unqualified lead after reset.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in draft state}:
|
||||
- state == "draft"
|
||||
-
|
||||
I put unqualified lead into pending.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_pending(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check status of pending lead.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in pending state}:
|
||||
- state == "pending"
|
||||
-
|
||||
I Escalate the Lead to Parent Team.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_escalate(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check lead escalate to Parent Team.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Escalate lead to parent team}:
|
||||
- section_id.name == "Sales Department"
|
||||
-
|
||||
I mark as lost the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_lost(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check opportunity after lost.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_itisatelesalescampaign0'))
|
||||
assert lead.state == 'done', "lead is not done state"
|
||||
assert lead.stage_id.id == ref('crm.stage_lead6'), 'Stage is not changed!'
|
||||
assert lead.probability == 0.0, 'Probability is wrong!'
|
|
@ -0,0 +1,56 @@
|
|||
-
|
||||
Customer interested in our product. so He send request by email to get more details.
|
||||
-
|
||||
Mail script will be fetched him request from mail server. so I process that mail after read EML file
|
||||
-
|
||||
!python {model: mail.thread}: |
|
||||
import addons
|
||||
request_file = open(addons.get_module_resource('crm','test', 'customer_request.eml'),'rb')
|
||||
request_message = request_file.read()
|
||||
self.message_process(cr, uid, 'crm.lead', request_message)
|
||||
-
|
||||
After getting the mail, I check details of new lead of that customer.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right <info@customer.com>')])
|
||||
assert lead_ids and len(lead_ids), "Lead is not created after getting request"
|
||||
lead = self.browse(cr, uid, lead_ids[0], context=context)
|
||||
assert not lead.partner_id, "Customer should be a new"
|
||||
assert lead.name == "Fournir votre devis avec le meilleur prix.", "Subject does not match"
|
||||
-
|
||||
I reply him request with welcome message.
|
||||
-
|
||||
!python {model: mail.compose.message}: |
|
||||
lead_ids = self.pool.get('crm.lead').search(cr, uid, [('email_from','=', 'Mr. John Right <info@customer.com>')])
|
||||
context.update({'active_model': 'crm.lead','active_id': lead_ids[0]})
|
||||
id = self.create(cr, uid, {'body_text': "Merci à l'intérêt pour notre produit.nous vous contacterons bientôt. Merci", 'email_from': 'sales@mycompany.com'}, context=context)
|
||||
try:
|
||||
self.send_mail(cr, uid, [id], context=context)
|
||||
except:
|
||||
pass
|
||||
-
|
||||
Now, I convert him into customer and put into regular customer list.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right <info@customer.com>')])
|
||||
self.convert_partner(cr, uid, lead_ids, context=context)
|
||||
-
|
||||
Now, I search customer in regular customer list.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
partner_ids = self.message_partner_by_email(cr, uid, 'Mr. John Right <info@customer.com>')
|
||||
assert partner_ids.get('partner_id'), "Customer is not found in regular customer list."
|
||||
-
|
||||
I convert one phonecall request as a customer and put into regular customer list.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.convert_partner(cr, uid, [ref('crm.crm_case_phone06')], context=context)
|
||||
-
|
||||
I check converted phonecall to partner.
|
||||
-
|
||||
!python {model: res.partner}: |
|
||||
partner_id = self.search(cr, uid, [('phonecall_ids', '=', ref('crm.crm_case_phone06'))])
|
||||
assert partner_id, "Customer is not found in regular customer list."
|
||||
data = self.browse(cr, uid, partner_id, context=context)[0]
|
||||
assert data.user_id.id == ref("base.user_root"), "User not assign properly"
|
||||
assert data.name == "Bad time", "User not assign properly"
|
|
@ -0,0 +1,90 @@
|
|||
-
|
||||
In order to test convert customer lead into opportunity,
|
||||
-
|
||||
I open customer lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_case_qrecorp0")])
|
||||
-
|
||||
I check lead state is "Open".
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_qrecorp0, string: Lead in open state}:
|
||||
- state == "open"
|
||||
-
|
||||
I convert lead into opportunity for exiting customer.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.convert_opportunity(cr, uid ,[ref("crm_case_qrecorp0")], ref("base.res_partner_agrolait"))
|
||||
-
|
||||
I check details of converted opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_qrecorp0'))
|
||||
assert lead.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
assert lead.partner_id.id == ref("base.res_partner_agrolait"), 'Partner missmatch!'
|
||||
assert lead.stage_id.id == ref("stage_lead1"), 'Stage of opportunity is incorrect!'
|
||||
-
|
||||
Now I begin communication and schedule a phone call with the customer.
|
||||
-
|
||||
!python {model: crm.opportunity2phonecall}: |
|
||||
import time
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref('crm_case_qrecorp0')]})
|
||||
call_id = self.create(cr, uid, {'date': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'name': "Bonjour M. Jean, Comment êtes-vous? J'ai obtenu votre demande. peut-on parler au sujet de ce pour quelques minutes?"}, context=context)
|
||||
self.action_schedule(cr, uid, [call_id], context=context)
|
||||
-
|
||||
I check that phonecall is scheduled for that opportunity.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
ids = self.search(cr, uid, [('opportunity_id', '=', ref('crm_case_qrecorp0'))])
|
||||
assert len(ids), 'phonecall is not scheduled'
|
||||
-
|
||||
Now I schedule Meeting with Customer.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.action_makeMeeting(cr, uid, [ref('crm_case_qrecorp0')])
|
||||
|
||||
-
|
||||
After communicated with customer, I put some notes with Contract details.
|
||||
-
|
||||
!python {model: crm.add.note}: |
|
||||
context.update({'active_model': 'crm.lead', 'active_id': ref('crm_case_qrecorp0')})
|
||||
note_id = self.create(cr, uid, {'body': "ces détails envoyés par le client sur le FAX pour la qualité"})
|
||||
self.action_add(cr, uid, [note_id], context=context)
|
||||
-
|
||||
Finally, I won this opportunity, so I close this opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_won(cr, uid, [ref("crm_case_qrecorp0")])
|
||||
-
|
||||
I check details of the opportunity After won the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_qrecorp0'))
|
||||
assert lead.state == 'done', 'Opportunity is not in done state!'
|
||||
assert lead.stage_id.name == 'Won', ' Stage of Opportunity is not win!'
|
||||
assert lead.probability == 100.0, 'probability revenue should not be 100.0!'
|
||||
-
|
||||
I convert mass lead into opportunity customer.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner.mass}: |
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref("crm_case_employee0"), ref("crm_case_electonicgoodsdealer0")], 'active_id': ref("crm_case_qrecorp0")})
|
||||
id = self.create(cr, uid, {'user_ids': [ref('base.user_root')], 'section_id': ref('crm.section_sales_department')}, context=context)
|
||||
self.mass_convert(cr, uid, [id], context=context)
|
||||
-
|
||||
Now I check First lead converted on opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opp = self.browse(cr, uid, ref('crm_case_employee0'))
|
||||
assert opp.name == "Need Info about Onsite Intervention", "Opportunity name not correct"
|
||||
assert opp.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
assert opp.partner_id.name == "Agrolait", 'Partner missmatch!'
|
||||
assert opp.stage_id.id == ref("stage_lead1"), 'Stage of probability is incorrect!'
|
||||
-
|
||||
Then check for Second lead converted on opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opp = self.browse(cr, uid, ref('crm_case_electonicgoodsdealer0'))
|
||||
assert opp.name == "Interest in Your New Product", "Opportunity name not correct"
|
||||
assert opp.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
assert opp.stage_id.id == ref("stage_lead1"), 'Stage of probability is incorrect!'
|
|
@ -0,0 +1,51 @@
|
|||
-
|
||||
I make direct opportunity for Customer.
|
||||
-
|
||||
!python {model: crm.partner2opportunity}: |
|
||||
context.update({'active_model': 'res.partner', 'active_ids': [ref("base.res_partner_9")]})
|
||||
res_id = self.create(cr, uid, {'name': "enquête pour l'achat de services"}, context=context)
|
||||
self.make_opportunity(cr, uid, [res_id], context=context)
|
||||
-
|
||||
I make another opportunity from phonecall for same customer.
|
||||
-
|
||||
!python {model: crm.phonecall2opportunity}: |
|
||||
context.update({'active_model': 'crm.phonecall', 'active_ids': [ref("crm.crm_case_phone06")]})
|
||||
res_id = self.create(cr, uid, {'name': "Quoi de prix de votre autre service?", 'partner_id': ref("base.res_partner_9")}, context=context)
|
||||
self.make_opportunity(cr, uid, [res_id], context=context)
|
||||
-
|
||||
Now I merge all opportunities of customer.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opportunity_ids = self.search(cr, uid, [('partner_id','=', ref("base.res_partner_9"))])
|
||||
self.merge_opportunity(cr, uid, opportunity_ids, context=context)
|
||||
-
|
||||
I check for merged opportunities for customer.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
merge_id = self.search(cr, uid, [('partner_id','=', ref("base.res_partner_9"))])
|
||||
assert merge_id, 'Fail to create Merge opportunity'
|
||||
merge_data = self.browse(cr, uid, merge_id)[0]
|
||||
assert merge_data.type == 'opportunity', 'Merged opportunity type not change!'
|
||||
assert merge_data.partner_id.id == ref("base.res_partner_9"), 'Partner missmatch!'
|
||||
-
|
||||
Now I schedule another phonecall to customer after merged.
|
||||
-
|
||||
!python {model: crm.phonecall2phonecall}: |
|
||||
context.update({'active_model': 'crm.phonecall', 'active_ids': [ref("crm.crm_case_phone06")]})
|
||||
res_id = self.create(cr, uid, {'name': "vos chances sont fusionnés en un seul"}, context=context)
|
||||
self.action_schedule(cr, uid, [res_id], context=context)
|
||||
-
|
||||
I schedule Meeting on this phonecall.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.action_make_meeting(cr, uid, [ref("crm.crm_case_phone06")])
|
||||
-
|
||||
I setting Phone call to Held (Done).
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.case_close(cr, uid, [ref("crm.crm_case_phone06")])
|
||||
-
|
||||
I check that the phone call is in 'Held' state.
|
||||
-
|
||||
!assert {model: crm.phonecall, id: crm.crm_case_phone06, string: Phone call Helded}:
|
||||
- state == "done"
|
|
@ -0,0 +1,16 @@
|
|||
-
|
||||
In order to test segmentation process which create specific partner categories criteria,
|
||||
-
|
||||
I start the process.
|
||||
-
|
||||
!python {model: crm.segmentation}: |
|
||||
self.process_start(cr, uid, [ref("crm_segmentation0")],context)
|
||||
#Todo: Need to check after segmentation started
|
||||
|
||||
-
|
||||
I create rule Segmentation line record for partner .
|
||||
-
|
||||
!python {model: crm.segmentation.line}: |
|
||||
id = self.create(cr, uid, {'name': "OpenERP partners",'expr_value': 25})
|
||||
self.test(cr, uid, [id],partner_id=0)
|
||||
#Todo: Need to test segmantation line record
|
|
@ -1,154 +0,0 @@
|
|||
-
|
||||
In order to test the CRM in OpenERP, I will do a customer qualification
|
||||
process that starts with a fist contact with a customer (a lead), which will
|
||||
be converted to a business opportunity and a partner.
|
||||
-
|
||||
I create a two new users "user_crm" and I assign the group "salesman".
|
||||
-
|
||||
!record {model: res.users, id: res_users_usercrm0}:
|
||||
company_id: base.main_company
|
||||
context_lang: en_US
|
||||
context_section_id: crm.section_sales_department
|
||||
groups_id:
|
||||
- base.group_sale_salesman
|
||||
login: user_crm
|
||||
name: user_crm
|
||||
password: user_crm
|
||||
|
||||
- |
|
||||
I start by creating a new lead "New Customer" and I provide an address to this
|
||||
new customer, as well as an email "info@mycustomer.com".
|
||||
-
|
||||
!record {model: crm.lead, id: crm_lead_newcustomer0}:
|
||||
email_from: info@mycustomer.com
|
||||
name: New Customer
|
||||
partner_name: Capegemini
|
||||
partner_id: base.res_partner_9
|
||||
phone: (855) 924-4364
|
||||
mobile: (333) 715-1450
|
||||
section_id: crm.section_sales_department
|
||||
referred: False
|
||||
- |
|
||||
I check that the lead is in 'draft' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_newcustomer0, string: Lead in Draft}:
|
||||
- state == "draft"
|
||||
-
|
||||
I open lead by click on "Open" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_lead_newcustomer0")])
|
||||
fields={
|
||||
'day_open': 0.0,
|
||||
'day_close': 0.0
|
||||
}
|
||||
self._compute_day(cr, uid, [ref("crm_lead_newcustomer0")], fields, context)
|
||||
- |
|
||||
I check that lead is now in 'open' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_newcustomer0, string: Lead in open state}:
|
||||
- state == "open"
|
||||
-
|
||||
I search id for case object.
|
||||
-
|
||||
!python {model: crm.case.categ}: |
|
||||
self._find_object_id(cr, uid, context)
|
||||
- |
|
||||
As the lead seems to be a real business opportunity, I will convert it to a
|
||||
partner
|
||||
and a business opportunity by clicking on the "Convert" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_lead_newcustomer0'))
|
||||
action = self.convert_opportunity(cr, uid, [ref("crm_lead_newcustomer0")], {'active_ids': [ref("crm_lead_newcustomer0")]})
|
||||
assert action['res_model'] == 'crm.lead2opportunity.partner'
|
||||
-
|
||||
|
|
||||
I select "create a new partner" option.
|
||||
-
|
||||
!record {model: crm.lead2opportunity.partner, id: crm_lead2opportunity_partner_create_0}:
|
||||
action: 'create'
|
||||
name: 'convert'
|
||||
-
|
||||
Then, Click on "Create Opportunity" button.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner}: |
|
||||
self.action_apply(cr, uid, [ref("crm_lead2opportunity_partner_create_0")], {'active_ids': [ref("crm_lead_newcustomer0")], 'active_id': ref("crm_lead_newcustomer0")})
|
||||
-
|
||||
|
|
||||
I select "Link to an existing partner" option.
|
||||
-
|
||||
!record {model: crm.lead2opportunity.partner, id: crm_lead2opportunity_partner_create_1}:
|
||||
action: 'exist'
|
||||
-
|
||||
Then, Click on "Create Opportunity" button.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner}: |
|
||||
self.action_apply(cr, uid, [ref("crm_lead2opportunity_partner_create_1")], {'active_ids': [ref("crm_lead_newcustomer0")], 'active_id': ref("crm_lead_newcustomer0")})
|
||||
-
|
||||
|
|
||||
I select "Do not link to a partner" option.
|
||||
-
|
||||
!record {model: crm.lead2opportunity.partner, id: crm_lead2opportunity_partner_create_2}:
|
||||
action: 'nothing'
|
||||
-
|
||||
Then, Click on "Create Opportunity" button.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner}: |
|
||||
self.action_apply(cr, uid, [ref("crm_lead2opportunity_partner_create_2")], {'active_ids': [ref("crm_lead_newcustomer0")], 'active_id': ref("crm_lead_newcustomer0")})
|
||||
- |
|
||||
In order to check the opportunity is created or not, I check type.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref("crm_lead_newcustomer0"))
|
||||
assert lead.type == 'opportunity'
|
||||
|
||||
-
|
||||
I create mass report of lead to opprtunity partner.
|
||||
-
|
||||
!record {model: crm.lead2opportunity.partner.mass, id: crm_lead2opportunity_partner_mass0}:
|
||||
user_ids:
|
||||
- base.user_root
|
||||
section_id: crm.section_sales_department
|
||||
-
|
||||
Then, execute that mass wizard.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner.mass}: |
|
||||
self.mass_convert(cr, uid, [ref("crm_lead2opportunity_partner_mass0")],{'active_ids': [ref("crm_lead_newcustomer0")], 'active_id': ref("crm_lead_newcustomer0")})
|
||||
-
|
||||
I close lead by click on "close" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_close(cr, uid, [ref("crm_lead_newcustomer0")])
|
||||
- |
|
||||
I check that lead is now in 'done' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_newcustomer0, string: Lead in done state}:
|
||||
- state == "done"
|
||||
-
|
||||
I cancel lead by click on "cancel" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_cancel(cr, uid, [ref("crm_lead_newcustomer0")])
|
||||
- |
|
||||
I check that lead is now in 'cancel' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_newcustomer0, string: Lead in cancel state}:
|
||||
- state == "cancel"
|
||||
|
||||
#-
|
||||
# |
|
||||
# yaml is also not working with smtp server and send new email.
|
||||
|
||||
- |
|
||||
I configure with smtp server.
|
||||
- |
|
||||
And I communicate with lead through send New mail to Lead using its email address from the user who is logged in.
|
||||
- |
|
||||
I check that communication history generated when send email to lead.
|
||||
- |
|
||||
Then, I add a cc which receive copy of future communication between partner and users by mail.
|
||||
|
||||
- |
|
||||
I Reply to last Email to lead with some document attached.and check that communication history generated or not.
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
-
|
||||
In order to do complete test the CRM in OpenERP,
|
||||
I will create new full configured record and carry test on it.
|
||||
- |
|
||||
I Start by creating "Test Sales Team" with No Unlink.
|
||||
I create a crm.case.section record.
|
||||
-
|
||||
!record {model: crm.case.section, id: crm_case_section_demosalesteam}:
|
||||
code: DEMO
|
||||
complete_name: Test Sales Team
|
||||
name: Test Sales Team
|
||||
allow_unlink: False
|
||||
member_ids:
|
||||
- base.user_admin
|
||||
stage_ids:
|
||||
- crm.stage_lead1
|
||||
- crm.stage_lead2
|
||||
- crm.stage_lead3
|
||||
- crm.stage_lead4
|
||||
- crm.stage_lead5
|
||||
- crm.stage_lead6
|
||||
working_hours: 0.0
|
||||
resource_calendar_id: resource.timesheet_group1
|
||||
parent_id: crm.section_sales_department
|
||||
-
|
||||
I assign segmentation.
|
||||
-
|
||||
!record {model: res.users, id: res_users_usercrm0}:
|
||||
context_section_id: crm_case_section_demosalesteam
|
||||
- |
|
||||
I create a new lead "Test Customer" and I provide an address to this
|
||||
demo customer and email "info@democustomer.com" and Also "Test Sales Team".
|
||||
-
|
||||
!record {model: crm.lead, id: crm_lead_democustomer}:
|
||||
email_from: info@democustomer.com
|
||||
name: Test Customer
|
||||
partner_name: NotSoTinySARL
|
||||
phone: (+32).81.81.37.00
|
||||
mobile: (+32).81.81.37.00
|
||||
section_id: crm_case_section_demosalesteam
|
||||
referred: False
|
||||
type: lead
|
||||
-
|
||||
I check that the lead is in 'draft' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_democustomer, string: Lead in Draft}:
|
||||
- state == "draft"
|
||||
-
|
||||
I create categories.
|
||||
-
|
||||
!record {model: crm.case.categ, id: crm_case_categ0}:
|
||||
name: crm_case_section_demosalesteam
|
||||
section_id: crm_case_section_demosalesteam
|
||||
-
|
||||
I assigning contact detail to the Lead "Test Customer" without address.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.onchange_partner_address_id(cr, uid, ref("crm_lead_democustomer"), None, email=False)
|
||||
|
||||
-
|
||||
I assigning contact detail to the Lead "Test Customer" with address.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.onchange_partner_address_id(cr, uid, ref("crm_lead_democustomer"), ref("base.res_partner_address_notsotinysarl0"), email=False)
|
||||
|
||||
-
|
||||
I selecting email "Opt-out" option for the "Test Customer" Lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.on_change_optout(cr, uid, ref("crm_lead_democustomer"), True)
|
||||
|
||||
-
|
||||
I change the Opt-out to Opt-in to show email receive preference.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.on_change_optin(cr, uid, ref("crm_lead_democustomer"), True)
|
||||
-
|
||||
I open lead by click on "Open" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_lead_democustomer")])
|
||||
-
|
||||
I check that lead "Test Customer" is now in 'open' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_democustomer, string: Lead in open state}:
|
||||
- state == "open"
|
||||
-
|
||||
I reset the lead "Test Customer".
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_reset(cr, uid, [ref("crm_lead_democustomer")])
|
||||
-
|
||||
I again opening lead by click on "Open" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_lead_democustomer")])
|
||||
-
|
||||
I setting stage "New" for the lead "Test Customer".
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.stage_next(cr, uid, [ref("crm_lead_democustomer")], context={'stage_type': 'lead'})
|
||||
-
|
||||
I try to Unlink the Lead "Test Customer" demo Lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
try:
|
||||
self.unlink(cr, uid, [ref("crm_lead_democustomer")])
|
||||
except:
|
||||
pass
|
||||
-
|
||||
I setting Lead "Test Customer" to Pending State.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_pending(cr, uid, [ref("crm_lead_democustomer")])
|
||||
-
|
||||
I check that lead "Test Customer" is now in 'Pending' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_lead_democustomer, string: Lead in Pending state}:
|
||||
- state == "pending"
|
||||
-
|
||||
I Escalate the Lead "Test Customer" Parent "Sales Team".
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_escalate(cr, uid, [ref("crm_lead_democustomer")])
|
||||
-
|
||||
I add Internal Note Saying Escalated Reason.
|
||||
-
|
||||
!record {model: crm.add.note, id: crm_add_note_0}:
|
||||
body: Sales Lead Has Been Escalated Due to Some Technical reason to the parent 'Sales
|
||||
Team'
|
||||
state: unchanged
|
||||
-
|
||||
I click a note button to attach the record.
|
||||
-
|
||||
!python {model: crm.add.note}: |
|
||||
context['active_model'] = "crm.lead"
|
||||
context['active_ids'] = [ref("crm_lead_democustomer")]
|
||||
self.action_add(cr, uid, [ref("crm_add_note_0")], context=context)
|
||||
|
||||
-
|
||||
I Copying this lead "Test Customer" to New Lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.copy(cr, uid, ref("crm_lead_democustomer"))
|
||||
-
|
||||
I checking the Lead Copied or Not.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
sid = self.search(cr, uid, [('name', '=', 'Test Customer'),('state', '=', 'draft')])
|
||||
if not sid:
|
||||
raise AssertionError("Lead is not copied Successfully")
|
|
@ -1,97 +0,0 @@
|
|||
- |
|
||||
I will test Meetings which may be customer meeting or phonecall meeting or
|
||||
internal Meeting.
|
||||
- |
|
||||
I start by creating a new Meeting.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_regardingpresentation0}:
|
||||
categ_id: crm.categ_meet2
|
||||
date: !eval time.strftime('%Y-%m-%d 16:04:00')
|
||||
date_deadline: !eval "(datetime.now() + timedelta(1)).strftime('%Y-%m-%d 00:04:00')"
|
||||
duration: 8.0
|
||||
email_from: info@balmerinc.be
|
||||
location: Ahmedabad
|
||||
name: Regarding Presentation
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
rrule_type: weekly
|
||||
section_id: crm.section_sales_department
|
||||
- |
|
||||
I check that the Meetings is in 'UnConfirmed' state.
|
||||
-
|
||||
!assert {model: crm.meeting, id: crm_meeting_regardingpresentation0}:
|
||||
- state == "draft"
|
||||
- |
|
||||
I can set reminder on meeting if I put reminder "40 minutes before" .
|
||||
- |
|
||||
For that, I first create alarm.
|
||||
-
|
||||
!record {model: res.alarm, id: res_alarm_minituesbefore0}:
|
||||
name: 40 minutes before
|
||||
trigger_duration: 40
|
||||
trigger_interval: minutes
|
||||
trigger_occurs: before
|
||||
trigger_related: start
|
||||
- |
|
||||
I will assign this reminder.
|
||||
|
||||
- !python {model: crm.meeting}: |
|
||||
self.write(cr, uid, [ref('crm_meeting_regardingpresentation0')], {'alarm_id': ref("res_alarm_minituesbefore0")})
|
||||
- |
|
||||
In order to check recurrence on meetings I will set Recurrency to Custom
|
||||
and I set the fields so that the meeting will occur weekly on Monday and Friday 10 times.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.write(cr, uid, [ref("crm_meeting_regardingpresentation0")], {'fr': 1, 'mo': 1, 'th': 1, 'tu': 1, 'we':1, 'count':10, 'interval': 1, 'rrule_type': 'weekly', 'recurrency' : True})
|
||||
|
||||
- |
|
||||
I can see from the calendar view that the meeting is scheduled on Monday and Friday
|
||||
for 10 times.
|
||||
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.fields_view_get(cr, uid, False, 'calendar', context)
|
||||
- |
|
||||
I will search for one of the recurrent event and count the number of meeting.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
import time
|
||||
from datetime import datetime, date, timedelta
|
||||
ids = self.search(cr, uid, [('date', '>=', time.strftime('%Y-%m-%d 00:00:00')), ('date', '<=', (datetime.now()+timedelta(31)).strftime('%Y-%m-%d 00:00:00')), ('name', '=', 'Regarding Presentation')], context={'virtual_id': True})
|
||||
assert len(ids) == 10
|
||||
|
||||
- |
|
||||
If I want to edit meetings information for all occurrence I click on "Edit All" button.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.write(cr, uid, [ref('crm_meeting_regardingpresentation0')], {'edit_all':'True'},context)
|
||||
- |
|
||||
I can see that new meeting form is opened with same value.
|
||||
I change some data for meeting and save it.
|
||||
I can see from meeting's calendar view that all meeting occurrences are changed accordingly.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm.crm_meeting_regardingpresentation0}:
|
||||
alarm_id: base_calendar.alarm9
|
||||
rrule_type: weekly
|
||||
|
||||
- |
|
||||
In order to invite people for this meetings, I click on "Invite People" button
|
||||
I can invite internal user.
|
||||
-
|
||||
!record {model: base_calendar.invite.attendee, id: base_calendar_invite_attendee_0}:
|
||||
type: internal
|
||||
send_mail: False
|
||||
partner_id: base.res_partner_9
|
||||
user_ids:
|
||||
- base.user_demo
|
||||
-
|
||||
I click on "Invite" button of "Invite attendee" wizard.
|
||||
-
|
||||
!python {model: base_calendar.invite.attendee}: |
|
||||
self.do_invite(cr, uid, [ref('base_calendar_invite_attendee_0')], {'active_id': ref('crm_meeting_regardingpresentation0'), 'model' : 'crm.meeting', 'attendee_field':'attendee_ids'})
|
||||
|
||||
- |
|
||||
After direct/indirect confirmation for meetings I can confirm meeting.
|
||||
-
|
||||
!python {model: crm.meeting}: |
|
||||
self.case_open(cr, uid, [ref('crm_meeting_regardingpresentation0')])
|
|
@ -1,113 +0,0 @@
|
|||
- |
|
||||
I start by creating a new Opportunity. And I select partner for opportunity.
|
||||
I can see that after selecting partner his contact and email is automatically filled.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_opportunity_abcfuelcounits0}:
|
||||
email_from: info@balmerinc.be
|
||||
name: 'ABC FUEL CO 829264 - 10002 units'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
probability: 1.0
|
||||
stage_id: crm.stage_lead1
|
||||
categ_id: crm.categ_oppor2
|
||||
section_id: crm.section_sales_department
|
||||
- |
|
||||
I check that the opportunity is in 'New' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_opportunity_abcfuelcounits0}:
|
||||
- state == "draft"
|
||||
|
||||
- |
|
||||
I check that phonecall record is created for that opportunity.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
phone_obj = self.pool.get('crm.phonecall')
|
||||
- |
|
||||
I schedule Meeting on this current opportunity by clicking on "schedule
|
||||
Meeting".
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.action_makeMeeting(cr, uid, [ref("crm_opportunity_abcfuelcounits0")])
|
||||
|
||||
- |
|
||||
I can see that Meeting's calendar view is shown.
|
||||
then I click on the date on which I want to schedule meeting.
|
||||
I fill proper data for that meeting and save it.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_abcfuelcounits0}:
|
||||
date: !eval time.strftime('%Y-%m-%d 00:00:00')
|
||||
date_deadline: !eval time.strftime('%Y-%m-%d 08:00:00')
|
||||
duration: 8.0
|
||||
email_from: info@balmerinc.be
|
||||
name: 'ABC FUEL CO 829264 - 10002 units'
|
||||
opportunity_id: 'crm_opportunity_abcfuelcounits0'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
section_id: crm.section_sales_department
|
||||
state: open
|
||||
- |
|
||||
In order to schedule a phonecall to the partner
|
||||
I click on "schedule call" button and select planned date for the call.
|
||||
-
|
||||
!record {model: crm.opportunity2phonecall, id: crm_opportunity2phonecall_abcfuelcounits0}:
|
||||
date: !eval "(datetime.now() + timedelta(1)).strftime('%Y-%m-%d 11:15:00')"
|
||||
name: 'ABC FUEL CO 829264 - 10002 units'
|
||||
section_id: crm.section_sales_department
|
||||
user_id: base.user_demo
|
||||
categ_id: crm.categ_phone1
|
||||
- |
|
||||
schedule phonecall by opportunity2phoncall wizard.
|
||||
-
|
||||
!python {model: crm.opportunity2phonecall}: |
|
||||
self.action_apply(cr, uid, [ref('crm_opportunity2phonecall_abcfuelcounits0')], {'active_ids': [ref("crm_opportunity_abcfuelcounits0")]})
|
||||
- |
|
||||
I check that phonecall record is created for that opportunity.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
phone_obj = self.pool.get('crm.phonecall')
|
||||
ids = phone_obj.search(cr, uid, [('name', '=', 'ABC FUEL CO 829264 - 10002 units')])
|
||||
assert len(ids)
|
||||
- |
|
||||
I can see phonecall record after click on "Schedule call" wizard.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_phonecall_abcfuelcounits0}:
|
||||
date: !eval "(datetime.now() + timedelta(1)).strftime('%Y-%m-%d 11:15:00')"
|
||||
duration: 3.0
|
||||
name: 'ABC FUEL CO 829264 - 10002 units'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
section_id: crm.section_sales_department
|
||||
- |
|
||||
I Merge the opportunities.
|
||||
-
|
||||
for that create two opportunities first opportunity 'Test FUEL CO'.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_opportunity_1}:
|
||||
email_from: info@balmerinc.be
|
||||
name: 'Test FUEL CO 829264 - 10002 units'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
probability: 1.0
|
||||
stage_id: crm.stage_lead1
|
||||
categ_id: crm.categ_oppor2
|
||||
section_id: crm.section_sales_department
|
||||
-
|
||||
I create the opportunity 'FUEL CO'.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_opportunity_2}:
|
||||
email_from: info@balmerinc.be
|
||||
name: 'FUEL CO 829264 - 10002 units'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
probability: 1.0
|
||||
stage_id: crm.stage_lead1
|
||||
categ_id: crm.categ_oppor2
|
||||
section_id: crm.section_sales_department
|
||||
- |
|
||||
I Merge two Opportunities.
|
||||
-
|
||||
!python {model: crm.merge.opportunity}: |
|
||||
op_list = [ref('crm_opportunity_1'),ref('crm_opportunity_2')]
|
||||
op_ids=self.pool.get('crm.lead').browse(cr,uid,op_list)
|
||||
lead_ids = [ref('crm_lead_newcustomer0')]
|
||||
self.merge(cr, uid, op_ids, {'lead_ids': lead_ids})
|
|
@ -1,45 +0,0 @@
|
|||
- |
|
||||
I start by creating a new Opportunity. And I select partner for opportunity.
|
||||
I can see that after selecting partner his contact and email is automatically filled.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_opportunity_demotestopportunity}:
|
||||
email_from: info@balmerinc.be
|
||||
name: 'Demo Test Opportunity'
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
probability: 1.0
|
||||
categ_id: crm.categ_oppor2
|
||||
section_id: crm.section_sales_department
|
||||
type: opportunity
|
||||
-
|
||||
I check that the opportunity is in 'New' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_opportunity_demotestopportunity, string: Opportunity in Draft}:
|
||||
- state == "draft"
|
||||
-
|
||||
I open opportunity by click on "Open" button.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_opportunity_demotestopportunity")])
|
||||
-
|
||||
I change partner of the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.onchange_partner_id(cr, uid, [ref("crm_opportunity_demotestopportunity")], ref("base.res_partner_agrolait"))
|
||||
|
||||
-
|
||||
I change Contact Detail of the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.onchange_partner_address_id(cr, uid,[ref("crm_opportunity_demotestopportunity")], ref("base.res_partner_address_8invoice"))
|
||||
|
||||
-
|
||||
I change Opportunity to Won State.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_won(cr, uid, [ref("crm_opportunity_demotestopportunity")])
|
||||
-
|
||||
I check that the opportunity is in 'Done' state.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm_opportunity_demotestopportunity, string: Opportunity is Won}:
|
||||
- state == "done"
|
|
@ -1,25 +0,0 @@
|
|||
- |
|
||||
I start by creating a new opportunity from partner.
|
||||
-
|
||||
!record {model: crm.partner2opportunity, id: crm_partner2opportunity_id_0}:
|
||||
name: test
|
||||
planned_revenue: 0.0
|
||||
partner_id: base.res_partner_9
|
||||
probability: 0.0
|
||||
-
|
||||
I click on "Create Opportunity" button of this wizard.
|
||||
-
|
||||
!python {model: crm.partner2opportunity}: |
|
||||
fields = {
|
||||
'name': 'test',
|
||||
'planned_revenue': '0.0',
|
||||
'partner_id': ref('base.res_partner_9'),
|
||||
'probability': '0.0'
|
||||
}
|
||||
self.default_get(cr, uid, fields, {"active_ids": [ref("crm_partner2opportunity_id_0")]})
|
||||
- |
|
||||
In order to check the opportunity is created or not, I check type.
|
||||
-
|
||||
!python {model: crm.partner2opportunity}: |
|
||||
opportunity = self.make_opportunity(cr, uid, [ref("crm_partner2opportunity_id_0")], {"active_ids": [ref("crm_partner2opportunity_id_0")]})
|
||||
assert True
|
|
@ -1,116 +0,0 @@
|
|||
- |
|
||||
I start by creating a new phonecall.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_phonecall_interviewcall0}:
|
||||
date: !eval time.strftime('%Y-%m-%d 08:00:00')
|
||||
name: Interview call
|
||||
duration: 2.0
|
||||
section_id: crm.section_sales_department
|
||||
-
|
||||
I select partner by click on "Create a Partner" button.
|
||||
-
|
||||
!record {model: crm.phonecall2partner, id: crm_phonecall2partner_1}:
|
||||
action: exist
|
||||
partner_id: base.res_partner_9
|
||||
|
||||
-
|
||||
I click on "Continue" button of this wizard and make partner.
|
||||
-
|
||||
!python {model: crm.phonecall2partner}: |
|
||||
|
||||
self._select_partner(cr, uid,{"active_ids": [ref("crm_phonecall_interviewcall0")]})
|
||||
self.open_create_partner(cr, uid, [ref("crm_phonecall2partner_1")], {"active_ids": [ref("crm_phonecall_interviewcall0")]})
|
||||
self.make_partner(cr, uid, [ref("crm_phonecall2partner_1")], {"active_ids": [ref("crm_phonecall_interviewcall0")]})
|
||||
|
||||
- |
|
||||
As the success of phonecall seems to be a real business opportunity, I will convert
|
||||
it to opportunity by clicking on the "Convert to Opportunity" button.
|
||||
-
|
||||
!record {model: crm.phonecall2opportunity, id: crm_phonecall2opportunity_interviewcall0}:
|
||||
name: Interview call
|
||||
partner_id: base.res_partner_9
|
||||
planned_revenue: 0.0
|
||||
probability: 0.0
|
||||
- |
|
||||
I can see that a business opportunity is now assigned to this phonecall
|
||||
-
|
||||
!assert {model: crm.phonecall, id: crm_phonecall_interviewcall0}:
|
||||
- opportunity_id != False
|
||||
-
|
||||
I click on "Convert" button of this wizard.
|
||||
-
|
||||
!python {model: crm.phonecall2opportunity}: |
|
||||
self.action_apply(cr, uid, [ref("crm_phonecall2opportunity_interviewcall0")], {"active_id": ref("crm_phonecall_interviewcall0")})
|
||||
- |
|
||||
And I check that the phonecall and the newly created business opportunity is linked
|
||||
to same partner.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
obj_phonecall = self.browse(cr, uid, ref('crm_phonecall_interviewcall0'))
|
||||
ids = self.pool.get('crm.lead').search(cr, uid, [('name', '=', obj_phonecall.opportunity_id.name)])
|
||||
obj_opp = self.pool.get('crm.lead').browse(cr, uid, ids)[0]
|
||||
assert obj_phonecall.partner_id == obj_opp.partner_id
|
||||
- |
|
||||
I schedule Meeting on this current phonecall by clicking on "schedule
|
||||
Meeting".
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.action_make_meeting(cr, uid, [ref('crm_phonecall_interviewcall0')])
|
||||
|
||||
- |
|
||||
I can see that Meeting's calendar view is shown.
|
||||
then I click on the date on which I want schedule meeting.
|
||||
I fill proper data for that meeting and save it.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_interviewcall0}:
|
||||
alarm_id: base_calendar.alarm3
|
||||
date: !eval "'%s-%s-%s 09:00:00' %(datetime.now().year,datetime.now().month,datetime.now().day)"
|
||||
date_deadline: !eval "'%s-%s-%s 17:00:00' %(datetime.now().year,datetime.now().month,datetime.now().day)"
|
||||
duration: 8.0
|
||||
email_from: info@balmerinc.be
|
||||
name: Interview call
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
phonecall_id: 'crm_phonecall_interviewcall0'
|
||||
state: open
|
||||
|
||||
- |
|
||||
In order to schedule other phonecall to the partner
|
||||
I click on "schedule other call" button. and plan for other call
|
||||
I can see that it will open other phonecall view with some data same as current
|
||||
phonecall.
|
||||
-
|
||||
!record {model: crm.phonecall2phonecall, id: crm_phonecall2phonecall_interviewcall0}:
|
||||
date: !eval "'%s-%s-%s 19:49:00' %(datetime.now().year,datetime.now().month,datetime.now().day)"
|
||||
name: Interview call
|
||||
section_id: crm.section_sales_department
|
||||
user_id: base.user_root
|
||||
action: schedule
|
||||
categ_id: crm.categ_phone1
|
||||
-
|
||||
I click on "schedule other call" button. and plan for other call.
|
||||
-
|
||||
!record {model: crm.phonecall2phonecall, id: crm_phonecall2phonecall_interviewcall1}:
|
||||
date: !eval "'%s-%s-%s 19:49:00' %(datetime.now().year,datetime.now().month,datetime.now().day)"
|
||||
name: Interview call
|
||||
section_id: crm.section_sales_department
|
||||
user_id: base.user_root
|
||||
action: log
|
||||
categ_id: crm.categ_phone1
|
||||
- |
|
||||
I click on "Schedule" button of this wizard.
|
||||
-
|
||||
!python {model: crm.phonecall2phonecall}: |
|
||||
fields = {
|
||||
'name': 'Interview call',
|
||||
'section_id': ref('crm.section_sales_department'),
|
||||
'user_id': ref('base.user_root'),
|
||||
'categ_id': ref('crm.categ_phone1')
|
||||
}
|
||||
self.default_get(cr, uid, fields,{'active_id': ref('crm_phonecall_interviewcall0')})
|
||||
self.action_apply(cr, uid, [ref('crm_phonecall2phonecall_interviewcall0')], {'active_id': ref('crm_phonecall_interviewcall0')})
|
||||
- |
|
||||
I click on "Schedule" button of this wizard with log option.
|
||||
-
|
||||
!python {model: crm.phonecall2phonecall}: |
|
||||
self.action_apply(cr, uid, [ref('crm_phonecall2phonecall_interviewcall1')], {'active_id': ref('crm_phonecall_interviewcall0')})
|
|
@ -1,26 +0,0 @@
|
|||
- |
|
||||
I start by creating a new phonecall.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_phonecall_dummycall}:
|
||||
date: !eval time.strftime('%Y-%m-%d 08:00:00')
|
||||
name: Dummy call
|
||||
duration: 0.0
|
||||
section_id: crm.section_sales_department
|
||||
partner_id: base.res_partner_agrolait
|
||||
state: open
|
||||
-
|
||||
I change Contact Detail of the Partner.
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.onchange_partner_address_id(cr, uid,[ref("crm_phonecall_dummycall")], ref("base.res_partner_address_8invoice"))
|
||||
|
||||
-
|
||||
I setting Phone call to Held (Done).
|
||||
-
|
||||
!python {model: crm.phonecall}: |
|
||||
self.case_close(cr, uid, [ref("crm_phonecall_dummycall")])
|
||||
-
|
||||
I check that the hone call is in 'Held' state.
|
||||
-
|
||||
!assert {model: crm.phonecall, id: crm_phonecall_dummycall, string: Phone call Helded}:
|
||||
- state == "done"
|
|
@ -1,106 +0,0 @@
|
|||
-
|
||||
In order to test recurrent meetings in OpenERP, I create meetings with different recurrency.
|
||||
-
|
||||
I create a customer meeting record with daily recurrency.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_pricelistdiscussion0}:
|
||||
categ_id: crm.categ_meet1
|
||||
count: 0.0
|
||||
date: '2011-01-05 00:00:00'
|
||||
date_deadline: '2011-01-05 01:00:00'
|
||||
day: 0.0
|
||||
duration: 1.0
|
||||
end_date: '2011-01-12'
|
||||
end_type: end_date
|
||||
name: Pricelist Discussion
|
||||
recurrency: true
|
||||
recurrent_uid: 0.0
|
||||
rrule: FREQ=DAILY;INTERVAL=1;UNTIL=20110112T235959Z
|
||||
rrule_type: daily
|
||||
sequence: 0.0
|
||||
-
|
||||
I create another meeting record with weekly recurrency.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_changesindesigning0}:
|
||||
categ_id: crm.categ_meet2
|
||||
count: 15
|
||||
date: '2011-01-22 11:05:05'
|
||||
date_deadline: '2011-01-22 16:05:05'
|
||||
day: 0.0
|
||||
duration: 5.0
|
||||
email_from: info@opensides.be
|
||||
end_type: count
|
||||
fr: true
|
||||
mo: true
|
||||
name: Changes in Designing
|
||||
partner_address_id: base.res_partner_address_1
|
||||
partner_id: base.res_partner_9
|
||||
recurrency: true
|
||||
recurrent_uid: 0.0
|
||||
rrule: FREQ=WEEKLY;BYDAY=FR,TU,TH,WE,MO;INTERVAL=1;COUNT=15
|
||||
rrule_type: weekly
|
||||
section_id: crm.section_sales_department
|
||||
sequence: 0.0
|
||||
th: true
|
||||
tu: true
|
||||
user_id: base.user_demo
|
||||
we: true
|
||||
-
|
||||
I create a meeting record with monthly recurrency.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_reviewneeds0}:
|
||||
categ_id: crm.categ_meet3
|
||||
count: 0.0
|
||||
date: '2011-01-20 10:02:02'
|
||||
date_deadline: '2011-01-20 16:02:02'
|
||||
day: 15
|
||||
duration: 6.0
|
||||
end_date: '2011-05-31'
|
||||
end_type: end_date
|
||||
name: Review needs
|
||||
partner_address_id: base.res_partner_address_15
|
||||
partner_id: base.res_partner_11
|
||||
recurrency: true
|
||||
recurrent_uid: 0.0
|
||||
rrule: FREQ=MONTHLY;INTERVAL=1;UNTIL=20110531T235959Z;BYMONTHDAY=15
|
||||
rrule_type: monthly
|
||||
section_id: crm.section_sales_department
|
||||
sequence: 0.0
|
||||
user_id: base.user_demo
|
||||
-
|
||||
I create a record for daily scrum meeting.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_scrummeeting0}:
|
||||
categ_id: crm.categ_meet2
|
||||
count: 0.0
|
||||
date: '2011-01-06 00:00:00'
|
||||
date_deadline: '2011-01-06 01:00:00'
|
||||
day: 0.0
|
||||
duration: 1.0
|
||||
name: Scrum meeting
|
||||
recurrency: true
|
||||
recurrent_uid: 0.0
|
||||
rrule: FREQ=DAILY;INTERVAL=1
|
||||
rrule_type: daily
|
||||
sequence: 0.0
|
||||
-
|
||||
I create a meeting record for yearly recurrency.
|
||||
-
|
||||
!record {model: crm.meeting, id: crm_meeting_updatethedata0}:
|
||||
categ_id: crm.categ_meet2
|
||||
count: 0.0
|
||||
date: '2011-01-18 13:12:49'
|
||||
date_deadline: '2011-01-19 02:30:49'
|
||||
day: 0.0
|
||||
duration: 13.300000000000001
|
||||
end_date: '2015-01-06'
|
||||
end_type: end_date
|
||||
name: Update the data
|
||||
partner_address_id: base.res_partner_address_7
|
||||
partner_id: base.res_partner_4
|
||||
recurrency: true
|
||||
recurrent_uid: 0.0
|
||||
rrule: FREQ=YEARLY;INTERVAL=1;UNTIL=20150106T235959Z
|
||||
rrule_type: yearly
|
||||
section_id: crm.section_sales_department
|
||||
sequence: 0.0
|
|
@ -1,38 +0,0 @@
|
|||
- |
|
||||
I will test segmentation which create specific partner categories criteria.
|
||||
-
|
||||
I create a new segmentation record.
|
||||
-
|
||||
!record {model: crm.segmentation, id: crm_segmentation_id_0}:
|
||||
categ_id: base.res_partner_category_5
|
||||
exclusif: true
|
||||
name: segment
|
||||
som_interval: 0.0
|
||||
sales_purchase_active : True
|
||||
-
|
||||
I start the process.
|
||||
-
|
||||
!python {model: crm.segmentation}: |
|
||||
self.process_start(cr, uid, [ref("crm_segmentation_id_0")],context)
|
||||
-
|
||||
I continue the segmentation process.
|
||||
-
|
||||
!python {model: crm.segmentation}: |
|
||||
context.update({'start': True})
|
||||
self.process_continue(cr, uid, [ref("crm_segmentation_id_0")], context)
|
||||
-
|
||||
I create the segmentation line.
|
||||
-
|
||||
!record {model: crm.segmentation.line, id: crm_segmentation_line_id_0}:
|
||||
expr_name: sale
|
||||
expr_operator: '>'
|
||||
expr_value: 1000.0
|
||||
name: Rule1
|
||||
operator: or
|
||||
segmentation_id: crm_segmentation_id_0
|
||||
|
||||
-
|
||||
I check the Segmentation line record.
|
||||
-
|
||||
!python {model: crm.segmentation.line}: |
|
||||
self.test(cr, uid, [ref("crm_segmentation_line_id_0")],partner_id=0)
|
|
@ -1,96 +0,0 @@
|
|||
-
|
||||
In order to test the changes on stage of a lead or an opportunity with OpenERP,
|
||||
I create some leads and test the stage changes.
|
||||
-
|
||||
I want to change the probability to 0.0 when the opportunity is marked as lost.
|
||||
So I set its Change probability automatically true.
|
||||
-
|
||||
!record {model: crm.case.stage, id: crm.stage_lead6}:
|
||||
name: Lost
|
||||
on_change: true
|
||||
probability: 0.0
|
||||
section_ids:
|
||||
- crm.section_sales_department
|
||||
sequence: 0
|
||||
-
|
||||
I create a lead 'Test Lead1'.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_lead_openerppresentation0}:
|
||||
categ_id: crm.categ_oppor4
|
||||
day_close: 0.0
|
||||
day_open: 0.0
|
||||
name: Test Lead1
|
||||
planned_revenue: 0.0
|
||||
probability: 10.0
|
||||
section_id: crm.section_sales_department
|
||||
-
|
||||
I open the lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref('crm_lead_openerppresentation0')])
|
||||
-
|
||||
I assigning stage.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.onchange_stage_id(cr, uid, [ref('crm_lead_openerppresentation0')], [], context)
|
||||
-
|
||||
I assigning percent.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.stage_find_percent(cr, uid, 10.0, [])
|
||||
-
|
||||
I find that this lead can be converted to opportunity.
|
||||
-
|
||||
!record {model: crm.lead2opportunity.partner, id: crm_lead2opportunity_partner0}:
|
||||
action: 'create'
|
||||
name: 'convert'
|
||||
-
|
||||
So I convert the lead to opportunity.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner}: |
|
||||
self.action_apply(cr, uid, [ref('crm_lead2opportunity_partner0')], context={'active_ids': [ref('crm_lead_openerppresentation0')]})
|
||||
-
|
||||
I check that lead is now converted to opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_lead_openerppresentation0'))
|
||||
assert lead.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
-
|
||||
I mark this opportunity as lost.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_lost(cr, uid, [ref('crm_lead_openerppresentation0')])
|
||||
-
|
||||
I check whether the probability is set according to stage change or not.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opportunity = self.browse(cr, uid, ref('crm_lead_openerppresentation0'))
|
||||
assert opportunity.stage_id.id == ref('crm.stage_lead6'), 'Stage is not changed!'
|
||||
assert opportunity.probability == 0.0, 'Probability is wrong!'
|
||||
-
|
||||
I create one more opportunity.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_lead_test2}:
|
||||
name: Partner Demo
|
||||
type: opportunity
|
||||
categ_id: crm.categ_oppor3
|
||||
planned_revenue: 50000.0
|
||||
probability: 100.0
|
||||
section_id: crm.section_sales_department
|
||||
-
|
||||
I open this opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref('crm_lead_test2')])
|
||||
-
|
||||
I mark this opportunity as won.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_won(cr, uid, [ref('crm_lead_test2')])
|
||||
-
|
||||
I check whether the stage is changed to 'Won' and probability is 100.0 or not.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opportunity = self.browse(cr, uid, ref('crm_lead_test2'))
|
||||
assert opportunity.stage_id.id == ref('crm.stage_lead5'), 'Stage is not changed!'
|
||||
assert opportunity.probability == 100.0, 'Probability is wrong!'
|
|
@ -0,0 +1,29 @@
|
|||
-
|
||||
I create lead record to call of partner onchange, stage onchange and Mailing opt-in onchange method.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_case_shelvehouse}:
|
||||
name: 'Need more info about your pc2'
|
||||
partner_id: base.res_partner_theshelvehouse0
|
||||
type: opportunity
|
||||
stage_id: crm.stage_lead1
|
||||
state: draft
|
||||
optin: True
|
||||
-
|
||||
I create lead record to call Mailing opt-out onchange method.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_case_mediapoleunits0}:
|
||||
name: 'Need 20 Days of Consultancy'
|
||||
type: opportunity
|
||||
state: draft
|
||||
optout: True
|
||||
-
|
||||
I create phonecall record to call partner onchange method.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_case_phone05}:
|
||||
name: 'Bad time'
|
||||
partner_id: base.res_partner_5
|
||||
-
|
||||
I setting next stage "New" for the lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.stage_next(cr, uid, [ref("crm_case_qrecorp0")], context={'stage_type': 'lead'})
|
|
@ -0,0 +1,5 @@
|
|||
-
|
||||
I Unlink the Lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.unlink(cr, uid, [ref("crm_case_qrecorp0")])
|
|
@ -0,0 +1,5 @@
|
|||
-
|
||||
I make duplicate the Lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.copy(cr, uid, ref("crm_case_qrecorp0"))
|
|
@ -24,11 +24,11 @@ import crm_add_note
|
|||
|
||||
import crm_lead_to_partner
|
||||
import crm_lead_to_opportunity
|
||||
import crm_opportunity_to_phonecall
|
||||
import crm_phonecall_to_phonecall
|
||||
import crm_opportunity_to_phonecall
|
||||
import crm_phonecall_to_partner
|
||||
import crm_phonecall_to_opportunity
|
||||
import crm_partner_to_opportunity
|
||||
import crm_phonecall_to_opportunity
|
||||
|
||||
import crm_merge_opportunities
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
email = False
|
||||
for lead in lead_obj.browse(cr, uid, opportunities, context=context):
|
||||
partner_id = lead.partner_id and lead.partner_id.id or False
|
||||
|
||||
#TOFIX: use mail.mail_message.to_mail
|
||||
email = re.findall(r'([^ ,<@]+@[^> ,]+)', lead.email_from or '')
|
||||
email = map(lambda x: "'" + x + "'", email)
|
||||
|
||||
|
@ -93,139 +95,51 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
def view_init(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function checks for precondition before wizard executes
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
|
||||
for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context):
|
||||
if lead.state in ['done', 'cancel']:
|
||||
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled Leads can not be converted into Opportunity"))
|
||||
return False
|
||||
|
||||
def _convert(self, cr, uid, ids, lead, partner_id, stage_ids, context=None):
|
||||
leads = self.pool.get('crm.lead')
|
||||
address_id = False
|
||||
if partner_id:
|
||||
address_id = self.pool.get('res.partner.address').search(cr, uid,
|
||||
[('partner_id', '=', partner_id)],
|
||||
order='create_date desc',
|
||||
limit=1)
|
||||
vals = {
|
||||
'planned_revenue': lead.planned_revenue,
|
||||
'probability': lead.probability,
|
||||
'name': lead.name,
|
||||
'partner_id': partner_id,
|
||||
'user_id': (lead.user_id and lead.user_id.id),
|
||||
'type': 'opportunity',
|
||||
'stage_id': stage_ids and stage_ids[0] or False,
|
||||
'date_action': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
}
|
||||
if partner_id and address_id:
|
||||
vals['partner_address_id'] = address_id[0]
|
||||
else:
|
||||
vals['partner_address_id'] = False
|
||||
def _convert_opportunity(self, cr, uid, ids, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
lead = self.pool.get('crm.lead')
|
||||
partner_id = self._create_partner(cr, uid, ids, context=context)
|
||||
lead_ids = vals.get('lead_ids', [])
|
||||
user_ids = vals.get('user_ids', False)
|
||||
team_id = vals.get('section_id', False)
|
||||
return lead.convert_opportunity(cr, uid, lead_ids, partner_id, user_ids, team_id, context=context)
|
||||
|
||||
lead.write(vals, context=context)
|
||||
text = _('Converted to opportunity')
|
||||
leads.message_append(cr, uid, [lead], text, body_text=text, context=context)
|
||||
if lead.partner_id:
|
||||
msg_ids = [ x.id for x in lead.message_ids]
|
||||
self.pool.get('mail.message').write(cr, uid, msg_ids, {
|
||||
'partner_id': lead.partner_id.id
|
||||
}, context=context)
|
||||
leads.log(cr, uid, lead.id, _("Lead '%s' has been converted to an opportunity.") % lead.name)
|
||||
|
||||
def send_mail_to_salesman(self, cr, uid, lead):
|
||||
email_to = lead.user_id and lead.user_id.user_email
|
||||
if not email_to:
|
||||
return False
|
||||
message_pool = self.pool.get('mail.message')
|
||||
email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.user_email or email_to
|
||||
partner = lead.partner_id and lead.partner_id.name or lead.partner_name
|
||||
subject = "lead %s converted into opportunity" % lead.name
|
||||
body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description)
|
||||
return message_pool.schedule_with_attach(cr, uid, email_from, [email_to], subject, body)
|
||||
def _merge_opportunity(self, cr, uid, ids, opportunity_ids, action='merge', context=None):
|
||||
#TOFIX: is it usefully ?
|
||||
if context is None:
|
||||
context = {}
|
||||
merge_opportunity = self.pool.get('crm.merge.opportunity')
|
||||
res = False
|
||||
#If we convert in mass, don't merge if there is no other opportunity but no warning
|
||||
if action == 'merge' and (len(opportunity_ids) > 1 or not context.get('mass_convert') ):
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, [opportunity_ids[0].id])]}, context=context)
|
||||
context.update({'lead_ids' : record_id, "convert" : True})
|
||||
res = merge_opportunity.merge(cr, uid, data.opportunity_ids, context=context)
|
||||
return res
|
||||
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This converts lead to opportunity and opens Opportunity view
|
||||
@param ids: ids of the leads to convert to opportunities
|
||||
|
||||
@return : View dictionary opening the Opportunity form view
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
record_id = context and context.get('active_ids') or False
|
||||
if not record_id:
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
leads = self.pool.get('crm.lead')
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
# Get Opportunity views
|
||||
result = models_data._get_id(
|
||||
cr, uid, 'crm', 'view_crm_case_opportunities_filter')
|
||||
opportunity_view_search = models_data.browse(
|
||||
cr, uid, result, context=context).res_id
|
||||
opportunity_view_form = models_data._get_id(
|
||||
cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
opportunity_view_tree = models_data._get_id(
|
||||
cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
if opportunity_view_form:
|
||||
opportunity_view_form = models_data.browse(
|
||||
cr, uid, opportunity_view_form, context=context).res_id
|
||||
if opportunity_view_tree:
|
||||
opportunity_view_tree = models_data.browse(
|
||||
cr, uid, opportunity_view_tree, context=context).res_id
|
||||
|
||||
for lead in leads.browse(cr, uid, record_id, context=context):
|
||||
if lead.section_id:
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('sequence','>=',1), ('section_ids','=', lead.section_id.id)])
|
||||
else:
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('sequence','>=',1)])
|
||||
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
|
||||
|
||||
if data.action == 'create':
|
||||
partner_ids = []
|
||||
partner_ids = self._create_partner(cr, uid, ids, context=context)
|
||||
partner_id = partner_ids and partner_ids[0]
|
||||
elif data.action == 'exist':
|
||||
partner_id = data.partner_id and data.partner_id.id
|
||||
else:
|
||||
partner_id = False
|
||||
|
||||
self._convert(cr, uid, ids, lead, partner_id, stage_ids, context=context)
|
||||
self.send_mail_to_salesman(cr, uid, lead)
|
||||
#If we convert in mass, don't merge if there is no other opportunity but no warning
|
||||
if data.name == 'merge' and (len(data.opportunity_ids) > 1 or not context.get('mass_convert') ):
|
||||
merge_obj = self.pool.get('crm.merge.opportunity')
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, [data.opportunity_ids[0].id])]}, context=context)
|
||||
context.update({'lead_ids' : record_id, "convert" : True})
|
||||
return merge_obj.merge(cr, uid, data.opportunity_ids, context=context)
|
||||
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form,tree',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity')],
|
||||
'res_id': int(lead.id),
|
||||
'view_id': False,
|
||||
'views': [(opportunity_view_form, 'form'),
|
||||
(opportunity_view_tree, 'tree'),
|
||||
(False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': opportunity_view_search
|
||||
}
|
||||
|
||||
lead = self.pool.get('crm.lead')
|
||||
lead_ids = context.get('active_ids', [])
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
self._convert_opportunity(cr, uid, ids, {'lead_ids': lead_ids}, context=context)
|
||||
self._merge_opportunity(cr, uid, ids, data.opportunity_ids, data.action, context=context)
|
||||
return lead.redirect_opportunity_view(cr, uid, lead_ids[0], context=context)
|
||||
|
||||
crm_lead2opportunity_partner()
|
||||
|
||||
|
@ -240,55 +154,19 @@ class crm_lead2opportunity_mass_convert(osv.osv_memory):
|
|||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
|
||||
}
|
||||
def _convert_opportunity(self, cr, uid, ids, vals, context=None):
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
salesteam_id = data.section_id and data.section_id.id or False
|
||||
salesman = []
|
||||
if data.user_ids:
|
||||
salesman = [x.id for x in data.user_ids]
|
||||
vals.update({'user_ids': salesman, 'section_id': salesteam_id})
|
||||
return super(crm_lead2opportunity_mass_convert, self)._convert_opportunity(cr, uid, ids, vals, context=context)
|
||||
|
||||
def mass_convert(self, cr, uid, ids, context=None):
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
active_ids = context.get('active_ids')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
|
||||
salesteam = data.section_id and data.section_id.id
|
||||
if data.user_ids:
|
||||
salesmans = map(lambda x : x.id, data.user_ids)
|
||||
index = 0
|
||||
else:
|
||||
salesmans = False
|
||||
|
||||
for lead_id in active_ids:
|
||||
value = {}
|
||||
if salesteam:
|
||||
value['section_id'] = salesteam
|
||||
if salesmans:
|
||||
value['user_id'] = salesmans[index]
|
||||
index += 1
|
||||
index = index < len(salesmans) and index or 0
|
||||
if value:
|
||||
lead_obj.write(cr, uid, [lead_id], value, context=context)
|
||||
|
||||
context['active_ids'] = [lead_id]
|
||||
value = self.default_get(cr, uid, ['partner_id', 'opportunity_ids'], context=context)
|
||||
value['opportunity_ids'] = [(6, 0, value['opportunity_ids'])]
|
||||
self.write(cr, uid, ids, value, context=context)
|
||||
|
||||
self.action_apply(cr, uid, ids, context=context)
|
||||
|
||||
|
||||
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
result = models_data._get_id(cr, uid, 'crm', 'view_crm_case_opportunities_filter')
|
||||
opportunity_view_search = models_data.browse(cr, uid, result, context=context).res_id
|
||||
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity'), ('id', 'in', active_ids)],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': opportunity_view_search,
|
||||
}
|
||||
|
||||
value = self.default_get(cr, uid, ['partner_id', 'opportunity_ids'], context=context)
|
||||
value['opportunity_ids'] = [(6, 0, value['opportunity_ids'])]
|
||||
self.write(cr, uid, ids, value, context=context)
|
||||
return self.action_apply(cr, uid, ids, context=context)
|
||||
crm_lead2opportunity_mass_convert()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -65,6 +65,15 @@
|
|||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_crm_lead2opportunity_partner" model="ir.actions.act_window">
|
||||
<field name="name">Create a Partner</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">crm.lead2opportunity.partner</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_crm_lead2opportunity_partner"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<act_window id="action_crm_send_mass_convert"
|
||||
multi="True"
|
||||
|
|
|
@ -21,11 +21,9 @@
|
|||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
import re
|
||||
|
||||
class crm_lead2partner(osv.osv_memory):
|
||||
""" Converts lead to partner """
|
||||
|
||||
_name = 'crm.lead2partner'
|
||||
_description = 'Lead to Partner'
|
||||
|
||||
|
@ -35,171 +33,89 @@ class crm_lead2partner(osv.osv_memory):
|
|||
'Action', required=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
}
|
||||
|
||||
def view_init(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function checks for precondition before wizard executes
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
"""
|
||||
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
if context is None:
|
||||
context = {}
|
||||
model = context.get('active_model')
|
||||
model = self.pool.get(model)
|
||||
rec_ids = context and context.get('active_ids', [])
|
||||
for lead in lead_obj.browse(cr, uid, rec_ids, context=context):
|
||||
if lead.partner_id:
|
||||
for this in model.browse(cr, uid, rec_ids, context=context):
|
||||
if this.partner_id:
|
||||
raise osv.except_osv(_('Warning !'),
|
||||
_('A partner is already defined on this lead.'))
|
||||
_('A partner is already defined.'))
|
||||
|
||||
def _select_partner(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
lead = self.pool.get('crm.lead')
|
||||
partner = self.pool.get('res.partner')
|
||||
lead_ids = list(context and context.get('active_ids', []) or [])
|
||||
if not len(lead_ids):
|
||||
return False
|
||||
this = lead.browse(cr, uid, lead_ids[0], context=context)
|
||||
# Find partner address matches the email_from of the lead
|
||||
res = lead.message_partner_by_email(cr, uid, this.email_from, context=context)
|
||||
partner_id = res.get('partner_id', False)
|
||||
# Find partner name that matches the name of the lead
|
||||
if not partner_id and this.partner_name:
|
||||
partner_ids = partner.search(cr, uid, [('name', '=', this.partner_name)], context=context)
|
||||
if partner_ids and len(partner_ids):
|
||||
partner_id = partner_ids[0]
|
||||
return partner_id
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : default values of fields.
|
||||
"""
|
||||
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
|
||||
partner_id = self._select_partner(cr, uid, context=context)
|
||||
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
partner_id = False
|
||||
|
||||
data = list(context and context.get('active_ids', []) or [])
|
||||
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
|
||||
for lead in lead_obj.browse(cr, uid, data, context=context):
|
||||
partner_ids = []
|
||||
# Find partner address matches the email_from of the lead
|
||||
email = re.findall(r'([^ ,<@]+@[^> ,]+)', lead.email_from or '')
|
||||
email = map(lambda x: "'" + x + "'", email)
|
||||
if email:
|
||||
cr.execute("""select partner_id from res_partner_address
|
||||
where
|
||||
substring(email from '([^ ,<@]+@[^> ,]+)') in (%s)""" % (','.join(email)))
|
||||
partner_ids = map(lambda x: x[0], cr.fetchall())
|
||||
|
||||
# Find partner name that matches the name of the lead
|
||||
if not partner_ids and lead.partner_name:
|
||||
partner_ids = partner_obj.search(cr, uid, [('name', '=ilike', lead.partner_name)], context=context)
|
||||
|
||||
partner_id = partner_ids and partner_ids[0] or False
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': partner_id})
|
||||
if 'action' in fields:
|
||||
res.update({'action': partner_id and 'exist' or 'create'})
|
||||
if 'opportunity_ids' in fields:
|
||||
res.update({'opportunity_ids': data})
|
||||
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': partner_id})
|
||||
if 'action' in fields:
|
||||
res.update({'action': partner_id and 'exist' or 'create'})
|
||||
|
||||
return res
|
||||
|
||||
def open_create_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function Opens form of create partner.
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Lead to Partner's IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : Dictionary value for next form.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
view_obj = self.pool.get('ir.ui.view')
|
||||
view_id = view_obj.search(cr, uid, [('model', '=', 'crm.lead2partner'), \
|
||||
('name', '=', 'crm.lead2partner.view')])
|
||||
view_id = view_obj.search(cr, uid, [('model', '=', self._name), \
|
||||
('name', '=', self._name+'.view')])
|
||||
return {
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'view_id': view_id or False,
|
||||
'res_model': 'crm.lead2partner',
|
||||
'res_model': self._name,
|
||||
'context': context,
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def _create_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function Creates partner based on action.
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Lead to Partner's IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : Dictionary {}.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
contact_obj = self.pool.get('res.partner.address')
|
||||
partner_ids = []
|
||||
partner_id = False
|
||||
rec_ids = context and context.get('active_ids', [])
|
||||
|
||||
for data in self.browse(cr, uid, ids, context=context):
|
||||
for lead in lead_obj.browse(cr, uid, rec_ids, context=context):
|
||||
if data.action == 'create':
|
||||
partner_id = partner_obj.create(cr, uid, {
|
||||
'name': lead.partner_name or lead.contact_name or lead.name,
|
||||
'user_id': lead.user_id.id,
|
||||
'comment': lead.description,
|
||||
'address': []
|
||||
})
|
||||
contact_obj.create(cr, uid, {
|
||||
'partner_id': partner_id,
|
||||
'name': lead.contact_name,
|
||||
'phone': lead.phone,
|
||||
'mobile': lead.mobile,
|
||||
'email': lead.email_from,
|
||||
'fax': lead.fax,
|
||||
'title': lead.title and lead.title.id or False,
|
||||
'function': lead.function,
|
||||
'street': lead.street,
|
||||
'street2': lead.street2,
|
||||
'zip': lead.zip,
|
||||
'city': lead.city,
|
||||
'country_id': lead.country_id and lead.country_id.id or False,
|
||||
'state_id': lead.state_id and lead.state_id.id or False,
|
||||
})
|
||||
|
||||
else:
|
||||
if data.partner_id:
|
||||
partner_id = data.partner_id.id
|
||||
self.assign_partner(cr, uid, lead.id, partner_id)
|
||||
partner_ids.append(partner_id)
|
||||
return partner_ids
|
||||
|
||||
|
||||
def assign_partner(self, cr, uid, lead_id, partner_id):
|
||||
self.pool.get("crm.lead").write(cr, uid, [lead_id], {'partner_id' : partner_id})
|
||||
|
||||
lead = self.pool.get('crm.lead')
|
||||
lead_ids = context and context.get('active_ids') or []
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
partner_id = data.partner_id and data.partner_id.id or False
|
||||
partner_ids = lead.convert_partner(cr, uid, lead_ids, data.action, partner_id, context=context)
|
||||
return partner_ids[lead_ids[0]]
|
||||
|
||||
def make_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function Makes partner based on action.
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Lead to Partner's IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : Dictionary value for created Partner form.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
partner_ids = self._create_partner(cr, uid, ids, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
partner_id = self._create_partner(cr, uid, ids, context=context)
|
||||
return self.pool.get('res.partner').redirect_partner_form(cr, uid, partner_id, context=context)
|
||||
|
||||
crm_lead2partner()
|
||||
|
||||
|
|
|
@ -26,195 +26,16 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
_name = 'crm.merge.opportunity'
|
||||
_description = 'Merge two Opportunities'
|
||||
|
||||
def _get_first_not_null_id(self, attr, ops, oldest):
|
||||
if hasattr(oldest, attr) and getattr(oldest, attr):
|
||||
return getattr(oldest, attr).id
|
||||
|
||||
for op in ops:
|
||||
if hasattr(op, attr) and getattr(op, attr):
|
||||
return getattr(op, attr).id
|
||||
return False
|
||||
|
||||
def _get_first_not_null(self, attr, ops, oldest):
|
||||
if hasattr(oldest, attr) and getattr(oldest, attr):
|
||||
return getattr(oldest, attr)
|
||||
|
||||
for op in ops:
|
||||
if hasattr(op, attr) and getattr(op, attr):
|
||||
return getattr(op, attr)
|
||||
return False
|
||||
|
||||
def _concat_all(self, attr, ops):
|
||||
return ', '.join([getattr(op, attr) for op in ops if hasattr(op, attr) and getattr(op, attr)])
|
||||
|
||||
|
||||
def get_attachments(self, cr, uid, id, context=None):
|
||||
proxy = self.pool.get('ir.attachment')
|
||||
ids = proxy.search(cr, uid, [('res_model', '=', 'crm.lead'), ('res_id', '=', id)], context=context)
|
||||
return proxy.browse(cr, uid, ids, context=context)
|
||||
|
||||
def find_oldest(self, cr, uid, op_ids, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
ids = [op_id.id for op_id in op_ids]
|
||||
if context.get('convert'):
|
||||
ids = list(set(ids) - set(context.get('lead_ids', False)) )
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
op_id = lead_obj.search(cr, uid, [('id', 'in', ids)], order='create_date' , context=context)
|
||||
if not op_id:
|
||||
return False
|
||||
opps = lead_obj.browse(cr, uid, [op_id[0]], context=context)
|
||||
return opps[0]
|
||||
|
||||
def _update_data(self, op_ids, oldest_opp):
|
||||
data = {
|
||||
'partner_id': self._get_first_not_null_id('partner_id', op_ids, oldest_opp), # !!
|
||||
'title': self._get_first_not_null_id('title', op_ids, oldest_opp),
|
||||
'name' : self._get_first_not_null('name', op_ids, oldest_opp), #not lost
|
||||
'categ_id' : self._get_first_not_null_id('categ_id', op_ids, oldest_opp), # !!
|
||||
'channel_id' : self._get_first_not_null_id('channel_id', op_ids, oldest_opp), # !!
|
||||
'city' : self._get_first_not_null('city', op_ids, oldest_opp), # !!
|
||||
'company_id' : self._get_first_not_null_id('company_id', op_ids, oldest_opp), #!!
|
||||
'contact_name' : self._get_first_not_null('contact_name', op_ids, oldest_opp), #not lost
|
||||
'country_id' : self._get_first_not_null_id('country_id', op_ids, oldest_opp), #!!
|
||||
'partner_address_id' : self._get_first_not_null_id('partner_address_id', op_ids, oldest_opp), #!!
|
||||
'type_id' : self._get_first_not_null_id('type_id', op_ids, oldest_opp), #!!
|
||||
'user_id' : self._get_first_not_null_id('user_id', op_ids, oldest_opp), #!!
|
||||
'section_id' : self._get_first_not_null_id('section_id', op_ids, oldest_opp), #!!
|
||||
'state_id' : self._get_first_not_null_id('state_id', op_ids, oldest_opp),
|
||||
'description' : self._concat_all('description', op_ids), #not lost
|
||||
'email' : self._get_first_not_null('email', op_ids, oldest_opp), # !!
|
||||
'fax' : self._get_first_not_null('fax', op_ids, oldest_opp),
|
||||
'mobile' : self._get_first_not_null('mobile', op_ids, oldest_opp),
|
||||
'partner_name' : self._get_first_not_null('partner_name', op_ids, oldest_opp),
|
||||
'phone' : self._get_first_not_null('phone', op_ids, oldest_opp),
|
||||
'probability' : self._get_first_not_null('probability', op_ids, oldest_opp),
|
||||
'planned_revenue' : self._get_first_not_null('planned_revenue', op_ids, oldest_opp),
|
||||
'street' : self._get_first_not_null('street', op_ids, oldest_opp),
|
||||
'street2' : self._get_first_not_null('street2', op_ids, oldest_opp),
|
||||
'zip' : self._get_first_not_null('zip', op_ids, oldest_opp),
|
||||
'state' : 'open',
|
||||
'create_date' : self._get_first_not_null('create_date', op_ids, oldest_opp),
|
||||
'date_action_last': self._get_first_not_null('date_action_last', op_ids, oldest_opp),
|
||||
'date_action_next': self._get_first_not_null('date_action_next', op_ids, oldest_opp),
|
||||
'email_from' : self._get_first_not_null('email_from', op_ids, oldest_opp),
|
||||
'email_cc' : self._get_first_not_null('email_cc', op_ids, oldest_opp),
|
||||
'partner_name' : self._get_first_not_null('partner_name', op_ids, oldest_opp),
|
||||
}
|
||||
return data
|
||||
|
||||
def merge(self, cr, uid, op_ids, context=None):
|
||||
"""
|
||||
:param opp_ids: list of opportunities ids to merge
|
||||
"""
|
||||
opp_obj = self.pool.get('crm.lead')
|
||||
message_obj = self.pool.get('mail.message')
|
||||
|
||||
lead_ids = context and context.get('lead_ids', []) or []
|
||||
|
||||
if len(op_ids) <= 1:
|
||||
raise osv.except_osv(_('Warning !'),_('Please select more than one opportunities.'))
|
||||
|
||||
opportunities = opp_obj.browse(cr, uid, lead_ids, context=context)
|
||||
opportunities_list = list(set(op_ids) - set(opportunities))
|
||||
oldest_opp = self.find_oldest(cr, uid, op_ids, context=context)
|
||||
if opportunities :
|
||||
first_opportunity = opportunities[0]
|
||||
tail_opportunities = opportunities_list
|
||||
else:
|
||||
first_opportunity = opportunities_list[0]
|
||||
tail_opportunities = opportunities_list[1:]
|
||||
data = self._update_data(op_ids, oldest_opp)
|
||||
|
||||
#copy message into the first opportunity + merge attachement
|
||||
count = 1
|
||||
first_attachments = self.get_attachments(cr, uid, first_opportunity, context=context)
|
||||
for opp in tail_opportunities:
|
||||
attachments = self.get_attachments(cr, uid, opp, context=context)
|
||||
for first in first_attachments:
|
||||
for attachment in attachments:
|
||||
if attachment.name == first.name:
|
||||
values = dict(
|
||||
name = "%s (%s)" % (attachment.name, count,),
|
||||
res_id = first_opportunity.id,
|
||||
)
|
||||
attachment.write(values)
|
||||
count+=1
|
||||
|
||||
for history in opp.message_ids:
|
||||
message_obj.write(cr, uid, history.id, {'res_id': first_opportunity.id, 'subject' : _("From %s : %s") % (opp.name, history.subject) }, context=context)
|
||||
|
||||
#Notification about loss of information
|
||||
details = []
|
||||
subject = ['Merged opportunities :']
|
||||
for opp in op_ids:
|
||||
subject.append(opp.name)
|
||||
details.append(_('Merged Opportunity: %s\n Partner: %s\n Stage: %s\n Section: %s\n Salesman: %s\n Category: %s\n Channel: %s\n Company: %s\n Contact name: %s\n Email: %s\n Phone number: %s\n Fax: %s\n Mobile: %s\n State: %s\n Description: %s\n Probability: %s\n Planned revennue: %s\n Country: %s\n City: %s\n Street: %s\n Street 2: %s\n Zip 2: %s') % ( opp.name, opp.partner_id.name or '',
|
||||
opp.stage_id.name or '',
|
||||
opp.section_id.name or '',
|
||||
opp.user_id.name or '',
|
||||
opp.categ_id.name or '',
|
||||
opp.channel_id.name or '',
|
||||
opp.company_id.name or '',
|
||||
opp.contact_name or '',
|
||||
opp.email_from or '',
|
||||
opp.phone or '',
|
||||
opp.fax or '',
|
||||
opp.mobile or '',
|
||||
opp.state_id.name or '',
|
||||
opp.description or '',
|
||||
opp.probability or '',
|
||||
opp.planned_revenue or '',
|
||||
opp.country_id.name or '',
|
||||
opp.city or '',
|
||||
opp.street or '',
|
||||
opp.street2 or '',
|
||||
opp.zip or '',
|
||||
))
|
||||
subject = subject[0] + ", ".join(subject[1:])
|
||||
details = "\n\n".join(details)
|
||||
|
||||
opp_obj.message_append(cr, uid, [first_opportunity], subject, body_text=details)
|
||||
#data.update({'message_ids' : [(6, 0 ,self._concat_o2m('message_ids', op_ids))]})
|
||||
opp_obj.write(cr, uid, [first_opportunity.id], data, context=context)
|
||||
unlink_ids = map(lambda x: x.id, tail_opportunities)
|
||||
opp_obj.unlink(cr, uid, unlink_ids, context=context)
|
||||
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
# Get Opportunity views
|
||||
opportunity_view_form = models_data._get_id(
|
||||
cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
opportunity_view_tree = models_data._get_id(
|
||||
cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
if opportunity_view_form:
|
||||
opportunity_view_form = models_data.browse(
|
||||
cr, uid, opportunity_view_form, context=context).res_id
|
||||
if opportunity_view_tree:
|
||||
opportunity_view_tree = models_data.browse(
|
||||
cr, uid, opportunity_view_tree, context=context).res_id
|
||||
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree, form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity')],
|
||||
'res_id': int(first_opportunity.id),
|
||||
'view_id': False,
|
||||
'views': [(opportunity_view_form, 'form'),
|
||||
(opportunity_view_tree, 'tree'),
|
||||
(False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
|
||||
def action_merge(self, cr, uid, ids, context=None):
|
||||
obj_opportunity = self.browse(cr, uid, ids[0], context=context)
|
||||
op_ids = obj_opportunity.opportunity_ids
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, [op_ids[0].id])]}, context=context)
|
||||
context['lead_ids'] = [op_ids[0].id]
|
||||
return self.merge(cr, uid, op_ids, context)
|
||||
lead = self.pool.get('crm.lead')
|
||||
record = self.browse(cr, uid, ids[0], context=context)
|
||||
opportunities = record.opportunity_ids
|
||||
#TOFIX: why need to check lead_ids here
|
||||
lead_ids = [opportunities[0].id]
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, lead_ids)]}, context=context)
|
||||
context['lead_ids'] = lead_ids
|
||||
merge_id = lead.merge_opportunity(cr, uid, [x.id for x in opportunities], context=context)
|
||||
return lead.redirect_opportunity_view(cr, uid, merge_id, context=context)
|
||||
|
||||
_columns = {
|
||||
'opportunity_ids' : fields.many2many('crm.lead', 'merge_opportunity_rel', 'merge_id', 'opportunity_id', 'Opportunities', domain=[('type', '=', 'opportunity')]),
|
||||
|
@ -223,13 +44,6 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current users ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : default values of fields.
|
||||
"""
|
||||
record_ids = context and context.get('active_ids', False) or False
|
||||
res = super(crm_merge_opportunity, self).default_get(cr, uid, fields, context=context)
|
||||
|
|
|
@ -28,36 +28,11 @@ import time
|
|||
|
||||
class crm_opportunity2phonecall(osv.osv_memory):
|
||||
"""Converts Opportunity to Phonecall"""
|
||||
|
||||
_inherit = 'crm.phonecall2phonecall'
|
||||
_name = 'crm.opportunity2phonecall'
|
||||
_description = 'Opportunity to Phonecall'
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Call summary', size=64, required=True, select=1),
|
||||
'user_id' : fields.many2one('res.users', "Assign To"),
|
||||
'contact_name':fields.char('Contact', size=64),
|
||||
'phone':fields.char('Phone', size=64),
|
||||
'partner_id' : fields.many2one('res.partner', "Partner"),
|
||||
'date': fields.datetime('Date'),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Category', \
|
||||
domain="['|',('section_id','=',False),('section_id','=',section_id),\
|
||||
('object_id.model', '=', 'crm.phonecall')]"),
|
||||
'action': fields.selection([('schedule','Schedule a call'), ('log','Log a call')], 'Action', required=True),
|
||||
'note':fields.text('Note'),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : default values of fields.
|
||||
"""
|
||||
opp_obj = self.pool.get('crm.lead')
|
||||
categ_id = False
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
|
@ -66,8 +41,8 @@ class crm_opportunity2phonecall(osv.osv_memory):
|
|||
categ_id = data_obj.browse(cr, uid, res_id, context=context).res_id
|
||||
|
||||
record_ids = context and context.get('active_ids', []) or []
|
||||
res = super(crm_opportunity2phonecall, self).default_get(cr, uid, fields, context=context)
|
||||
res.update({'action': 'log', 'date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
res = {}
|
||||
res.update({'action': 'schedule', 'date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
for opp in opp_obj.browse(cr, uid, record_ids, context=context):
|
||||
if 'name' in fields:
|
||||
res.update({'name': opp.name})
|
||||
|
@ -87,84 +62,20 @@ class crm_opportunity2phonecall(osv.osv_memory):
|
|||
res.update({'phone': opp.phone or (opp.partner_address_id and opp.partner_address_id.phone or False)})
|
||||
return res
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Opportunity to Phonecall form
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Opportunity to Phonecall's IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This converts Opportunity to Phonecall and opens Phonecall view
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user's ID for security checks,
|
||||
@param ids: List of Opportunity to Phonecall IDs
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : Dictionary value for created Opportunity form
|
||||
"""
|
||||
def action_schedule(self, cr, uid, ids, context=None):
|
||||
value = {}
|
||||
record_ids = context and context.get('active_ids', []) or []
|
||||
|
||||
phonecall_obj = self.pool.get('crm.phonecall')
|
||||
opp_obj = self.pool.get('crm.lead')
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
result = mod_obj._get_id(cr, uid, 'crm', 'view_crm_case_phonecalls_filter')
|
||||
res = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
|
||||
# Select the view
|
||||
id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_phone_tree_view')
|
||||
id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_phone_form_view')
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
if id3:
|
||||
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
|
||||
|
||||
for this in self.browse(cr, uid, ids, context=context):
|
||||
for opp in opp_obj.browse(cr, uid, record_ids, context=context):
|
||||
vals = {
|
||||
'name' : opp.name,
|
||||
'case_id' : opp.id,
|
||||
'user_id' : this.user_id and this.user_id.id or False,
|
||||
'categ_id' : this.categ_id.id,
|
||||
'description' : opp.description or False,
|
||||
'date' : this.date,
|
||||
'section_id' : this.section_id.id or False,
|
||||
'partner_id': opp.partner_id and opp.partner_id.id or False,
|
||||
'partner_address_id': opp.partner_address_id and opp.partner_address_id.id or False,
|
||||
'partner_phone' : opp.phone or (opp.partner_address_id and opp.partner_address_id.phone or False),
|
||||
'partner_mobile' : opp.partner_address_id and opp.partner_address_id.mobile or False,
|
||||
'priority': opp.priority,
|
||||
'opportunity_id': opp.id,
|
||||
'date_open': time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
|
||||
new_case = phonecall_obj.create(cr, uid, vals, context=context)
|
||||
|
||||
if this.action == 'log':
|
||||
phonecall_obj.case_close(cr, uid, [new_case])
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
value = {
|
||||
'name': _('Phone Call'),
|
||||
'domain': "[('user_id','=',%s),('opportunity_id','=',%s)]" % (uid,opp.id),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'crm.phonecall',
|
||||
'res_id' : new_case,
|
||||
'views': [(id3, 'form'), (id2, 'tree'), (False, 'calendar')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': res['res_id'],
|
||||
}
|
||||
return value
|
||||
if context is None:
|
||||
context = {}
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
opportunity_ids = context and context.get('active_ids') or []
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
call_ids = opportunity.schedule_phonecall(cr, uid, opportunity_ids, data.date, data.name, \
|
||||
data.note, data.phone, data.contact_name, data.user_id and data.user_id.id or False, \
|
||||
data.section_id and data.section_id.id or False, \
|
||||
data.categ_id and data.categ_id.id or False, \
|
||||
action=data.action, context=context)
|
||||
return phonecall.redirect_phonecall_view(cr, uid, call_ids[opportunity_ids[0]], context=context)
|
||||
|
||||
crm_opportunity2phonecall()
|
||||
|
||||
|
|
|
@ -16,24 +16,19 @@
|
|||
<field name="name"/>
|
||||
<field name="date" string="Planned Date" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
<newline/>
|
||||
<group colspan="4">
|
||||
<field name="partner_id" readonly="True"/>
|
||||
<field name="categ_id" string="Type" widget="selection" domain="[('object_id.model', '=', 'crm.phonecall')]"/>
|
||||
<field name="contact_name"/>
|
||||
<field name="phone"/>
|
||||
</group>
|
||||
<group colspan="4">
|
||||
<field name="user_id" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
<field name="section_id" widget="selection" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
</group>
|
||||
<group colspan="4">
|
||||
<field name="note"/>
|
||||
</group>
|
||||
<field name="partner_id" readonly="True"/>
|
||||
<field name="categ_id" string="Type" widget="selection" domain="[('object_id.model', '=', 'crm.phonecall')]"/>
|
||||
<field name="contact_name"/>
|
||||
<field name="phone"/>
|
||||
<field name="user_id" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
<field name="section_id" widget="selection" attrs="{'invisible': [('action','=','log')]}"/>
|
||||
<separator string="Notes" colspan="4"/>
|
||||
<field name="note" colspan="4" nolabel="1"/>
|
||||
<separator string="" colspan="4"/>
|
||||
<group colspan="4" col="3">
|
||||
<button name="action_cancel" string="_Cancel" icon="gtk-cancel" special="cancel" />
|
||||
<button name="action_apply" type="object" string="Log call" icon="gtk-ok" attrs="{'invisible' : [('action', '!=', 'log')]}" />
|
||||
<button name="action_apply" type="object" string="Schedule call" icon="gtk-ok" attrs="{'invisible' : [('action', '!=', 'schedule')]}" />
|
||||
<button name="action_schedule" type="object" string="Log call" icon="gtk-ok" attrs="{'invisible' : [('action', '!=', 'log')]}" />
|
||||
<button name="action_schedule" type="object" string="Schedule call" icon="gtk-ok" attrs="{'invisible' : [('action', '!=', 'schedule')]}" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -35,16 +35,15 @@ class crm_partner2opportunity(osv.osv_memory):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
}
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Partner 2 Opportunity
|
||||
"""
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : default values of fields.
|
||||
"""
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
data = context and context.get('active_ids', []) or []
|
||||
|
@ -58,56 +57,17 @@ class crm_partner2opportunity(osv.osv_memory):
|
|||
return res
|
||||
|
||||
def make_opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
|
||||
data = context and context.get('active_ids', []) or []
|
||||
make_opportunity = self.pool.get('crm.partner2opportunity')
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
part_obj = self.pool.get('res.partner')
|
||||
categ_obj = self.pool.get('crm.case.categ')
|
||||
case_obj = self.pool.get('crm.lead')
|
||||
|
||||
for make_opportunity_obj in make_opportunity.browse(cr, uid, ids, context=context):
|
||||
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_opportunities_filter')
|
||||
res = data_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
if id3:
|
||||
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
|
||||
|
||||
address = part_obj.address_get(cr, uid, data)
|
||||
categ_ids = categ_obj.search(cr, uid, [('object_id.model','=','crm.lead')])
|
||||
|
||||
opp_id = case_obj.create(cr, uid, {
|
||||
'name' : make_opportunity_obj.name,
|
||||
'planned_revenue' : make_opportunity_obj.planned_revenue,
|
||||
'probability' : make_opportunity_obj.probability,
|
||||
'partner_id' : make_opportunity_obj.partner_id.id,
|
||||
'partner_address_id' : address['default'],
|
||||
'categ_id' : categ_ids and categ_ids[0] or '',
|
||||
'state' :'draft',
|
||||
'type': 'opportunity'
|
||||
})
|
||||
value = {
|
||||
'name' : _('Opportunity'),
|
||||
'view_type' : 'form',
|
||||
'view_mode' : 'form,tree',
|
||||
'res_model' : 'crm.lead',
|
||||
'res_id' : opp_id,
|
||||
'view_id' : False,
|
||||
'views' : [(id2, 'form'), (id3, 'tree'), (False, 'calendar'), (False, 'graph')],
|
||||
'type' : 'ir.actions.act_window',
|
||||
'search_view_id' : res['res_id']
|
||||
}
|
||||
return value
|
||||
partner_ids = context and context.get('active_ids', []) or []
|
||||
partner = self.pool.get('res.partner')
|
||||
lead = self.pool.get('crm.lead')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
opportunity_ids = partner.make_opportunity(cr, uid, partner_ids,
|
||||
data.name,
|
||||
data.planned_revenue,
|
||||
data.probability,
|
||||
)
|
||||
opportunity_id = opportunity_ids[partner_ids[0]]
|
||||
return lead.redirect_opportunity_view(cr, uid, opportunity_id, context=context)
|
||||
|
||||
crm_partner2opportunity()
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<field name="probability"/>
|
||||
<separator string="" colspan="4" />
|
||||
<group col="4" colspan="4">
|
||||
<button special="cancel" string="_Cancel" icon="gtk-cancel"/>
|
||||
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
|
||||
<button name="make_opportunity" string="Create Opportunity" type="object" icon="gtk-ok"/>
|
||||
</group>
|
||||
</form>
|
||||
|
|
|
@ -26,97 +26,31 @@ class crm_phonecall2opportunity(osv.osv_memory):
|
|||
""" Converts Phonecall to Opportunity"""
|
||||
|
||||
_name = 'crm.phonecall2opportunity'
|
||||
_inherit = 'crm.partner2opportunity'
|
||||
_description = 'Phonecall To Opportunity'
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Phonecall to Opportunity form
|
||||
"""
|
||||
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
def make_opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This converts Phonecall to Opportunity and opens Phonecall view
|
||||
"""
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
if record_id:
|
||||
opp_obj = self.pool.get('crm.lead')
|
||||
phonecall_obj = self.pool.get('crm.phonecall')
|
||||
case = phonecall_obj.browse(cr, uid, record_id, context=context)
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_opportunities_filter')
|
||||
res = data_obj.read(cr, uid, result, ['res_id'])
|
||||
id2 = data_obj._get_id(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
id3 = data_obj._get_id(cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
if id3:
|
||||
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
|
||||
|
||||
for this in self.browse(cr, uid, ids, context=context):
|
||||
address = None
|
||||
if this.partner_id:
|
||||
address_id = self.pool.get('res.partner').address_get(cr, uid, [this.partner_id.id])
|
||||
if address_id['default']:
|
||||
address = self.pool.get('res.partner.address').browse(cr, uid, address_id['default'], context=context)
|
||||
new_opportunity_id = opp_obj.create(cr, uid, {
|
||||
'name': this.name,
|
||||
'planned_revenue': this.planned_revenue,
|
||||
'probability': this.probability,
|
||||
'partner_id': this.partner_id and this.partner_id.id or False,
|
||||
'partner_address_id': address and address.id,
|
||||
'phone': address and address.phone,
|
||||
'mobile': address and address.mobile,
|
||||
'section_id': case.section_id and case.section_id.id or False,
|
||||
'description': case.description or False,
|
||||
'phonecall_id': case.id,
|
||||
'priority': case.priority,
|
||||
'type': 'opportunity',
|
||||
'phone': case.partner_phone or False,
|
||||
})
|
||||
vals = {
|
||||
'partner_id': this.partner_id.id,
|
||||
'opportunity_id' : new_opportunity_id,
|
||||
}
|
||||
phonecall_obj.write(cr, uid, [case.id], vals)
|
||||
phonecall_obj.case_close(cr, uid, [case.id])
|
||||
opp_obj.case_open(cr, uid, [new_opportunity_id])
|
||||
|
||||
value = {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form,tree',
|
||||
'res_model': 'crm.lead',
|
||||
'res_id': int(new_opportunity_id),
|
||||
'view_id': False,
|
||||
'views': [(id2, 'form'), (id3, 'tree'), (False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': res['res_id']
|
||||
}
|
||||
return value
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Opportunity Summary', size=64, required=True, select=1),
|
||||
'probability': fields.float('Success Probability'),
|
||||
'planned_revenue': fields.float('Expected Revenue'),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
}
|
||||
if not len(ids):
|
||||
return False
|
||||
call_ids = context and context.get('active_ids', False) or False
|
||||
this = self.browse(cr, uid, ids[0], context=context)
|
||||
if not call_ids:
|
||||
return {}
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
opportunity_ids = phonecall.convert_opportunity(cr, uid, call_ids, this.name, this.partner_id and this.partner_id.id or False, \
|
||||
this.planned_revenue, this.probability, context=context)
|
||||
return opportunity.redirect_opportunity_view(cr, uid, opportunity_ids[call_ids[0]], context=context)
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
@return : default values of fields.
|
||||
"""
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
res = super(crm_phonecall2opportunity, self).default_get(cr, uid, fields, context=context)
|
||||
res = {}
|
||||
|
||||
if record_id:
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, record_id, context=context)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue