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 b3e45a33978..e4dea534b65 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -109,6 +109,7 @@ between mails and Open ERP.""", 'process/crm_configuration_process.xml', ], 'demo_xml': [ + 'test/test_crm_meeting.yml', 'crm_demo.xml', 'crm_claims_demo.xml', 'crm_fund_demo.xml', @@ -118,6 +119,13 @@ between mails and Open ERP.""", 'crm_opportunity_demo.xml', 'crm_phonecall_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_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/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/idea/__openerp__.py b/addons/idea/__openerp__.py index c5794346f4d..4730fd4637c 100644 --- a/addons/idea/__openerp__.py +++ b/addons/idea/__openerp__.py @@ -43,6 +43,7 @@ 'security/ir.model.access.csv', ], 'demo_xml': [], + 'test':['test/test_idea.yml'], 'installable': True, 'certificate': '0071515601309', } diff --git a/addons/idea/test/test_idea.yml b/addons/idea/test/test_idea.yml new file mode 100644 index 00000000000..c1ee6deb80f --- /dev/null +++ b/addons/idea/test/test_idea.yml @@ -0,0 +1,103 @@ +- | + In order to test the Idea module in OpenERP, + we will create a full flow, from the idea definition up to the votes and discussions on the idea. +- | + Given that I have an Idea category "Technical". +- + !record {model: idea.category, id: idea_category_technical0}: + name: Technical +- | + I create a New Idea of "Technical presentation for 1 hours in every day" and specify category "Technical". + +- + !record {model: idea.idea, id: idea_idea_0}: + category_id: idea_category_technical0 + description: I want that Technical presentation are arranged for 1 hours in every + day.\nso, on that presentation, we can know all things what improvement and development + are done in our company.\n\n\n\n\n + title: Technical presentation for 1 hours in every day + user_id: base.user_root + +- | + I check that idea on draft state. +- + !assert {model: idea.idea, id: idea_idea_0}: + - state == 'draft' + +- | + I open this idea by click on "Open" button. +- + !workflow {model: idea.idea, action: idea_open, ref: idea_idea_0} + +- | + In order to check voting statistics in real systems I will create 2 new Users "user1". +- + !record {model: res.users, id: res_users_user0}: + company_id: base.main_company + context_lang: en_US + login: user1 + name: user1 + password: user1 +- | + And I will also create user2. +- + !record {model: res.users, id: res_users_user1}: + company_id: base.main_company + context_lang: en_US + login: user2 + name: user2 + password: user2 + +- | + In order to post vote I connect as user1 and open the idea page + I click on "Vote" wizard and vote the idea as "Normal" +- + !record {model: idea.post.vote, id: idea_post_vote_0}: + vote: 50 +- | + Now I click on "Post Vote" button of wizard. +- + !python {model: idea.post.vote}: | + uid = ref('res_users_user0') + self.do_vote(cr, uid, [ref("idea_post_vote_0")], {'active_id': ref('idea_idea_0')}) + +- | + To add other vote I connect as user2 and open the idea page + I click on "Vote" wizard and vote the idea as "Very Good" + +- + !record {model: idea.post.vote, id: idea_post_vote_1}: + vote: 100 + +- | + I click on "Post Vote" button of this wizard. +- + !python {model: idea.post.vote}: | + uid = ref('res_users_user1') + self.do_vote(cr, uid, [ref("idea_post_vote_1")], {'active_id': ref('idea_idea_0')}) + +- | + I can see that the Average score changed in "Average score" field with value 75 +- + !record {model: idea.idea, id: idea_idea_0}: + vote_avg: 75 + +- | + I put one comment "We can learn many things from technical presentation" for the idea. +- + !record {model: idea.idea, id: idea.idea_idea_0}: + comment_ids: + - content: We can learn many things from technical presentation + idea_id: idea.idea_idea_0 + user_id: res_users_user1 +- | + I connect as Manager and close this idea by click on "Close" button. +- + !workflow {model: idea.idea, action: idea_close, ref: idea_idea_0} + +- | + I check that the idea's state is now Accepted +- + !assert {model: idea.idea, id: idea_idea_0}: + - state == 'close' + \ No newline at end of file diff --git a/addons/lunch/__openerp__.py b/addons/lunch/__openerp__.py index 782d5f49df9..efde2f16e61 100644 --- a/addons/lunch/__openerp__.py +++ b/addons/lunch/__openerp__.py @@ -47,7 +47,10 @@ 'lunch_report.xml', #'process/lunch_process.xml' ], - "demo_xml": ['lunch_demo.xml'], + "demo_xml": ['lunch_demo.xml', + ], + "test": ['test/test_lunch.yml' + ], "installable": True, } diff --git a/addons/lunch/lunch.py b/addons/lunch/lunch.py index 207d7ebe940..a986dc25953 100644 --- a/addons/lunch/lunch.py +++ b/addons/lunch/lunch.py @@ -42,21 +42,9 @@ class lunch_product(osv.osv): _name = 'lunch.product' _description = "Lunch Product" - def _category_name_get(self, cr, uid, context={}): - - """ Get category name - @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""" - - obj = self.pool.get('lunch.category') - cat_ids = obj.search(cr, uid, []) - res = obj.read(cr, uid, cat_ids, ['name', 'category']) - return [(str(r['id']), r['name']) for r in res]+ [('0','')] - _columns = { 'name': fields.char('Name', size=50, required=True), - 'category_id': fields.selection(_category_name_get, 'Category', size=32), + 'category_id': fields.many2one('lunch.category', 'Category'), 'description': fields.char('Description', size=128, required=False), 'price': fields.float('Price', digits=(16,2)), 'active': fields.boolean('Active'), diff --git a/addons/lunch/lunch_view.xml b/addons/lunch/lunch_view.xml index 962330c1ea2..ab3d6792683 100644 --- a/addons/lunch/lunch_view.xml +++ b/addons/lunch/lunch_view.xml @@ -195,7 +195,7 @@ - + diff --git a/addons/lunch/test/test_lunch.yml b/addons/lunch/test/test_lunch.yml new file mode 100644 index 00000000000..97ed41b2abc --- /dev/null +++ b/addons/lunch/test/test_lunch.yml @@ -0,0 +1,130 @@ +- | + In order to test the Lunch module in OpenERP, + I will create one lunch order and then check the effect on cashboxes and cashmoves + +- | + Given that I have a category of lunch products "Burger". +- + !record {model: lunch.category, id: lunch_category_burger0}: + name: Burger +- | + Given that I have a product "Club1" in this category with a price of "2.75". + +- + !record {model: lunch.product, id: lunch_product_club1}: + category_id: lunch_category_burger0 + name: Club1 + price: 2.75 +- | + Given that I have a cashbox "Employee Cashbox" +- + !record {model: lunch.cashbox, id: lunch_cashbox_cashbox0}: + manager: base.user_root + name: Employee Cashbox +- | + I create a lunch order "LU001" for the "Club1" product +- | + When I select the product "club1", the price of 2.75 is automatically proposed +- + !record {model: lunch.order, id: lunch_order_0}: + date: '2010-04-19' + product: 'lunch_product_club1' + price: 2.75 + user_id: base.user_root + +- | + I check that lunch order is on draft state after having created it. +- + !assert {model: lunch.order, id: lunch_order_0}: + - state == 'draft' +- | + I confirm the order "LU001" using the "Confirm Order" wizard. +- + !record {model: lunch.order.confirm, id: lunch_order_confirm_0}: + confirm_cashbox: 'lunch_cashbox_cashbox0' +- + I click on "Confirm Order" button of this wizard. +- + !python {model: lunch.order.confirm}: | + self.confirm(cr, uid, [ref('lunch_order_confirm_0')], {'active_ids': [ref('lunch_order_0')]}) + +- | + I check that the Cash Moves have been generated with the right box + name +- + !assert {model: lunch.order, id: lunch_order_0}: + - cashmove.id != False + +- | + I check that the Total on the "Employee Cashbox" is -2.75 + +- + !assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}: + - sum_remain == -2.75 + +- | + I create a new lunch order "LU002" for the "Club1" product, at another date. +- + !record {model: lunch.order, id: lunch_order_1}: + date: '2010-04-22' + product: 'lunch_product_club1' + price: 2.75 + user_id: base.user_root + +- | + I confirm this order.open wizard and select "Employee Cashbox". +- + !record {model: lunch.order.confirm, id: lunch_order_confirm_1}: + confirm_cashbox: 'lunch_cashbox_cashbox0' +- | + Now I click on "Confirm Order" button of this wizard. +- + !python {model: lunch.order.confirm}: | + self.confirm(cr, uid, [ref('lunch_order_confirm_1')], {'active_ids': [ref('lunch_order_1')]}) + +- | + I check that the Total on the "Employee Cashbox" is -5.50 +- + !assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}: + - sum_remain == -5.50 +- | + I reset the "Employee Cashbox" to zero using the "Set CashBox to Zero" wizard. +- + !record {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}: + {} +- + Now click on "Set to Zero" button of this wizard. +- + !python {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}: | + self.set_to_zero(cr, uid, [ref('lunch_cashbox_clean_0')], {'active_ids': [ref('lunch_cashbox_cashbox0')]}) + +- | + I check that the Total on the "Employee Cashbox" is 0.0 +- + !assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}: + - sum_remain == 0.00 + +- | + I cancel the order "LU002" +- + !record {model: lunch.order.cancel, id: lunch_order_cancel_0}: + {} +- | + I click on "Yes" button of this wizard for cancel order. + +- + !python {model: lunch.order.cancel}: | + self.cancel(cr, uid, [ref('lunch_order_cancel_0')], {'active_ids': [ref('lunch_order_1')]}) + +- | + I test that the Cash Moves revord have been removed for the order LU002. +- + !assert {model: lunch.order, id: lunch_order_1}: + - cashmove.id == False + +- | + I check that the Total on the "Employee Cashbox" is -2.75 +- + !assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}: + - sum_remain == -2.75 + \ No newline at end of file diff --git a/addons/olap/__openerp__.py b/addons/olap/__openerp__.py index bdca188a08f..3a9f8f2c794 100644 --- a/addons/olap/__openerp__.py +++ b/addons/olap/__openerp__.py @@ -46,8 +46,8 @@ "data/olap_security.xml", 'security/ir.model.access.csv' ], - "demo_xml" : ["data/olap_demo.xml", - "test/olap_test00.yml"], + "demo_xml" : ["data/olap_demo.xml"], + "test" : ['test/olap_test00.yml'], "active": False, "installable": True } diff --git a/addons/olap/wizard/olap_load_column.py b/addons/olap/wizard/olap_load_column.py index 008fd9a150c..65517626d62 100644 --- a/addons/olap/wizard/olap_load_column.py +++ b/addons/olap/wizard/olap_load_column.py @@ -40,7 +40,6 @@ class olap_load_column(osv.osv_memory): model_data_ids = self.pool.get('ir.model.data').search(cr, uid, \ [('model', '=', 'ir.ui.view'), \ ('name', '=', 'view_olap_database_columns_form')], context={}) - print "model_ids", model_data_ids resource_id = self.pool.get('ir.model.data').read(cr, uid, \ model_data_ids, fields=['res_id'])[0]['res_id'] return { diff --git a/addons/thunderbird/__init__.py b/addons/thunderbird/__init__.py index 5b7582a98f0..4ab5861f126 100644 --- a/addons/thunderbird/__init__.py +++ b/addons/thunderbird/__init__.py @@ -47,4 +47,4 @@ ############################################################################## import partner - +import installer diff --git a/addons/thunderbird/__openerp__.py b/addons/thunderbird/__openerp__.py index 2cb470bf886..5e60f6508cc 100644 --- a/addons/thunderbird/__openerp__.py +++ b/addons/thunderbird/__openerp__.py @@ -39,7 +39,8 @@ Select a section for which you want to create case.''', "init_xml" : [], "demo_xml" : [], - "update_xml" : ['security/ir.model.access.csv'], + "update_xml" : ['thunderbird_installer.xml', + 'security/ir.model.access.csv'], "active": False, "installable": True } diff --git a/addons/thunderbird/installer.py b/addons/thunderbird/installer.py new file mode 100644 index 00000000000..69576aa2a46 --- /dev/null +++ b/addons/thunderbird/installer.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import fields +from osv import osv +from tools import config + +import base64 + +class thunderbird_installer(osv.osv_memory): + _name = 'thunderbird.installer' + _inherit = 'res.config.installer' + + def process_plugin(self, cr, uid, ids, context): + """ + Default Attach Thunderbird Plug-in File. + """ + data = {} + file = open(config['addons_path'] + "/thunderbird/plugin/tiny_plugin-2.0.xpi", 'r') + data['plugin_file'] = base64.encodestring(file.read()) + self.write(cr, uid, ids, data) + return False + + _columns = { + 'name':fields.char('File name', size=34, required=True, help='Save Thunderbird plugin file.'), + 'thunderbird':fields.boolean('Thunderbird Module ', help="Allows you to select an object that you’d like to add to your email and its attachments."), + 'plugin_file':fields.binary('Thunderbird Plug-in', readonly=True, help="Thunderbird plug-in file. Save as this file and install this plug-in in thunderbir."), + + } + _defaults = { + 'thunderbird' : True, + 'name' : 'tiny_plugin-2.0.xpi', + } + +thunderbird_installer() diff --git a/addons/thunderbird/partner/partner.py b/addons/thunderbird/partner/partner.py index 3d678289988..3aa190090a4 100644 --- a/addons/thunderbird/partner/partner.py +++ b/addons/thunderbird/partner/partner.py @@ -92,9 +92,9 @@ class tinythunderbird_partner(osv.osv): partner=add_obj.read(cr,user,partner_ids,['partner_id']) if partner: dictcreate.update({'partner_id':partner[0]['partner_id'][0]}) - search_id = self.pool.get('res.request.link').search(cr,user,[('object','=',dictcreate['ref'].split(',')[0])]) - if not search_id: - create_link_id = self.pool.get('res.request.link').create(cr,user,{'name':dictcreate['ref'].split(',')[0],'object':dictcreate['ref'].split(',')[0]}) +# search_id = self.pool.get('res.request.link').search(cr,user,[('object','=',dictcreate['ref'].split(',')[0])]) +# if not search_id: +# create_link_id = self.pool.get('res.request.link').create(cr,user,{'name':dictcreate['ref'].split(',')[0],'object':dictcreate['ref'].split(',')[0]}) create_id = self.pool.get(dictcreate.get('object','crm.case')).create(cr, user, dictcreate) cases=case_pool.browse(cr,user,[create_id]) case_pool._history(cr, user, cases, _('Archive'), history=True, email=False) @@ -162,12 +162,15 @@ class tinythunderbird_partner(osv.osv): dictcreate = dict(vals) datas = [dictcreate['datas']] name = [dictcreate['name']] + f_name = [dictcreate['datas_fname']] if(dictcreate['datas'].__contains__(',')): name = dictcreate['name'].split(',') datas = dictcreate['datas'].split(',') + f_name = dictcreate['datas_fname'].split(',') for i in range(0,datas.__len__()): dictcreate['name'] = name[i] dictcreate['datas'] = datas[i] + dictcreate['datas_fname'] = f_name[i] create_id = self.pool.get('ir.attachment').create(cr,user,dictcreate) return 0 diff --git a/addons/thunderbird/plugin/tiny_plugin-2.0.xpi b/addons/thunderbird/plugin/tiny_plugin-2.0.xpi index 1ec2f9daa0c..ad92876d570 100644 Binary files a/addons/thunderbird/plugin/tiny_plugin-2.0.xpi and b/addons/thunderbird/plugin/tiny_plugin-2.0.xpi differ diff --git a/addons/thunderbird/thunderbird_installer.xml b/addons/thunderbird/thunderbird_installer.xml new file mode 100644 index 00000000000..bd19a780456 --- /dev/null +++ b/addons/thunderbird/thunderbird_installer.xml @@ -0,0 +1,103 @@ + + + + + thunderbird.installer.view + thunderbird.installer + form + + + + + Thunderbird Module Installation + + + Configure Thunderbird Module + + + This module is required for the thuderbird plug-in to work properly.This allows you to select an object that you had like to add to your email and its attachments. You can select a partner, a task, a project, an analytical account, or any other object and attach selected mail as .eml file in attachment of selected record. + + + + + + + + +