diff --git a/addons/account/i18n/it.po b/addons/account/i18n/it.po index 79335be4e75..d38b9e78254 100644 --- a/addons/account/i18n/it.po +++ b/addons/account/i18n/it.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2010-03-29 15:32+0000\n" -"Last-Translator: Carlo Vettore \n" +"PO-Revision-Date: 2010-04-26 07:46+0000\n" +"Last-Translator: eLBati - albatos.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: 2010-04-17 04:06+0000\n" +"X-Launchpad-Export-Date: 2010-04-28 03:44+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: account @@ -1192,7 +1192,7 @@ msgstr "Report tassa" #: wizard_button:account.analytic.account.chart,init,open:0 #: wizard_button:account.chart,init,open:0 msgid "Open Charts" -msgstr "Conti aperti" +msgstr "Apri" #. module: account #: wizard_view:account.fiscalyear.close.state,init:0 @@ -2301,6 +2301,8 @@ msgstr "" #: wizard_view:account.chart,init:0 msgid "(If you do not select Fiscal year it will take all open fiscal years)" msgstr "" +"Se non si seleziona un anno fiscale, verranno visualizzati tutti gli anni " +"fiscali aperti" #. module: account #: help:account.invoice.tax,base_code_id:0 @@ -4429,7 +4431,7 @@ msgstr "" #. module: account #: wizard_view:account.wizard_paid_open,init:0 msgid "Open Invoice" -msgstr "Fattura aperta" +msgstr "Apri fattura" #. module: account #: model:process.node,note:account.process_node_draftstatement0 diff --git a/addons/account/i18n/pl.po b/addons/account/i18n/pl.po index 12e8c9efdf8..6634fd4f9ec 100644 --- a/addons/account/i18n/pl.po +++ b/addons/account/i18n/pl.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2010-04-25 17:34+0000\n" +"PO-Revision-Date: 2010-04-27 19:28+0000\n" "Last-Translator: Grzegorz Grzelak (Cirrus.pl) \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: 2010-04-26 03:42+0000\n" +"X-Launchpad-Export-Date: 2010-04-28 03:44+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: account @@ -2087,7 +2087,7 @@ msgstr "Wydatki" #. module: account #: field:account.journal,invoice_sequence_id:0 msgid "Invoice Sequence" -msgstr "Numeracja faktury" +msgstr "Numeracja faktur" #. module: account #: wizard_view:account.automatic.reconcile,init:0 diff --git a/addons/account_tax_include/i18n/cs.po b/addons/account_tax_include/i18n/cs.po index cd4dfc6f3ed..2cc4bc1bcc0 100644 --- a/addons/account_tax_include/i18n/cs.po +++ b/addons/account_tax_include/i18n/cs.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2010-04-25 21:20+0000\n" +"PO-Revision-Date: 2010-04-26 09:10+0000\n" "Last-Translator: Martin Volf \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: 2010-04-26 03:41+0000\n" +"X-Launchpad-Export-Date: 2010-04-28 03:44+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: account_tax_include @@ -24,12 +24,12 @@ msgstr "Neplatný XML pro zobrazení architektury" #. module: account_tax_include #: field:account.invoice,price_type:0 msgid "Price method" -msgstr "" +msgstr "Metoda určování cen" #. module: account_tax_include #: model:ir.module.module,shortdesc:account_tax_include.module_meta_information msgid "Invoices and prices with taxes included" -msgstr "" +msgstr "Faktury a ceny včetně daní" #. module: account_tax_include #: selection:account.invoice,price_type:0 diff --git a/addons/base_module_record/base_module_record.py b/addons/base_module_record/base_module_record.py index 97c0ada4bca..899241b4188 100644 --- a/addons/base_module_record/base_module_record.py +++ b/addons/base_module_record/base_module_record.py @@ -30,19 +30,26 @@ import tools #objects_proxy = netsvc.ExportService.getService('object').__class__ class recording_objects_proxy(osv_pool): def execute(self, *args, **argv): - if len(args) >= 6 and isinstance(args[5], dict): + if args[3] == 'create': + _old_args = args[4].copy() + elif args[3] == 'write': _old_args = args[5].copy() + elif len(args) >= 5 and isinstance(args[4], dict): + _old_args = args[4].copy() else: _old_args = None res = super(recording_objects_proxy, self).execute(*args, **argv) pool = pooler.get_pool(args[0]) mod = pool.get('ir.module.record') + if mod and mod.recording: if args[3] not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink'): if _old_args is not None: - args[5].update(_old_args) - if args[5]: - mod.recording_data.append(('query', args, argv,res)) + if args[3] == 'create': + args[4].update(_old_args) + elif args[3] == 'write': + args[5].update(_old_args) + mod.recording_data.append(('query', args, argv,res)) return res def exec_workflow(self, *args, **argv): @@ -125,7 +132,8 @@ class base_module_record(osv.osv): name = filter(lambda x: x in string.letters, (data.get('name','') or '').lower()) except: name='' - val = model.replace('.','_')+'_'+name+ str(i) +# name=data.get('name','') or ''.lower() + val = model.replace('.','_')+'_'+ name + str(i) i+=1 if val not in self.ids.values(): break @@ -146,7 +154,6 @@ class base_module_record(osv.osv): def _create_record(self, cr, uid, doc, model, data, record_id, noupdate=False): - data_pool = self.pool.get('ir.model.data') model_pool = self.pool.get(model) record = doc.createElement('record') @@ -196,12 +203,26 @@ class base_module_record(osv.osv): fname = model_pool._columns[key]._fields_id else: fname = model_pool._inherit_fields[key][2]._fields_id - valitem[2][fname] = record_id - newid,update = self._get_id(cr, uid, fields[key]['relation'], valitem[1]) - if not newid: + if valitem[0] == 0: newid = self._create_id(cr, uid, fields[key]['relation'], valitem[2]) + valitem[1]=newid + else: + newid,update = self._get_id(cr, uid, fields[key]['relation'], valitem[1]) + if not newid: + newid = self._create_id(cr, uid, fields[key]['relation'], valitem[2]) + valitem[1]=newid self.ids[(fields[key]['relation'], valitem[1])] = newid - +# if valitem[0] in (0,1): +# if key in model_pool._columns: +# fname = model_pool._columns[key]._fields_id +# else: +# fname = model_pool._inherit_fields[key][2]._fields_id +# valitem[2][fname] = record_id +# newid,update = self._get_id(cr, uid, fields[key]['relation'], valitem[1]) +# if not newid: +# newid = self._create_id(cr, uid, fields[key]['relation'], valitem[2]) +# self.ids[(fields[key]['relation'], valitem[1])] = newid +# childrecord, update = self._create_record(cr, uid, doc, fields[key]['relation'],valitem[2], newid) noupdate = noupdate or update record_list += childrecord @@ -245,7 +266,7 @@ class base_module_record(osv.osv): for key,val in data.items(): if ((key in defaults[model]) and (val == defaults[model][key])) and not(fields[key].get('required',False)): continue - if not (val or (fields[key]['type']=='boolean')): + if not (val or (fields[key]['type']=='function')): continue elif fields[key]['type'] in ('boolean',): if not val: @@ -267,12 +288,9 @@ class base_module_record(osv.osv): fname = model_pool._columns[key]._fields_id else: fname = model_pool._inherit_fields[key][2]._fields_id - valitem[2][fname] = record_id - newid,update = self._get_id(cr, uid, fields[key]['relation'], valitem[1]) - if not newid: - newid = self._create_id(cr, uid, fields[key]['relation'], valitem[2]) - self.ids[(fields[key]['relation'], valitem[1])] = newid - childrecord = self._create_yaml_record(cr, uid, fields[key]['relation'],valitem[2], newid) + del valitem[2][fname] #delete parent_field from child's fields list + + childrecord = self._create_yaml_record(cr, uid, fields[key]['relation'],valitem[2], None) items[0].append(childrecord['attrs']) attrs[key] = items elif fields[key]['type'] in ('many2many',): @@ -289,11 +307,11 @@ class base_module_record(osv.osv): if m2m[0]: attrs[key] = m2m else: - val=val.replace('"','\'') try: attrs[key]=str(val) except: attrs[key]=tools.ustr(val) + attrs[key]=attrs[key].replace('"','\'') record['attrs'] = attrs return record @@ -311,7 +329,7 @@ class base_module_record(osv.osv): for f in filter(lambda a: isinstance(obj._columns[a], fields.function)\ and (not obj._columns[a].store),obj._columns): del data[f] - + for key,val in data.items(): if result.has_key(key): continue @@ -361,16 +379,16 @@ class base_module_record(osv.osv): def _generate_object_xml(self, cr, uid, rec, recv, doc, result=None): record_list = [] noupdate = False - if rec[4]=='write': - for id in rec[5]: - id,update = self._get_id(cr, uid, rec[3], id) + if rec[3]=='write': + for id in rec[4]: + id,update = self._get_id(cr, uid, rec[2], id) noupdate = noupdate or update if not id: continue - record,update = self._create_record(cr, uid, doc, rec[3], rec[6], id) + record,update = self._create_record(cr, uid, doc, rec[2], rec[5], id) noupdate = noupdate or update record_list += record - + elif rec[4] in ('menu_create',): for id in rec[5]: id,update = self._get_id(cr, uid, rec[3], id) @@ -487,7 +505,10 @@ class base_module_record(osv.osv): yaml_file += str(object) + '''\n\n''' else: record= self._generate_object_yaml(cr, uid, rec[1],rec[3]) - yaml_file+="!comment Creating an %s record"%(record['model']) + '''\n''' + if self.mode == "create" or self.mode == "copy": + yaml_file+="!comment Creating a %s record"%(record['model']) + '''\n''' + else: + yaml_file+="!comment Modifying a %s record"%(record['model']) + '''\n''' object= yaml.load(unicode('''\n !record %s \n'''%record,'iso-8859-1')) yaml_file += str(object) + '''\n''' attrs=yaml.dump(object.attrs, default_flow_style=False) diff --git a/addons/base_setup/base_setup_installer.xml b/addons/base_setup/base_setup_installer.xml index 7a6d61a0e08..594133d3b12 100644 --- a/addons/base_setup/base_setup_installer.xml +++ b/addons/base_setup/base_setup_installer.xml @@ -28,7 +28,7 @@ If you don't think you need any of these right now, you can easily install them - + diff --git a/addons/base_setup/installer.py b/addons/base_setup/installer.py index 2c1ba113e47..9a817eaf10e 100644 --- a/addons/base_setup/installer.py +++ b/addons/base_setup/installer.py @@ -73,6 +73,7 @@ class base_setup_installer(osv.osv_memory): 'report_designer':fields.boolean('Advanced Reporting', help="Lets you install various tools to simplify and enhance " "OpenERP's report creation."), + 'thunderbird' :fields.boolean('Thunderbird'), # Vertical modules 'profile_association':fields.boolean('Associations', help="Installs a preselected set of OpenERP " diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 9c3eb9610d5..f60483f6f59 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -70,8 +70,16 @@ between mails and Open ERP.""", 'process/crm_configuration_process.xml', ], 'demo_xml': [ + 'test/test_crm_meeting.yml', 'crm_demo.xml', ], + 'test': ['test/test_crm_lead.yml', + 'test/test_crm_opportunity.yml', + 'test/test_crm_phonecall.yml', + 'test/test_crm_fund.yml', + 'test/test_crm_claim.yml', + 'test/test_crm_helpdesk.yml', + ], 'installable': True, 'active': False, 'certificate': '0079056041421', diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 85a27bb5d55..0c7d2e295ad 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -59,6 +59,7 @@ class crm_case_section(osv.osv): true, it will allow you to hide the sales team without removing it."), 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"), 'user_id': fields.many2one('res.users', 'Responsible User'), + 'member_ids':fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'), 'reply_to': fields.char('Reply-To', size=64, help="The email address put \ in the 'Reply-To' of all emails sent by Open ERP about cases in this sales team"), 'parent_id': fields.many2one('crm.case.section', 'Parent Team'), @@ -66,6 +67,7 @@ class crm_case_section(osv.osv): 'resource_calendar_id': fields.many2one('resource.calendar', "Resource's Calendar"), 'server_id':fields.many2one('email.smtpclient', 'Server ID'), 'note': fields.text('Description'), + } _defaults = { @@ -79,14 +81,14 @@ class crm_case_section(osv.osv): def _check_recursion(self, cr, uid, ids): """ - Checks for recursion level for sections + Checks for recursion level for sales team @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 section ids + @param ids: List of Sales team ids """ level = 100 - + while len(ids): cr.execute('select distinct parent_id from crm_case_section where id =ANY(%s)', (ids,)) ids = filter(None, map(lambda x: x[0], cr.fetchall())) @@ -97,7 +99,7 @@ class crm_case_section(osv.osv): return True _constraints = [ - (_check_recursion, 'Error ! You cannot create recursive sections.', ['parent_id']) + (_check_recursion, 'Error ! You cannot create recursive Sales team.', ['parent_id']) ] def name_get(self, cr, uid, ids, context=None): @@ -105,7 +107,7 @@ class crm_case_section(osv.osv): @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 section ids + @param ids: List of sales team ids """ if not context: context = {} diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py index 495eb9f351a..6979f3e5eee 100644 --- a/addons/crm/crm_meeting.py +++ b/addons/crm/crm_meeting.py @@ -65,7 +65,7 @@ class crm_meeting(osv.osv): _defaults = { 'state': lambda *a: 'draft', } - + def open_meeting(self, cr, uid, ids, context=None): """ Open Crm Meeting Form for Crm Meeting. @@ -75,13 +75,14 @@ class crm_meeting(osv.osv): @param context: A standard dictionary for contextual values @return: Dictionary value which open Crm Meeting form. """ + if not context: context = {} - + data_obj = self.pool.get('ir.model.data') - + value = {} - + 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') id4 = data_obj._get_id(cr, uid, 'crm', 'crm_case_calendar_view_meet') @@ -93,17 +94,17 @@ class crm_meeting(osv.osv): id4 = data_obj.browse(cr, uid, id4, context=context).res_id for id in ids: value = { - 'name': _('Meeting'), - 'view_type': 'form', - 'view_mode': 'form,tree', - 'res_model': 'crm.meeting', - 'view_id': False, + 'name': _('Meeting'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'crm.meeting', + 'view_id': False, 'views': [(id2, 'form'), (id3, 'tree'), (id4, 'calendar')], - 'type': 'ir.actions.act_window', - 'res_id': base_calendar.base_calendar_id2real_id(id), + 'type': 'ir.actions.act_window', + 'res_id': base_calendar.base_calendar_id2real_id(id), 'nodestroy': True } - + return value crm_meeting() diff --git a/addons/crm/crm_opportunity.py b/addons/crm/crm_opportunity.py index 204890e348c..dec672c3277 100644 --- a/addons/crm/crm_opportunity.py +++ b/addons/crm/crm_opportunity.py @@ -231,7 +231,7 @@ class crm_opportunity(osv.osv): } value = { 'name': _('Meetings'), - 'domain': "[('user_id','=',%s)]" % (uid), + 'domain': "[('user_id','=',%s),('opportunity_id','=',%s)]" % (uid,opp.id), 'context': context, 'view_type': 'form', 'view_mode': 'calendar,form,tree', @@ -242,7 +242,6 @@ class crm_opportunity(osv.osv): 'search_view_id': res['res_id'], 'nodestroy': True } - return value crm_opportunity() diff --git a/addons/crm/crm_opportunity_menu.xml b/addons/crm/crm_opportunity_menu.xml index 3bcdbc7bb9f..55bf9354287 100644 --- a/addons/crm/crm_opportunity_menu.xml +++ b/addons/crm/crm_opportunity_menu.xml @@ -18,8 +18,8 @@ res_model="crm.phonecall" src_model="crm.opportunity" view_mode="calendar,tree,form" - context="{'default_duration': 1.0}" - domain="[('user_id','=',uid)]" + context="{'default_duration': 1.0 ,'default_opportunity_id': active_id}" + domain="[('user_id','=',uid),('opportunity_id', '=', active_id)]" view_type="form"/> diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index 31d82cd94fb..5c171236836 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -11,7 +11,7 @@ crm.case.section form -
+ @@ -19,22 +19,24 @@ - - + + - + - - + + + + @@ -51,7 +53,7 @@ tree child_ids - + @@ -62,7 +64,7 @@ - Sections + Sales Team crm.case.section form diff --git a/addons/crm/report/crm_report_view.xml b/addons/crm/report/crm_report_view.xml index 97fa4feb6f1..814b056dbf1 100644 --- a/addons/crm/report/crm_report_view.xml +++ b/addons/crm/report/crm_report_view.xml @@ -178,7 +178,7 @@ diff --git a/addons/crm/test/test_crm_claim.yml b/addons/crm/test/test_crm_claim.yml new file mode 100644 index 00000000000..54ef47a56f5 --- /dev/null +++ b/addons/crm/test/test_crm_claim.yml @@ -0,0 +1,38 @@ +- | + Now I check claims which contain customer claim information about document + related problem, product related problem. +- | + I start by creating new claims for Damaged product as Value Claims with priority High and specify + date of claim at which claim is created. +- + !record {model: crm.claim, id: crm_claim_damagedproduct0}: + categ_id: crm.categ_claim2 + date: '2010-04-21 20:13:00' + email_from: info@balmerinc.be + name: 'Damaged product ' + partner_address_id: base.res_partner_address_1 + partner_id: base.res_partner_9 + priority: '2' + section_id: crm.section_sales_department + +- | + I check that the claims is in 'draft' state. +- + !assert {model: crm.claim, id: crm_claim_damagedproduct0}: + - state == 'draft' +- | + Now I make sure that claim is at "Accepted" stage. +- + !record {model: crm.claim, id: crm.crm_claim_damagedproduct0}: + stage_id: crm.stage_claim1 +- | + I can change that stage by next button right on it +- + !python {model: crm.claim}: | + self.stage_next(cr, uid, [ref('crm_claim_damagedproduct0')]) +- | + I make this claim as Open +- + !python {model: crm.claim}: | + self.case_open(cr, uid, [ref('crm_claim_damagedproduct0')]) + diff --git a/addons/crm/test/test_crm_fund.yml b/addons/crm/test/test_crm_fund.yml new file mode 100644 index 00000000000..4bcacbe148e --- /dev/null +++ b/addons/crm/test/test_crm_fund.yml @@ -0,0 +1,32 @@ +- | + Now I start test Fund Raising which contain information about Donation or charity + given by user. +- | + I start by creating new Funds entry for donation for books to poor school children + with cost 500000.00 and category as "Learning And Education" + I make payment by Cheque so I make sure that the mode on fund is selected as cheque +- + !record {model: crm.fundraising, id: crm_fundraising_donationforbookstopoorschoolchildren0}: + categ_id: crm.categ_fund2 + email_from: info@balmerinc.be + name: Donation for books to poor school children + partner_address_id: base.res_partner_address_1 + partner_id: base.res_partner_9 + planned_cost: 500000.0 + section_id: crm.section_sales_department + type_id: crm.type_fund2 +- | + I check that the Funds is in 'draft' state. +- + !assert {model: crm.fundraising, id: crm_fundraising_donationforbookstopoorschoolchildren0}: + - state == 'draft' +- | + Now I open Funds by click on "Open" button +- + !python {model: crm.fundraising}: | + self.case_open(cr, uid, [ref('crm_fundraising_donationforbookstopoorschoolchildren0')]) +- | + I can close Funds by click on "Done" button. +- + !python {model: crm.fundraising}: | + self.case_close(cr, uid, [ref('crm_fundraising_donationforbookstopoorschoolchildren0')]) diff --git a/addons/crm/test/test_crm_helpdesk.yml b/addons/crm/test/test_crm_helpdesk.yml new file mode 100644 index 00000000000..6d3beb43b41 --- /dev/null +++ b/addons/crm/test/test_crm_helpdesk.yml @@ -0,0 +1,38 @@ +- + | + I start by creating New helpdesk request regarding some functional questions. + I select Date at which helpdesk request is created. +- + !record {model: crm.helpdesk, id: crm_helpdesk_somefunctionalquestion0}: + date: '2010-04-22 10:17:00' + email_from: info@balmerinc.be + name: Some functional question. + partner_address_id: base.res_partner_address_1 + partner_id: base.res_partner_9 + section_id: crm.section_sales_department + +- | + I check that the Helpdesk request is in 'Draft' state. +- + !assert {model: crm.helpdesk, id: crm_helpdesk_somefunctionalquestion0}: + - state == 'draft' +- | + In order to make this helpdesk request to be considered I make it "Open" +- + !python {model: crm.helpdesk}: | + self.case_open(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')]) +- | + I can see that "Send Reminder" button is visible, which is used to send reminder to partner from + responsible person or send reminder to responsible person from partner. +- + #this is not work for yaml. +- +# !python {model: crm.helpdesk}: | +# self.remind_user(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')], context={}, attach=False, destination=True) +- | + After a proper communication for the request via email I make sure that the request is fulfilled and + I close this HelpDesk Request by clicking on "Close" button. +- + !python {model: crm.helpdesk}: | + self.case_close(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')]) +- diff --git a/addons/crm/test/test_crm_lead.yml b/addons/crm/test/test_crm_lead.yml new file mode 100644 index 00000000000..22fdfffca1b --- /dev/null +++ b/addons/crm/test/test_crm_lead.yml @@ -0,0 +1,113 @@ +- | + 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. +- | + In order to test the flow, 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: + - crm.group_crm_user + 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: Sandip zala + phone: (855) 924-4364 + mobile: (333) 715-1450 + section_id: crm.section_sales_department + referred: False + title: M. +- | + 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")]) + +- | + 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')) + if not lead.partner_id: + self.convert_opportunity(cr, uid, [ref("crm_lead_newcustomer0")], {'active_ids': [ref("crm_lead_newcustomer0")]}) +- + | + Now, select "create a new partner" option in this wizard. +- + !record {model: crm.lead2opportunity.partner, id: crm_lead2opportunity_partner_create_0}: + action: 'create' +- + I click on "Continue" button of this wizard. +- + !python {model: crm.lead2opportunity.partner}: | + self.make_partner(cr, uid, [ref("crm_lead2opportunity_partner_create_0")], {'active_ids': [ref("crm_lead_newcustomer0")]}) +- + Now, I give value to this wizard field. +- + !record {model: crm.lead2opportunity, id: crm_lead2opportunity_stonage_0}: + name: Sandip zala + planned_revenue: 0.00 + probability: 0.00 +- + Then, Click on "Create Opportunity" button of this wizard. +- + !python {model: crm.lead2opportunity}: | + self.action_apply(cr, uid, [ref('crm_lead2opportunity_stonage_0')], {'active_id': ref('crm_lead_newcustomer0')}) + +- | + I can check that a lead and a business opportunity is now assigned to this + lead. +- + # !python {model: crm.lead, id: crm_lead_newcustomer0}: + # - opportunity_id.id != False + +- | + I check that the partner associated to this lead as the same country, phone number + and name than the opportunity. +- + !python {model: crm.lead}: | + lead = self.browse(cr, uid, ref("crm_lead_newcustomer0")) + print "lead", lead.partner_name + obj_opportunity = self.pool.get('crm.opportunity') + ids = obj_opportunity.search(cr, uid, [('name', '=', lead.partner_name)]) + opportunity = obj_opportunity.browse(cr, uid, ids)[0] + assert lead.partner_name == opportunity.partner_id.name + assert lead.phone == opportunity.phone +- + | + # yaml is also not working smpt server and send new email. + +- | + I configure with smtp server. +- | + And I communicate with lead through send New mail to Lead using it email address from user which are loged. +- | + 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. + + \ No newline at end of file diff --git a/addons/crm/test/test_crm_meeting.yml b/addons/crm/test/test_crm_meeting.yml new file mode 100644 index 00000000000..6365c913b1f --- /dev/null +++ b/addons/crm/test/test_crm_meeting.yml @@ -0,0 +1,99 @@ +- | + Now 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: '2010-04-21 16:04:00' + date_deadline: '2010-04-22 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 +- | + Now 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 occure 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, 'freq': 'weekly', 'rrule_type': 'custom'}) + +- | + 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}: | + ids = self.search(cr, uid, [('date', '>=', '2010-05-21 00:00:00'), ('date', '<=', '2010-04-21 00:00:00')] ) + assert len(ids) == 9 + +- | + Now If I want to edit meetings information for all occurence I click on "Edit All" button. +- + !python {model: crm.meeting}: | + self.open_meeting(cr, uid, [ref('crm_meeting_regardingpresentation0')]) +- | + 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 occurences 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 + partner_id: base.res_partner_9 + user_ids: + - base.user_demo +- | + If I set Send mail boolean as True I can see that an email is send to + specified email address with proper meeting information. +- + #This is not working for send mail boolean as True. +- + 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')]) diff --git a/addons/crm/test/test_crm_opportunity.yml b/addons/crm/test/test_crm_opportunity.yml new file mode 100644 index 00000000000..d7118dd0c90 --- /dev/null +++ b/addons/crm/test/test_crm_opportunity.yml @@ -0,0 +1,81 @@ +- | + 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.opportunity, 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_oppor1 + categ_id: crm.categ_oppor2 + section_id: crm.section_sales_department + +- | + I check that the opportunity is in 'New' state. +- + !assert {model: crm.opportunity, id: crm_opportunity_abcfuelcounits0}: + - state == "draft" +- | + I open opportunity by click on "Open" button, +- + !python {model: crm.opportunity}: | + self.case_open(cr, uid, [ref("crm_opportunity_abcfuelcounits0")]) + +- | + I schedule Meeting on this current opportunity by clicking on "schedule + Meeting". +- + !python {model: crm.opportunity}: | + 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 schedule meeting. + I fill proper data for that meeting and save it +- + !record {model: crm.meeting, id: crm_meeting_abcfuelcounits0}: + alarm_id: base_calendar.alarm3 + date: '2010-04-16 00:00:00' + date_deadline: '2010-04-16 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 + rrule_type: weekly + 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: '2010-04-17 11:15:00' + name: 'ABC FUEL CO 829264 - 10002 units ' + section_id: crm.section_sales_department + user_id: base.user_demo +- | + schedule phonecall by apply (action_apply)function of 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}: | + ids = self.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: '2010-04-17 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 + \ No newline at end of file diff --git a/addons/crm/test/test_crm_phonecall.yml b/addons/crm/test/test_crm_phonecall.yml new file mode 100644 index 00000000000..feb87e0a879 --- /dev/null +++ b/addons/crm/test/test_crm_phonecall.yml @@ -0,0 +1,91 @@ +- | + I start by creating a new phonecall. +- + !record {model: crm.phonecall, id: crm_phonecall_interviewcall0}: + date: '2010-04-21 18:59:00' + name: Interview call + partner_address_id: base.res_partner_address_1 + partner_id: base.res_partner_9 + partner_mobile: (+32)2 211 34 83 + section_id: crm.section_sales_department + +- | + 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. +- +# !python {model: crm.phonecall2opportunity}: | +# self.action_apply(cr, uid, [1], {'active_id': ref('crm_phonecall_interviewcall0')}) + +- + # This is not working, find a way to do that in YAML + +- | + I can see that a business opportunity is now assigned to this phonecall +- | + I check that the partner associated to this as the same country, phone number + and name than the phonecall. +- | + In order to avoid the duplication of similar partner, OpenERP should be able to + detect if the partner exists or if it should be created from the phonecall during the + conversion. +- | + In order to test this, I log as the user "user_crm2" +- | + Then, I create the same phonecall than the preceeding one but I change the name + of the phonecall. But this customer keeps the same email. +- | + This time OpenERP should detect that this customer already exists in the + partner base and I check that in the wizard, proposes me to link to this existing + partner instead of creating another one. +- | + I confirm the conversion wizard. +- | + And I check that the phonecall and the newly created business opportunity is linked + to the partner +- | + 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: '2010-04-20 00:00:00' + date_deadline: '2010-04-20 08:00:00' + 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' + rrule_type: weekly + state: open + +- + #This is not working for yaml +- | + I can jump to this meeting by "Meetings" shortcut from my phonecall's form view +- + +- | + 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: '2010-04-21 19:49:00' + name: Interview call + section_id: crm.section_sales_department + user_id: base.user_root +- | + I click on "Schedule" button of this wizard. +- + !python {model: crm.phonecall2phonecall}: | + self.action_apply(cr, uid, [ref('crm_phonecall2phonecall_interviewcall0')], {'active_id': ref('crm_phonecall_interviewcall0')}) diff --git a/addons/crm/wizard/crm_opportunity_to_phonecall.py b/addons/crm/wizard/crm_opportunity_to_phonecall.py index 148ec3aec6e..ffe91a927d2 100644 --- a/addons/crm/wizard/crm_opportunity_to_phonecall.py +++ b/addons/crm/wizard/crm_opportunity_to_phonecall.py @@ -29,10 +29,10 @@ class crm_opportunity2phonecall(osv.osv_memory): _description = 'Opportunity to Phonecall' _columns = { - 'name' : fields.char('Call summary', size=64, required=True, select=1), - 'user_id' : fields.many2one('res.users', "Assign To"), - 'date': fields.datetime('Date' , required=True), - 'section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'name' : fields.char('Call summary', size=64, required=True, select=1), + 'user_id' : fields.many2one('res.users', "Assign To"), + 'date': fields.datetime('Date' , required=True), + 'section_id': fields.many2one('crm.case.section', 'Sales Team'), } def default_get(self, cr, uid, fields, context=None): @@ -46,7 +46,6 @@ class crm_opportunity2phonecall(osv.osv_memory): @return : default values of fields. """ - opp_obj = self.pool.get('crm.opportunity') record_ids = context and context.get('active_ids', []) or [] res = super(crm_opportunity2phonecall, self).default_get(cr, uid, fields, context=context) @@ -93,7 +92,7 @@ class crm_opportunity2phonecall(osv.osv_memory): data_obj = self.pool.get('ir.model.data') categ_id = mod_obj._get_id(cr, uid, 'crm', 'categ_phone1') categ_id = data_obj.browse(cr, uid, categ_id, context=context).res_id - + # 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') @@ -105,31 +104,32 @@ class crm_opportunity2phonecall(osv.osv_memory): for this in self.browse(cr, uid, ids, context=context): for opp in opp_obj.browse(cr, uid, record_ids, context=context): new_case = phonecall_obj.create(cr, uid, { - 'name' : opp.name, - 'case_id' : opp.id , - 'user_id' : this.user_id and this.user_id.id or False, - 'categ_id' : categ_id, - 'description' : opp.description or False, - 'date' : this.date, - 'section_id' : opp.section_id and opp.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, + 'name' : opp.name, + 'case_id' : opp.id , + 'user_id' : this.user_id and this.user_id.id or False, + 'categ_id' : categ_id, + 'description' : opp.description or False, + 'date' : this.date, + 'section_id' : opp.section_id and opp.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, 'opp_id': opp.id }, context=context) phonecall_obj.case_open(cr, uid, [new_case]) value = { - 'name': _('Phone Call'), - 'view_type': 'form', - 'view_mode': 'tree,form', - 'res_model': 'crm.phonecall', - 'res_id' : new_case, - 'views': [(id3, 'form'), (id2, 'tree'), (False, 'calendar'), (False, 'graph')], - 'type': 'ir.actions.act_window', + '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'), (False, 'graph')], + 'type': 'ir.actions.act_window', 'search_view_id': res['res_id'] } return value diff --git a/addons/document/__openerp__.py b/addons/document/__openerp__.py index 2ffb708738c..7626bd3c51b 100644 --- a/addons/document/__openerp__.py +++ b/addons/document/__openerp__.py @@ -46,6 +46,9 @@ 'report/document_report_view.xml' ], 'demo_xml': [ 'document_demo.xml',], + 'test': [ + 'test/document_test.yml', + ], 'installable': True, 'active': False, 'certificate': None, diff --git a/addons/document/document_directory.py b/addons/document/document_directory.py index c9c124cdfe0..19c4489132c 100644 --- a/addons/document/document_directory.py +++ b/addons/document/document_directory.py @@ -105,7 +105,11 @@ class document_directory(osv.osv): ] def name_get(self, cr, uid, ids, context={}): res = [] + all_ids = self.search(cr,uid,[]) for d in self.browse(cr, uid, ids, context=context): + if d.id not in all_ids: + continue + s = '' d2 = d while d2 and d2.parent_id: diff --git a/addons/document/test/document_test.yml b/addons/document/test/document_test.yml new file mode 100644 index 00000000000..fe3008d35da --- /dev/null +++ b/addons/document/test/document_test.yml @@ -0,0 +1,52 @@ +- | + In order to test the Document Management System In OpenERP. +- + In order to test behaviour of resource Directory I will make one resource Directory "Partner Labels" in OpenERP having type "Other Resources" and Directory mapped to object "Partner" +- + !record {model: 'document.directory', id: dir_partner_label}: + name : "Partner Labels" + storage_id : storage_default + type : ressource + content_ids: + - name: "Label" + report_id : base.res_partner_address_report +- + Assign "res.partner" object to ressource_type_id. +- + !python {model: document.directory}: | + ids = self.pool.get('ir.model').search(cr, uid, [('model','=','res.partner')]) + id = self.write(cr, uid, [ref("dir_partner_label")], {'ressource_type_id' : ids[0]}, context) +- + In order to check static directory in OpenERP which is the real directory just like system's local folders, + First I create a directory in OpenERP named "Directory 1" with storage as "Default File storage" and type as "Static Directory" +- + !record {model: 'document.directory', id: directory_1}: + name : "Directory 1" + storage_id : storage_default + type : directory +- + In order to make a directory hierarchy in OpenERP I will make other static directory "Directory 2" and I put its Parent Item as "Directory 1", + So I can see the directory hierarchy in OpenERP's client like :- Directory1 -> Directory2 +- + !record {model: 'document.directory', id: directory_2}: + name : "Directory 2" + storage_id : storage_default + type : directory + parent_id : directory_1 +- + I am create a one Document Attachment name "My document" and select "Directory 2" as its Directory, + And in order to put a File content. +- + When I am creating the document then "Resource Title" is filled automatic with "My document". +- + !record {model: 'ir.attachment', id: document_1}: + name : "My document" + parent_id : directory_2 +- + Attach a pdf file in "My document" +- + !python {model: ir.attachment}: | + import tools + import base64 + file = open(tools.config['addons_path'] + '/document/test/partner.pdf') + id = self.write(cr, uid, [ref("document_1")], {'datas' : base64.encodestring(file.read())}, context) diff --git a/addons/document/test/partner.pdf b/addons/document/test/partner.pdf new file mode 100644 index 00000000000..1b1c7f0daac --- /dev/null +++ b/addons/document/test/partner.pdf @@ -0,0 +1,118 @@ +%PDF-1.3 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +% 'BasicFonts': class PDFDictionary +1 0 obj +% The standard fonts dictionary +<< /F1 2 0 R + /F2 3 0 R + /F3 4 0 R >> +endobj +% 'F1': class PDFType1Font +2 0 obj +% Font Helvetica +<< /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font >> +endobj +% 'F2': class PDFType1Font +3 0 obj +% Font Helvetica-Bold +<< /BaseFont /Helvetica-Bold + /Encoding /WinAnsiEncoding + /Name /F2 + /Subtype /Type1 + /Type /Font >> +endobj +% 'F3': class PDFType1Font +4 0 obj +% Font Times-Roman +<< /BaseFont /Times-Roman + /Encoding /WinAnsiEncoding + /Name /F3 + /Subtype /Type1 + /Type /Font >> +endobj +% 'Page1': class PDFPage +5 0 obj +% Page dictionary +<< /Contents 9 0 R + /MediaBox [ 0 + 0 + 841.8898 + 595.2756 ] + /Parent 8 0 R + /Resources << /Font 1 0 R + /ProcSet [ /PDF + /Text + /ImageB + /ImageC + /ImageI ] >> + /Rotate 0 + /Trans << >> + /Type /Page >> +endobj +% 'R6': class PDFCatalog +6 0 obj +% Document Root +<< /Outlines 10 0 R + /PageMode /UseNone + /Pages 8 0 R + /Type /Catalog >> +endobj +% 'R7': class PDFInfo +7 0 obj +<< /Author (Generated by OpenERP, Fabien Pinckaers) + /CreationDate (20100421145542) + /Keywords () + /Producer (ReportLab http://www.reportlab.com) + /Subject (\(unspecified\)) + /Title (Partner) >> +endobj +% 'R8': class PDFPages +8 0 obj +% page tree +<< /Count 1 + /Kids [ 5 0 R ] + /Type /Pages >> +endobj +% 'R9': class PDFStream +9 0 obj +% page stream +<< /Filter [ /ASCII85Decode + /FlateDecode ] + /Length 524 >> +stream +Gat=(?#P3ie[>S,B2ME\)S7:@oo6@nF8`I+h##OY3a-n#Qm!>5jiD.9pQ@E1#Xj$=)27)F3RmD%fbqZh,T`gJd0/,?A3`0:_VVm`"l`>oOf9p&HGF7>WCGVJoD2&_+c#BDb)/&0>>rL5@]KY$9YOAqZHTJq8k]!o+?4a5\-KbB#NYJC'`~>endstream + +endobj +% 'R10': class PDFOutlines +10 0 obj +<< /Count 0 + /Type /Outlines >> +endobj +xref +0 11 +0000000000 65535 f +0000000113 00000 n +0000000233 00000 n +0000000398 00000 n +0000000573 00000 n +0000000740 00000 n +0000001017 00000 n +0000001152 00000 n +0000001395 00000 n +0000001500 00000 n +0000002169 00000 n +trailer +<< /ID + % ReportLab generated PDF document -- digest (http://www.reportlab.com) + [(\210\344\006bE\230CUUi\010[\)Qif) (\210\344\006bE\230CUUi\010[\)Qif)] + + /Info 7 0 R + /Root 6 0 R + /Size 11 >> +startxref +2221 +%%EOF diff --git a/addons/document_ftp/__openerp__.py b/addons/document_ftp/__openerp__.py index b4c6b2c0b71..7fcdfd8d0d5 100644 --- a/addons/document_ftp/__openerp__.py +++ b/addons/document_ftp/__openerp__.py @@ -37,6 +37,9 @@ 'security/ir.model.access.csv' ], 'demo_xml': [], + 'test': [ + 'test/document_ftp_test.yml', + ], 'installable': True, 'active': False, 'certificate': None, diff --git a/addons/document_ftp/test/document_ftp_test.yml b/addons/document_ftp/test/document_ftp_test.yml new file mode 100644 index 00000000000..f7c4abb0cdf --- /dev/null +++ b/addons/document_ftp/test/document_ftp_test.yml @@ -0,0 +1,87 @@ +- | + In order to test the document_ftp module in OpenERP, I will try different operation on the FTP interface, and check their impacts on OpenERP's documents and vice-versa. +- + In order to test behaviour of resource Directory I will make one resource Directory "Labels" in OpenERP having type "Other Resources" and Directory mapped to object "Partner" +- + !record {model: 'document.directory', id: dir_label}: + name : "Labels" + storage_id : document.storage_default + type : ressource + content_ids: + - name: "Label" + report_id : base.res_partner_address_report +- + Assign "res.partner" object to ressource_type_id. +- + !python {model: document.directory}: | + ids = self.pool.get('ir.model').search(cr, uid, [('model','=','res.partner')]) + id = self.write(cr, uid, [ref("dir_label")], {'ressource_type_id' : ids[0]}, context) +- + In order to check static directory in OpenERP which is the real directory just like system's local folders, + First I create a directory in OpenERP named "Directory 1" with storage as "Default File storage" and type as "Static Directory" +- + !record {model: 'document.directory', id: directory_file}: + name : "File" + storage_id : document.storage_default + type : directory +- + I am create a one Document name "Document" and select "File" as its Directory, +- + When I am creating the record then "Resource Title" is filled automatic with "Document". +- + !record {model: 'ir.attachment', id: document_1}: + name : "Document" + parent_id : directory_file +- + In order to connect FTP server and set "File" path. + I create one directory "New" in "File" directory from FTP and check its effect in OpenERP +- + Also Rename the directory name "New" to "New Directory". +- + Remove directory "New Directory" and remove file "Document". +- + !python {model: ir.attachment}: | + from ftplib import FTP + from tools.misc import detect_ip_addr + from tools import config + ftp = FTP() + if detect_ip_addr: + host = config.get('ftp_server_host', detect_ip_addr()) + else: + host = config.get('ftp_server_host', '127.0.0.1') + port = config.get('ftp_server_port','8021') + ftp.connect(host,port) + user = self.pool.get('res.users').read(cr, uid, uid, context) + ftp.login(user.get('login',''),user.get('password','')) + ftp.cwd("/" + cr.dbname+"/Documents/File/") + ftp.mkd("New") + ftp.rename('New','New Directory') + ftp.cwd("/" + cr.dbname+"/Documents/File/") + ftp.rmd('New Directory') + ftp.delete('Document') + ftp.quit() +- + In order to check directory created from FTP is working perfectly +- + Now I will test the same for Resource directory which is mapped with OpenERP object. + When you open this directory from FTP clients, it displays each records of mapped resource object as directory. +- + Now I test FTP client and Open the "Labels" Directory to check Resource Directory in FTP. + I can see that all Label of OpenERP are shown as children of "Labels" in FTP client as Directories +- + !python {model: ir.attachment}: | + from ftplib import FTP + from tools.misc import detect_ip_addr + from tools import config + ftp = FTP() + if detect_ip_addr: + host = config.get('ftp_server_host', detect_ip_addr()) + else: + host = config.get('ftp_server_host', '127.0.0.1') + port = config.get('ftp_server_port','8021') + ftp.connect(host,port) + user = self.pool.get('res.users').read(cr, uid, uid, context) + ftp.login(user.get('login',''),user.get('password','')) + ftp.cwd("/" + cr.dbname+"/Documents/Labels/") +- + I make sure that I Open Labels Directory successfully. diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py index 611b7c178fb..3639decf3dc 100644 --- a/addons/fetchmail/fetchmail.py +++ b/addons/fetchmail/fetchmail.py @@ -137,7 +137,8 @@ class email_server(osv.osv): ('imap','IMAP Server'), ],'State', select=True, readonly=False), 'is_ssl':fields.boolean('SSL ?', required=False), - 'date': fields.date('Date'), + 'attach':fields.boolean('Add Attachments ?', required=False), + 'date': fields.date('Date', readonly=True, states={'draft':[('readonly',False)]}), 'user' : fields.char('User Name', size=256, required=True, readonly=True, states={'draft':[('readonly',False)]}), 'password' : fields.char('Password', size=1024, invisible=True, required=True, readonly=True, states={'draft':[('readonly',False)]}), 'note': fields.text('Description'), @@ -292,17 +293,18 @@ class email_server(osv.osv): else: logger.notifyChannel('imap', netsvc.LOG_WARNING, 'method def message_new is not define in model %s' % (model_pool._name)) return False - -# for attactment in attachents or []: -# data_attach = { -# 'name': attactment, -# 'datas':binascii.b2a_base64(str(attachents.get(attactment))), -# 'datas_fname': attactment, -# 'description': 'Mail attachment', -# 'res_model': server.object_id.model, -# 'res_id': res_id, -# } -# self.pool.get('ir.attachment').create(cr, uid, data_attach) + + if server.attach: + for attactment in attachents or []: + data_attach = { + 'name': attactment, + 'datas':binascii.b2a_base64(str(attachents.get(attactment))), + 'datas_fname': attactment, + 'description': 'Mail attachment', + 'res_model': server.object_id.model, + 'res_id': res_id, + } + self.pool.get('ir.attachment').create(cr, uid, data_attach) if server.action_id: action_pool = self.pool.get('ir.actions.server') @@ -319,10 +321,15 @@ class email_server(osv.osv): his_id = history_pool.create(cr, uid, res) return res_id - - def __fetch_mail(self, cr, uid, ids, context={}): - sendmail_thread = threading.Thread(target=self.fetch_mail, args=(cr, uid, ids)) - sendmail_thread.start() + + def set_draft(self, cr, uid, ids, context={}): + self.write(cr, uid, ids , {'state':'draft'}) + return True + + def button_fetch_mail(self, cr, uid, ids, context={}): + self.fetch_mail(cr, uid, ids) +# sendmail_thread = threading.Thread(target=self.fetch_mail, args=(cr, uid, ids)) +# sendmail_thread.start() return True def _fetch_mails(self, cr, uid, ids=False, context={}): diff --git a/addons/fetchmail/fetchmail_view.xml b/addons/fetchmail/fetchmail_view.xml index a3a8534b559..ea08706b62d 100644 --- a/addons/fetchmail/fetchmail_view.xml +++ b/addons/fetchmail/fetchmail_view.xml @@ -26,15 +26,15 @@ - - + + @@ -58,7 +58,8 @@ -