diff options
| author | Thibault Francois <tfr@openerp.com> | 2010-11-12 14:44:40 +0100 |
|---|---|---|
| committer | Thibault Francois <tfr@openerp.com> | 2010-11-12 14:44:40 +0100 |
| commit | cd2af4bb80ed730f7e6ec6c6c0c21dcdf39e15f5 (patch) | |
| tree | a05146180ce42b8aff18bd35e4bfc50a360004ea | |
| parent | b82ad6d02201a832152dc3998d75477d579a8d8d (diff) | |
| parent | 8ad87d0d946ecc5fcfc75f665409828921d2299b (diff) | |
[FIX,IMP] addons1 : 16 Bugs fix
Plugin improvement
Demo user has user right
crm leads logs stages changes
bzr revid: tfr@openerp.com-20101112134440-drbjwz4in82irkav
163 files changed, 2563 insertions, 1075 deletions
diff --git a/addons/account/report/account_voucher_print.py b/addons/account/report/account_voucher_print.py index 44587b3e689..a174a6ad680 100644 --- a/addons/account/report/account_voucher_print.py +++ b/addons/account/report/account_voucher_print.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/account/test/account_use_model.yml b/addons/account/test/account_use_model.yml index 4eb03a13026..ddb18c1a7d4 100644 --- a/addons/account/test/account_use_model.yml +++ b/addons/account/test/account_use_model.yml @@ -10,6 +10,7 @@ name: test1 sequence: 0.0 quantity: 0.0 + partner_id: base.res_partner_3 name: My Test Model - diff --git a/addons/account_coda/wizard/account_coda_import.py b/addons/account_coda/wizard/account_coda_import.py index b3c34efc5a5..a52528e2fa5 100644 --- a/addons/account_coda/wizard/account_coda_import.py +++ b/addons/account_coda/wizard/account_coda_import.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/account_payment/wizard/account_payment_order.py b/addons/account_payment/wizard/account_payment_order.py index aaec72e37f7..ef603a48f62 100644 --- a/addons/account_payment/wizard/account_payment_order.py +++ b/addons/account_payment/wizard/account_payment_order.py @@ -93,7 +93,6 @@ class payment_order_create(osv.osv_memory): return {} def search_entries(self, cr, uid, ids, context=None): - order_obj = self.pool.get('payment.order') line_obj = self.pool.get('account.move.line') mod_obj = self.pool.get('ir.model.data') if context is None: diff --git a/addons/audittrail/audittrail_view.xml b/addons/audittrail/audittrail_view.xml index 5fdcfcd5558..aee308785a8 100644 --- a/addons/audittrail/audittrail_view.xml +++ b/addons/audittrail/audittrail_view.xml @@ -152,7 +152,7 @@ <field name="res_model">audittrail.log</field> <field name="view_type">form</field> </record> - <menuitem name="Logs" id="menu_action_audittrail_log_tree" + <menuitem name="Audit Logs" id="menu_action_audittrail_log_tree" action="action_audittrail_log_tree" parent="base.menu_audit" /> </data> diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index c3aa7bb8720..ce5f7cfff8e 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -399,7 +399,7 @@ property or property parameter."), res = None def ics_datetime(idate, short=False): if idate: - if short: + if short or len(idate)<=10: return date.fromtimestamp(time.mktime(time.strptime(idate, '%Y-%m-%d'))) else: return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S') @@ -454,16 +454,16 @@ property or property parameter."), if interval == 'minutes': delta = timedelta(minutes=duration) trigger.value = delta - # Compute other details valarm.add('DESCRIPTION').value = alarm_data['name'] or 'OpenERP' - + for attendee in event_obj.attendee_ids: attendee_add = event.add('attendee') attendee_add.params['CUTYPE'] = [str(attendee.cutype)] attendee_add.params['ROLE'] = [str(attendee.role)] attendee_add.params['RSVP'] = [str(attendee.rsvp)] attendee_add.value = 'MAILTO:' + (attendee.email or '') + res = cal.serialize() return res diff --git a/addons/base_module_quality/unit_test/__init__.py b/addons/base_module_quality/unit_test/__init__.py index f96719c920e..3c61be82974 100644 --- a/addons/base_module_quality/unit_test/__init__.py +++ b/addons/base_module_quality/unit_test/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_module_quality/unit_test/unit_test.py b/addons/base_module_quality/unit_test/unit_test.py index c92ba6ddeac..248f647310c 100644 --- a/addons/base_module_quality/unit_test/unit_test.py +++ b/addons/base_module_quality/unit_test/unit_test.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_module_record/wizard/base_module_record_data.py b/addons/base_module_record/wizard/base_module_record_data.py index 24cdfd9fe86..8071a01ab11 100644 --- a/addons/base_module_record/wizard/base_module_record_data.py +++ b/addons/base_module_record/wizard/base_module_record_data.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/About.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/About.py index 319a1d6703c..b31065ce37e 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/About.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/About.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/AddAttachment.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/AddAttachment.py index d42cb4614aa..4dbb28a30c0 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/AddAttachment.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/AddAttachment.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py index 7dc26c78505..730ce8efefb 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Change.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertBracesToField.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertBracesToField.py index d4e8b5855ff..59b7d32b529 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertBracesToField.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertBracesToField.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertFieldsToBraces.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertFieldsToBraces.py index 05a794410b6..d804405c990 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertFieldsToBraces.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ConvertFieldsToBraces.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py index 875fe210c03..e2720c1e803 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ExportToRML.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Expression.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Expression.py index 43531d10168..074a3bd020e 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Expression.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Expression.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py index 4e2f40889c9..cfe65d61022 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Fields.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/LoginTest.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/LoginTest.py index 507ec28efb8..dbd597e1f2d 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/LoginTest.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/LoginTest.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ModifyExistingReport.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ModifyExistingReport.py index cc1d30ba6b0..138513475bb 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ModifyExistingReport.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ModifyExistingReport.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/NewReport.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/NewReport.py index 06ba55275d5..0e4a18c3b10 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/NewReport.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/NewReport.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py index 4e26508f106..d8458be027d 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Repeatln.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py index fd8a874749d..896f3cfcac2 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/SendToServer.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py index 659357ef100..de67ea0abda 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/ServerParameter.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py index e1df582c1e5..54343d02d7f 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/Translation.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/__init__.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/__init__.py index af5e28965ce..d2192cd5ddd 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/__init__.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/__init__.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/compile_all.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/compile_all.py index 5a95c61ecae..acafd5f549e 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/compile_all.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/compile_all.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/__init__.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/__init__.py index b67392208fe..2a732da8226 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/__init__.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/actions.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/actions.py index 8faec4cb5aa..56a83159e4a 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/actions.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/actions.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/error.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/error.py index bb51a35caf1..a6cfe9215a3 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/error.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/error.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py index 2f5f5186828..db1f15b1fc5 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/functions.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/gui.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/gui.py index 4210f2afe1e..79f2ae370de 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/gui.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/gui.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py index 0e47ab627fb..dfcc78374c9 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/logreport.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/rpc.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/rpc.py index 446d00094b4..f211c6309f4 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/rpc.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/rpc.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tiny_socket.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tiny_socket.py index 38ed0073d68..415e4b3c91e 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tiny_socket.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tiny_socket.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py index e5fa0d9f9e7..8c9a8c9a1a8 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/lib/tools.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py index 730d5b3d33b..fa7874cff45 100644 --- a/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py +++ b/addons/base_report_designer/plugin/openerp_report_designer/bin/script/modify.py @@ -30,16 +30,16 @@ # Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>). # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # diff --git a/addons/base_report_designer/wizard/base_report_designer_modify.py b/addons/base_report_designer/wizard/base_report_designer_modify.py index e65a386a3f8..ab942b6037a 100644 --- a/addons/base_report_designer/wizard/base_report_designer_modify.py +++ b/addons/base_report_designer/wizard/base_report_designer_modify.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/base_synchro/base_synchro_view.xml b/addons/base_synchro/base_synchro_view.xml index 66fbaf7ec82..f161d6c31ea 100755 --- a/addons/base_synchro/base_synchro_view.xml +++ b/addons/base_synchro/base_synchro_view.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - + <menuitem id="synch_config" name="Synchronization" parent="base.menu_config" sequence="30"/> <record id="view_transfer_line_tree" model="ir.ui.view"> <field name="name">base.synchro.obj.line.tree</field> <field name="model">base.synchro.obj.line</field> @@ -190,13 +190,13 @@ </record> <record id="action_base_synchro_server_tree" model="ir.actions.act_window"> - <field name="name">Synchronized Servers</field> + <field name="name">Servers to be synchronized</field> <field name="type">ir.actions.act_window</field> <field name="res_model">base.synchro.server</field> <field name="view_type">form</field> </record> - <menuitem action="action_base_synchro_server_tree" id="synchro_server_tree_menu_id" parent="base_synchro.next_id_63"/> + <menuitem action="action_base_synchro_server_tree" id="synchro_server_tree_menu_id" parent="base_synchro.synch_config"/> <!--view_base_synchro_server end --> diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py index b735d853025..70671507b01 100644 --- a/addons/caldav/caldav_node.py +++ b/addons/caldav/caldav_node.py @@ -19,17 +19,15 @@ # ############################################################################## -import time from document_webdav import nodes -from document.nodes import _str2time +from document.nodes import _str2time, nodefd_static import logging -import StringIO from orm_utils import get_last_modified try: - from tools.dict_tools import dict_merge, dict_merge2 + from tools.dict_tools import dict_merge2 except ImportError: - from document.dict_tools import dict_merge, dict_merge2 + from document.dict_tools import dict_merge2 # TODO: implement DAV-aware errors, inherit from IOError @@ -381,6 +379,9 @@ class node_calendar(nodes.node_class): res.append(child._get_caldav_calendar_data(cr)) return res + def open_data(self, cr, mode): + return nodefd_static(self, cr, mode) + def _get_caldav_calendar_description(self, cr): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') @@ -389,7 +390,7 @@ class node_calendar(nodes.node_class): try: calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx) return calendar.description or calendar.name - except Exception, e: + except Exception: return None def _get_dav_supported_report_set(self, cr): @@ -458,14 +459,10 @@ class res_node_calendar(nodes.node_class): self.model = res_model self.res_id = res_id - def open(self, cr, mode=False): - if self.type in ('collection','database'): - return False - s = StringIO.StringIO(self.get_data(cr)) - s.name = self - return s + def open_data(self, cr, mode): + return nodefd_static(self, cr, mode) - def get_data(self, cr, fil_obj = None): + def get_data(self, cr, fil_obj=None): uid = self.context.uid calendar_obj = self.context._dirobj.pool.get('basic.calendar') context = self.context.context.copy() diff --git a/addons/caldav/caldav_setup.xml b/addons/caldav/caldav_setup.xml index c33edbc75f7..e2e9d7eae5a 100644 --- a/addons/caldav/caldav_setup.xml +++ b/addons/caldav/caldav_setup.xml @@ -6,7 +6,7 @@ <field name="domain">[]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field name="storage_id" ref="document.storage_default"/> <field name="type">directory</field> @@ -17,6 +17,7 @@ <field name="domain">[]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_calendars0"/> <field name="type">directory</field> @@ -24,10 +25,10 @@ <field name="name">resources</field> </record> <record id="document_directory_uids0" model="document.directory"> - <field name="domain">[]</field> + <field name="domain">[('id','=',uid)]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_calendars0"/> <field name="type">ressource</field> @@ -36,9 +37,10 @@ <field name="name">__uids__</field> </record> <record id="document_directory_users0" model="document.directory"> - <field name="domain">[]</field> + <field name="domain">[('id','=',uid)]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> + <field name="user_id" eval="False"/> <field name="resource_field" ref="base.field_res_users_login"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_calendars0"/> @@ -56,7 +58,7 @@ <record id="document_directory_c0" model="document.directory"> <field name="domain">[]</field> <field eval="1" name="resource_find_all"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_users0"/> <field name="storage_id" ref="document.storage_default"/> diff --git a/addons/caldav/caldav_view.xml b/addons/caldav/caldav_view.xml index 6238ee1441d..1081cb16a09 100644 --- a/addons/caldav/caldav_view.xml +++ b/addons/caldav/caldav_view.xml @@ -4,12 +4,16 @@ <record model="ir.ui.view" id="view_calendar_collection_form"> <field name="name">Calendar Collections : Form</field> <field name="model">document.directory</field> + <field name="priority">40</field> <field name="type">form</field> <field name="arch" type="xml"> <form string="Calendar Collections"> <field name="name" select="1" colspan="4"/> <field name="user_id"/> <field name="parent_id"/> + <field name="type"/> + <field name="calendar_collection"/> + <field name="storage_id"/> <field name="calendar_ids" colspan="4" nolabel="1"/> </form> </field> @@ -19,12 +23,17 @@ <field name="name">Calendar Collections : Tree</field> <field name="model">document.directory</field> <field name="type">tree</field> + <field name="priority">40</field> <field name="arch" type="xml"> <tree string="Calendar Collections" toolbar="1"> <field name="name"/> + <field name="parent_id"/> <field name="user_id"/> <field name="create_date"/> <field name="write_date"/> + <field name="type"/> + <field name="calendar_collection"/> + <field name="storage_id"/> </tree> </field> </record> @@ -125,8 +134,10 @@ <field name="name"/> <field name="type"/> <field name="user_id"/> - <field name="create_date"/> - <field name="write_date"/> + <field name="collection_id" required="1"/> + <field name="has_webcal" groups="base.group_extended" /> + <field name="calendar_color" groups="base.group_extended" /> + <field name="calendar_order" groups="base.group_extended" /> </tree> </field> </record> diff --git a/addons/crm/crm.py b/addons/crm/crm.py index c809857de66..d54f82af52c 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -201,7 +201,7 @@ class crm_case(object): if stage.on_change: data.update({'probability': stage.probability}) self.write(cr, uid, [case.id], data, context=context) - return True + return prev_stage def onchange_partner_id(self, cr, uid, ids, part, email=False): """This function returns value of partner address based on partner diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 6a113a42c2a..f40d4d627df 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -119,7 +119,7 @@ class crm_lead(crm_case, osv.osv): # Lead fields 'categ_id': fields.many2one('crm.case.categ', 'Category', \ - domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.project.bug')]"), + domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]"), 'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \ domain="['|',('section_id','=',section_id),('section_id','=',False)]"), 'channel_id': fields.many2one('res.partner.canal', 'Channel'), @@ -286,11 +286,31 @@ class crm_lead(crm_case, osv.osv): stage = super(crm_lead, self).stage_next(cr, uid, ids, context) if stage: stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage, context=context) + self.history(cr, uid, ids, _('Stage'), details=stage_obj.name) + for case in self.browse(cr, uid, ids, context=context): + if case.type == 'lead': + message = _("The stage of lead '%s' has been changed to '%s'.") % (case.name, case.stage_id.name) + elif case.type == 'opportunity': + message = _("The stage of opportunity '%s' has been changed to '%s'.") % (case.name, case.stage_id.name) + self.log(cr, uid, case.id, message) if stage_obj.on_change: data = {'probability': stage_obj.probability} self.write(cr, uid, ids, data) return stage - + + def stage_previous(self, cr, uid, ids, context=None): + stage = super(crm_lead, self).stage_previous(cr, uid, ids, context) + if stage: + stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage, context=context) + self.history(cr, uid, ids, _('Stage'), details=stage_obj.name) + for case in self.browse(cr, uid, ids, context=context): + if case.type == 'lead': + message = _("The stage of lead '%s' has been changed to '%s'.") % (case.name, case.stage_id.name) + elif case.type == 'opportunity': + message = _("The stage of opportunity '%s' has been changed to '%s'.") % (case.name, case.stage_id.name) + self.log(cr, uid, case.id, message) + return stage + def message_new(self, cr, uid, msg, context): """ Automatically calls when new email message arrives diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py index 4327052c36b..fc4d1235f29 100644 --- a/addons/crm/crm_meeting.py +++ b/addons/crm/crm_meeting.py @@ -133,6 +133,7 @@ class crm_meeting(crm_case, osv.osv): res = super(crm_meeting, self).case_open(cr, uid, ids, args) for (id, name) in self.name_get(cr, uid, ids): message = _("The meeting '%s' has been confirmed.") % name + id=base_calendar.base_calendar_id2real_id(id) self.log(cr, uid, id, message) return res diff --git a/addons/crm/crm_meeting_menu.xml b/addons/crm/crm_meeting_menu.xml index 73880da9523..2d26adbdb1c 100644 --- a/addons/crm/crm_meeting_menu.xml +++ b/addons/crm/crm_meeting_menu.xml @@ -9,6 +9,7 @@ src_model="res.partner" view_mode="calendar,tree,form,gantt" context="{'search_default_partner_id': active_id, 'default_duration': 4.0}" + domain="[('partner_id', '=', active_id)]" /> <record model="ir.actions.act_window" id="crm_case_categ_meet_create_partner"> diff --git a/addons/crm/crm_opportunity.py b/addons/crm/crm_opportunity.py index 9bd998d0f46..a09d7b39e4c 100644 --- a/addons/crm/crm_opportunity.py +++ b/addons/crm/crm_opportunity.py @@ -142,11 +142,11 @@ class crm_opportunity(osv.osv): @param uid: the current user’s ID for security checks, @param ids: List of stage’s IDs @stage_id: change state id on run time """ - if not stage_id: return {'value':{}} stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id, context) + if not stage.on_change: return {'value':{}} return {'value':{'probability': stage.probability}} diff --git a/addons/crm/security/crm_security.xml b/addons/crm/security/crm_security.xml index 1e25ecb5bdd..ab29f28d89b 100644 --- a/addons/crm/security/crm_security.xml +++ b/addons/crm/security/crm_security.xml @@ -34,6 +34,10 @@ <record model="ir.ui.menu" id="base.menu_base_config"> <field eval="[(4, ref('base.group_sale_manager'))]" name="groups_id"/> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('base.group_sale_salesman'))]"/> + </record> </data> </openerp> diff --git a/addons/crm/wizard/crm_partner_to_opportunity.py b/addons/crm/wizard/crm_partner_to_opportunity.py index 0df19df8eb7..84da9ea0613 100644 --- a/addons/crm/wizard/crm_partner_to_opportunity.py +++ b/addons/crm/wizard/crm_partner_to_opportunity.py @@ -84,7 +84,7 @@ class crm_partner2opportunity(osv.osv_memory): categ_obj = self.pool.get('crm.case.categ') - categ_ids = categ_obj.search(cr, uid, [('name','ilike','Part%')]) + categ_ids = categ_obj.search(cr, uid, [('object_id.model','=','crm.lead')]) case_obj = self.pool.get('crm.lead') opp_id = case_obj.create(cr, uid, { @@ -93,7 +93,7 @@ class crm_partner2opportunity(osv.osv_memory): 'probability' : make_opportunity_obj.probability, 'partner_id' : make_opportunity_obj.partner_id.id, 'partner_address_id' : address['default'], - 'categ_id' : categ_ids[0], + 'categ_id' : categ_ids and categ_ids[0] or '', 'state' :'draft', 'type': 'opportunity' }) diff --git a/addons/crm/wizard/crm_send_email.py b/addons/crm/wizard/crm_send_email.py index de4d616b67b..bd090c041b5 100644 --- a/addons/crm/wizard/crm_send_email.py +++ b/addons/crm/wizard/crm_send_email.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/crm/wizard/wizard_history_event.py b/addons/crm/wizard/wizard_history_event.py index 92e98c23dbb..50f30e12f90 100644 --- a/addons/crm/wizard/wizard_history_event.py +++ b/addons/crm/wizard/wizard_history_event.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml index 8175dd20da6..e2107f44501 100644 --- a/addons/crm_claim/crm_claim_view.xml +++ b/addons/crm_claim/crm_claim_view.xml @@ -111,7 +111,6 @@ <field name="section_id" widget="selection"/> <group colspan="2" col="4"> <field name="stage_id" - on_change="onchange_stage_id(stage_id)" domain="[('object_id.model', '=', 'crm.claim'), ('section_ids', '=', section_id)]" /> <button name="stage_previous" string="" type="object" icon="gtk-go-back" /> <button icon="gtk-go-forward" string="" name="stage_next" type="object"/> diff --git a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py index aaa26c438b6..d14759dc3a7 100644 --- a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py +++ b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/document/__openerp__.py b/addons/document/__openerp__.py index 5741a7223e0..5d0088579a1 100644 --- a/addons/document/__openerp__.py +++ b/addons/document/__openerp__.py @@ -22,7 +22,7 @@ { 'name': 'Integrated Document Management System', - 'version': '2.0', + 'version': '2.1', 'category': 'Generic Modules/Others', 'description': """This is a complete document management system: * User Authentication diff --git a/addons/document/content_index.py b/addons/document/content_index.py index df2b12b5456..6d49a29873f 100644 --- a/addons/document/content_index.py +++ b/addons/document/content_index.py @@ -71,8 +71,10 @@ class indexer(object): pass fp = open(realfile,'rb') - content2 = fp.read() - fp.close() + try: + content2 = fp.read() + finally: + fp.close() # The not-handled exception may be raised here return self._doIndexContent(content2) @@ -164,8 +166,10 @@ class contentIndex(object): os.close(fd) fp = Popen(['file','-b','--mime',fname], shell=False, stdout=PIPE).stdout - result = fp.read() - fp.close() + try: + result = fp.read() + finally: + fp.close() mime2 = result.split(';')[0] self.__logger.debug('File gave us: %s', mime2) # Note that the temporary file still exists now. diff --git a/addons/document/directory_report.py b/addons/document/directory_report.py index 657fd39d9a9..88a95a1705b 100644 --- a/addons/document/directory_report.py +++ b/addons/document/directory_report.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/document/doc/access_permissions.rst b/addons/document/doc/access_permissions.rst new file mode 100644 index 00000000000..2cdc45dadab --- /dev/null +++ b/addons/document/doc/access_permissions.rst @@ -0,0 +1,65 @@ +Access control in the Document Management system +================================================ + +The purpose is to let the DMS act as a real-life management system for +the file handling of some small business. +The key concept, there, is the separation of access according to users +and groups. + +Fact 1: Users, in general, must NOT see each other's documents, not even +their names (because they usually imply sensitive data, like eg. a doc: +"Acme Company's Patent 012356 about fooobars.odf" ) +Fact 2: Users, sometimes, fail to comprehend complex ACL schemes, so we +owe to keep things simple, a main principle applied all over the place. +Fact 3: our system has both statically placed files and directories, as +well as dynamic (aka "resources" in our terminology) nodes. + +We allow/limit the access based on 3 factors (fields): + - The "owner" field, which holds the user that created or "owns" the + file or directory. + - The "group_ids" field, on directories, which specifieds group-wise + access + - The "company_id" field, for multi-company access rules [1] + +[1] at multi-company setups, we may want the same file hierarchy to apply +to different companies, and also nodes to be company-specific in it. + +Principle of "owner" +---------------------- +Files or directories that have an empty "owner" field are public. All users +will be able to _read_ them. Only the OpenERP Administrator or specified +groups, however, will be able to modify them! +Files or directories that have an "owner" are private. Only their users will +be able to read or modify (including delete) them. +By default, all user's files are created with "owner" field set, thus private. + +Principle of "group_ids" +------------------------- +Directories that have any group ids set will only (apart from their owner) +allow members of these groups to read them. +Directories that are created into the above directories will initially inherit +(that is, copy) the group_ids of their parents, so that they also allow +access to the same users. + +Implementation note +--------------------- +Most of the principles are applied through record rules (see ir.rule object), +so an administrator can actually readjust them. +In order to have logical "areas" of folders, where different policies apply +(like group folders, personal areas), default values for directories' owners +and group_ids can be tuned (through the 'set default' functionality of +fields). + +Summary +-------- + +Table of permissions and behavior + +|| Type | Owner set | Groups set | Description || +|| Public | - | - | Public-readable folders, admin can write || +|| Group | - | X | Group can read, write, delete in them || +|| Group-read | X | X | Group can read[2], owner can write/delete || +|| Private | X | - | Only owner can read, write, delete in. || + +[2] hint: using a wide group, like "Internal users" at this setup creates the + effect of public-readable folders, with write permission to a non-admin user. diff --git a/addons/document/document.py b/addons/document/document.py index 470d67c582b..e3d810668b4 100644 --- a/addons/document/document.py +++ b/addons/document/document.py @@ -74,7 +74,7 @@ class document_file(osv.osv): 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), - 'res_model': fields.char('Attached Model', size=64, readonly=True), + 'res_model': fields.char('Attached Model', size=64, readonly=True, change_default=True), 'res_id': fields.integer('Attached ID', readonly=True), # If ir.attachment contained any data before document is installed, preserve @@ -86,7 +86,7 @@ class document_file(osv.osv): 'user_id': fields.many2one('res.users', 'Owner', select=1), # 'group_ids': fields.many2many('res.groups', 'document_group_rel', 'item_id', 'group_id', 'Groups'), # the directory id now is mandatory. It can still be computed automatically. - 'parent_id': fields.many2one('document.directory', 'Directory', select=1, required=True), + 'parent_id': fields.many2one('document.directory', 'Directory', select=1, required=True, change_default=True), 'index_content': fields.text('Indexed Content'), 'partner_id':fields.many2one('res.partner', 'Partner', select=1), 'file_size': fields.integer('File Size', required=True), @@ -245,7 +245,7 @@ class document_file(osv.osv): # files to be unlinked, update the db (safer to do first, can be # rolled back) and then unlink the files. The list wouldn't exist # after we discard the objects - + ids = self.search(cr, uid, [('id','in',ids)]) for f in self.browse(cr, uid, ids, context): # TODO: update the node cache par = f.parent_id diff --git a/addons/document/document_data.xml b/addons/document/document_data.xml index ef829b6e258..a4f546cbf83 100644 --- a/addons/document/document_data.xml +++ b/addons/document/document_data.xml @@ -16,13 +16,13 @@ <record model="document.directory" id="dir_root"> <field name="name">Documents</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="storage_id" ref="storage_default"/> <field name="ressource_id">0</field> </record> <record model="document.directory" id="dir_my_folder"> - <field name="name">My Folder</field> + <field name="name">Admin Folder</field> <field name="parent_id" ref="dir_root"/> <field name="user_id" ref="base.user_root"/> <field name="ressource_id">0</field> @@ -37,7 +37,7 @@ <field name="ressource_id">0</field> <field name="ressource_type_id" search="[('model','=','res.partner.category')]" /> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> </record> <record model="document.directory" id="dir_partner"> @@ -46,7 +46,7 @@ <field name="domain">[('category_id','in',[active_id])]</field> <field name="ressource_type_id" search="[('model','=','res.partner')]" /> <field name="ressource_parent_type_id" search="[('model','=','res.partner.category')]" /> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="ressource_id">0</field> </record> @@ -55,14 +55,14 @@ <field name="name">Personal Folders</field> <field name="parent_id" ref="dir_root"/> <field name="type">ressource</field> + <field name="user_id" eval="False"/> <field name="ressource_type_id" ref="base.model_res_users" /> <field name="ressource_id">0</field> - </record> <record model="document.directory" id="dir_product"> <field name="name">Products</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="parent_id" ref="dir_root"/> <field name="ressource_id">0</field> @@ -70,7 +70,7 @@ <record model="document.directory" id="dir_sale_order"> <field name="name">Sales Order</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="parent_id" ref="dir_root"/> <field name="ressource_id">0</field> @@ -78,7 +78,7 @@ <record model="document.directory" id="dir_sale_order_all"> <field name="name">All Sales Order</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="parent_id" ref="dir_sale_order"/> <field name="ressource_id">0</field> @@ -86,7 +86,7 @@ <record model="document.directory" id="dir_sale_order_quote"> <field name="name">Quotations</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="parent_id" ref="dir_sale_order"/> <field name="ressource_id">0</field> @@ -94,7 +94,7 @@ <record model="document.directory" id="dir_project"> <field name="name">Projects</field> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="parent_id" ref="dir_root"/> <field name="ressource_id">0</field> diff --git a/addons/document/document_directory.py b/addons/document/document_directory.py index 9b7ba18b16f..9412527db22 100644 --- a/addons/document/document_directory.py +++ b/addons/document/document_directory.py @@ -21,8 +21,8 @@ from osv import osv, fields +from osv.orm import except_orm -import os import nodes from tools.translate import _ @@ -38,9 +38,9 @@ class document_directory(osv.osv): 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'domain': fields.char('Domain', size=128, help="Use a domain if you want to apply an automatic filter on visible resources."), 'user_id': fields.many2one('res.users', 'Owner'), - 'storage_id': fields.many2one('document.storage', 'Storage'), + 'storage_id': fields.many2one('document.storage', 'Storage', change_default=True), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), - 'parent_id': fields.many2one('document.directory', 'Parent Directory', select=1), + 'parent_id': fields.many2one('document.directory', 'Parent Directory', select=1, change_default=True), 'child_ids': fields.one2many('document.directory', 'parent_id', 'Children'), 'file_ids': fields.one2many('ir.attachment', 'parent_id', 'Files'), 'content_ids': fields.one2many('document.directory.content', 'directory_id', 'Virtual Files'), @@ -48,22 +48,24 @@ class document_directory(osv.osv): ('directory','Static Directory'), ('ressource','Folders per resource'), ], - 'Type', required=True, select=1, + 'Type', required=True, select=1, change_default=True, help="Each directory can either have the type Static or be linked to another resource. A static directory, as with Operating Systems, is the classic directory that can contain a set of files. The directories linked to systems resources automatically possess sub-directories for each of resource types defined in the parent directory."), - 'ressource_type_id': fields.many2one('ir.model', 'Resource model', + 'ressource_type_id': fields.many2one('ir.model', 'Resource model', change_default=True, help="Select an object here and there will be one folder per record of that resource."), 'resource_field': fields.many2one('ir.model.fields', 'Name field', help='Field to be used as name on resource directories. If empty, the "name" will be used.'), 'resource_find_all': fields.boolean('Find all resources', required=True, help="If true, all attachments that match this resource will " \ " be located. If false, only ones that have this as parent." ), - 'ressource_parent_type_id': fields.many2one('ir.model', 'Parent Model', + 'ressource_parent_type_id': fields.many2one('ir.model', 'Parent Model', change_default=True, help="If you put an object here, this directory template will appear bellow all of these objects. " \ + "Such directories are \"attached\" to the specific model or record, just like attachments. " \ "Don't put a parent directory if you select a parent model."), - 'ressource_id': fields.integer('Resource ID'), + 'ressource_id': fields.integer('Resource ID', + help="Along with Parent Model, this ID attaches this folder to a specific record of Parent Model."), 'ressource_tree': fields.boolean('Tree Structure', help="Check this if you want to use the same tree structure as the object selected in the system."), 'dctx_ids': fields.one2many('document.directory.dctx', 'dir_id', 'Context fields'), - 'company_id': fields.many2one('res.company', 'Company'), + 'company_id': fields.many2one('res.company', 'Company', change_default=True), } @@ -98,10 +100,10 @@ class document_directory(osv.osv): _defaults = { 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'document.directory', context=c), 'user_id': lambda self,cr,uid,ctx: uid, - 'domain': lambda self,cr,uid,ctx: '[]', - 'type': lambda *args: 'directory', - 'ressource_id': lambda *a: 0, - 'storage_id': _get_def_storage, + 'domain': '[]', + 'type': 'directory', + 'ressource_id': 0, + 'storage_id': _get_def_storage, # Still, it is bad practice to set it everywhere. 'resource_find_all': True, } _sql_constraints = [ @@ -188,7 +190,6 @@ class document_directory(osv.osv): dbro = self.browse(cr, uid, ids, context=context) if dynamic: - assert dbro.type == 'directory' return nodes.node_res_obj elif dbro.type == 'directory': return nodes.node_dir @@ -211,22 +212,19 @@ class document_directory(osv.osv): """ return - def get_dir_permissions(self, cr, uid, ids ): + def get_dir_permissions(self, cr, uid, ids, context=None ): """Check what permission user 'uid' has on directory 'id' """ assert len(ids) == 1 - id = ids[0] - cr.execute( "SELECT count(dg.item_id) AS needs, count(ug.uid) AS has " \ - " FROM document_directory_group_rel dg " \ - " LEFT OUTER JOIN res_groups_users_rel ug " \ - " ON (dg.group_id = ug.gid AND ug.uid = %s) " \ - " WHERE dg.item_id = %s ", (uid, id)) - needs, has = cr.fetchone() - if needs and not has: - return 1 # still allow to descend into. - else: - return 15 + res = 0 + for pperms in [('read', 5), ('write', 2), ('unlink', 8)]: + try: + self.check_access_rule(cr, uid, ids, pperms[0], context=context) + res |= pperms[1] + except except_orm: + pass + return res def _locate_child(self, cr, uid, root_id, uri,nparent, ncontext): """ try to locate the node in uri, diff --git a/addons/document/document_storage.py b/addons/document/document_storage.py index 0ecc01941b4..aa2edb6b411 100644 --- a/addons/document/document_storage.py +++ b/addons/document/document_storage.py @@ -26,6 +26,7 @@ import tools import base64 import errno import logging +import shutil from StringIO import StringIO import psycopg2 @@ -48,7 +49,7 @@ DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config.get( We have to consider 3 cases of data /retrieval/: Given (context,path) we need to access the file (aka. node). given (directory, context), we need one of its children (for listings, views) - given (ir.attachment, context), we needs its data and metadata (node). + given (ir.attachment, context), we need its data and metadata (node). For data /storage/ we have the cases: Have (ir.attachment, context), we modify the file (save, update, rename etc). @@ -100,10 +101,17 @@ class nodefd_file(nodes.node_descriptor): if mode.endswith('b'): mode = mode[:-1] self.mode = mode + self._size = os.stat(path).st_size - for attr in ('closed', 'read', 'write', 'seek', 'tell'): + for attr in ('closed', 'read', 'write', 'seek', 'tell', 'next'): setattr(self,attr, getattr(self.__file, attr)) + def size(self): + return self._size + + def __iter__(self): + return self + def close(self): # TODO: locking in init, close() fname = self.__file.name @@ -165,6 +173,7 @@ class nodefd_db(StringIO, nodes.node_descriptor): """ def __init__(self, parent, ira_browse, mode): nodes.node_descriptor.__init__(self, parent) + self._size = 0L if mode.endswith('b'): mode = mode[:-1] @@ -172,6 +181,8 @@ class nodefd_db(StringIO, nodes.node_descriptor): cr = ira_browse._cr # reuse the cursor of the browse object, just now cr.execute('SELECT db_datas FROM ir_attachment WHERE id = %s',(ira_browse.id,)) data = cr.fetchone()[0] + if data: + self._size = len(data) StringIO.__init__(self, data) elif mode in ('w', 'w+'): StringIO.__init__(self, None) @@ -184,6 +195,9 @@ class nodefd_db(StringIO, nodes.node_descriptor): raise IOError(errno.EINVAL, "Invalid file mode") self.mode = mode + def size(self): + return self._size + def close(self): # we now open a *separate* cursor, to update the data. # FIXME: this may be improved, for concurrency handling @@ -241,11 +255,15 @@ class nodefd_db64(StringIO, nodes.node_descriptor): """ def __init__(self, parent, ira_browse, mode): nodes.node_descriptor.__init__(self, parent) + self._size = 0L if mode.endswith('b'): mode = mode[:-1] if mode in ('r', 'r+'): - StringIO.__init__(self, base64.decodestring(ira_browse.db_datas)) + data = base64.decodestring(ira_browse.db_datas) + if data: + self._size = len(data) + StringIO.__init__(self, data) elif mode in ('w', 'w+'): StringIO.__init__(self, None) # at write, we start at 0 (= overwrite), but have the original @@ -257,6 +275,9 @@ class nodefd_db64(StringIO, nodes.node_descriptor): raise IOError(errno.EINVAL, "Invalid file mode") self.mode = mode + def size(self): + return self._size + def close(self): # we now open a *separate* cursor, to update the data. # FIXME: this may be improved, for concurrency handling @@ -452,11 +473,11 @@ class document_storage(osv.osv): elif boo.type == 'realstore': path, npath = self.__prepare_realpath(cr, file_node, ira, boo.path, - do_create = (mode[1] in ('w','a')) ) + do_create = (mode[0] in ('w','a')) ) fpath = os.path.join(path, npath[-1]) - if (not os.path.exists(fpath)) and mode[1] == 'r': + if (not os.path.exists(fpath)) and mode[0] == 'r': raise IOError("File not found: %s" % fpath) - elif mode[1] in ('w', 'a') and not ira.store_fname: + elif mode[0] in ('w', 'a') and not ira.store_fname: store_fname = os.path.join(*npath) cr.execute('UPDATE ir_attachment SET store_fname = %s WHERE id = %s', (store_fname, ira.id)) @@ -541,9 +562,11 @@ class document_storage(osv.osv): try: store_fname = self.__get_random_fname(path) fname = os.path.join(path, store_fname) - fp = file(fname, 'wb') - fp.write(data) - fp.close() + fp = open(fname, 'wb') + try: + fp.write(data) + finally: + fp.close() self._doclog.debug( "Saved data to %s" % fname) filesize = len(data) # os.stat(fname).st_size @@ -568,9 +591,11 @@ class document_storage(osv.osv): try: path, npath = self.__prepare_realpath(cr, file_node, ira, boo.path, do_create=True) fname = os.path.join(path, npath[-1]) - fp = file(fname,'wb') - fp.write(data) - fp.close() + fp = open(fname,'wb') + try: + fp.write(data) + finally: + fp.close() self._doclog.debug("Saved data to %s", fname) filesize = len(data) # os.stat(fname).st_size store_fname = os.path.join(*npath) @@ -649,7 +674,7 @@ class document_storage(osv.osv): if ktype == 'file': try: os.unlink(fname) - except Exception, e: + except Exception: self._doclog.warning("Could not remove file %s, please remove manually.", fname, exc_info=True) else: self._doclog.warning("Unknown unlink key %s" % ktype) @@ -729,26 +754,34 @@ class document_storage(osv.osv): # nothing to do for a rename, allow to change the db field return { 'parent_id': ndir_bro.id } elif sbro.type == 'realstore': - raise NotImplementedError("Cannot move in realstore, yet") # TODO - fname = fil_bo.store_fname + ira = self.pool.get('ir.attachment').browse(cr, uid, file_node.file_id, context=context) + + path, opath = self.__prepare_realpath(cr, file_node, ira, sbro.path, do_create=False) + fname = ira.store_fname + if not fname: - return ValueError("Tried to rename a non-stored file") - path = sbro.path - oldpath = os.path.join(path, fname) + self._doclog.warning("Trying to rename a non-stored file") + if fname != os.path.join(*opath): + self._doclog.warning("inconsistency in realstore: %s != %s" , fname, repr(opath)) + + oldpath = os.path.join(path, opath[-1]) - for ch in ('*', '|', "\\", '/', ':', '"', '<', '>', '?', '..'): - if ch in new_name: - raise ValueError("Invalid char %s in name %s" %(ch, new_name)) - - file_node.fix_ppath(cr, ira) - npath = file_node.full_path() or [] - dpath = [path,] - dpath.extend(npath[:-1]) - dpath.append(new_name) - newpath = os.path.join(*dpath) - # print "old, new paths:", oldpath, newpath - os.rename(oldpath, newpath) - return { 'name': new_name, 'datas_fname': new_name, 'store_fname': new_name } + npath = [sbro.path,] + (ndir_bro.get_full_path() or []) + npath = filter(lambda x: x is not None, npath) + newdir = os.path.join(*npath) + if not os.path.isdir(newdir): + self._doclog.debug("Must create dir %s", newdir) + os.makedirs(newdir) + npath.append(opath[-1]) + newpath = os.path.join(*npath) + + self._doclog.debug("Going to move %s from %s to %s", opath[-1], oldpath, newpath) + shutil.move(oldpath, newpath) + + store_path = npath[1:] + [opath[-1],] + store_fname = os.path.join(*store_path) + + return { 'store_fname': store_fname } else: raise TypeError("No %s storage" % sbro.type) diff --git a/addons/document/nodes.py b/addons/document/nodes.py index 68220885dff..ee506d5eb2b 100644 --- a/addons/document/nodes.py +++ b/addons/document/nodes.py @@ -175,6 +175,23 @@ class node_descriptor(object): def write(self, str): raise NotImplementedError + def size(self): + raise NotImplementedError + + def __len__(self): + return self.size() + + def __nonzero__(self): + """ Ensure that a node_descriptor will never equal False + + Since we do define __len__ and __iter__ for us, we must avoid + being regarded as non-true objects. + """ + return True + + def next(self, str): + raise NotImplementedError + class node_class(object): """ this is a superclass for our inodes It is an API for all code that wants to access the document files. @@ -366,12 +383,14 @@ class node_class(object): def create_child(self, cr, path, data=None): """ Create a regular file under this node """ - raise NotImplementedError(repr(self)) + logger.warning("Attempted to create a file under %r, not possible.", self) + raise IOError(errno.EPERM, "Not allowed to create files here") def create_child_collection(self, cr, objname): """ Create a child collection (directory) under self """ - raise NotImplementedError(repr(self)) + logger.warning("Attempted to create a collection under %r, not possible.", self) + raise IOError(errno.EPERM, "Not allowed to create folders here") def rm(self, cr): raise NotImplementedError(repr(self)) @@ -433,12 +452,12 @@ class node_database(node_class): return res[0] return None - def _child_get(self, cr, name=False, parent_id=False, domain=None): + def _child_get(self, cr, name=False, domain=None): dirobj = self.context._dirobj uid = self.context.uid ctx = self.context.context.copy() ctx.update(self.dctx) - where = [('parent_id','=',parent_id)] + where = [('parent_id','=', False), ('ressource_parent_type_id','=',False)] if name: where.append(('name','=',name)) is_allowed = self.check_perms(1) @@ -448,23 +467,14 @@ class node_database(node_class): if not is_allowed: raise IOError(errno.EPERM, "Permission into directory denied") - if not domain: - domain = [] - - where2 = where + domain + ['|', ('type', '=', 'directory'), \ - '&', ('type', '=', 'ressource'), ('ressource_parent_type_id','=',False)] - ids = dirobj.search(cr, uid, where2, context=ctx) + if domain: + where = where + domain + ids = dirobj.search(cr, uid, where, context=ctx) res = [] for dirr in dirobj.browse(cr, uid, ids, context=ctx): klass = dirr.get_node_class(dirr, context=ctx) res.append(klass(dirr.name, self, self.context,dirr)) - fil_obj = dirobj.pool.get('ir.attachment') - ids = fil_obj.search(cr, uid, where, context=ctx) - if ids: - for fil in fil_obj.browse(cr, uid, ids, context=ctx): - klass = self.context.node_file_class - res.append(klass(fil.name, self, self.context, fil)) return res def _file_get(self,cr, nodename=False): @@ -485,6 +495,22 @@ def mkdosname(company_name, default='noname'): return n +def _uid2unixperms(perms, has_owner): + """ Convert the uidperms and the owner flag to full unix bits + """ + res = 0 + if has_owner: + res |= (perms & 0x07) << 6 + res |= (perms & 0x05) << 3 + elif perms & 0x02: + res |= (perms & 0x07) << 6 + res |= (perms & 0x07) << 3 + else: + res |= (perms & 0x07) << 6 + res |= (perms & 0x05) << 3 + res |= 0x05 + return res + class node_dir(node_database): our_type = 'collection' def __init__(self, path, parent, context, dirr, dctx=None): @@ -499,13 +525,13 @@ class node_dir(node_database): # TODO: the write date should be MAX(file.write).. self.write_date = dirr and (dirr.write_date or dirr.create_date) or False self.content_length = 0 - self.unixperms = 040750 try: self.uuser = (dirr.user_id and dirr.user_id.login) or 'nobody' except Exception: self.uuser = 'nobody' self.ugroup = mkdosname(dirr.company_id and dirr.company_id.name, default='nogroup') self.uidperms = dirr.get_dir_permissions() + self.unixperms = 040000 | _uid2unixperms(self.uidperms, dirr and dirr.user_id) if dctx: self.dctx.update(dctx) dc2 = self.context.context @@ -516,7 +542,7 @@ class node_dir(node_database): for dfld in dirr.dctx_ids: try: self.dctx['dctx_' + dfld.field] = safe_eval(dfld.expr,dc2) - except Exception: + except Exception,e: print "Cannot eval %s" % dfld.expr print e pass @@ -559,7 +585,46 @@ class node_dir(node_database): return res def _child_get(self, cr, name=None, domain=None): - return super(node_dir,self)._child_get(cr, name, self.dir_id, domain=domain) + dirobj = self.context._dirobj + uid = self.context.uid + ctx = self.context.context.copy() + ctx.update(self.dctx) + where = [('parent_id','=',self.dir_id)] + if name: + where.append(('name','=',name)) + is_allowed = self.check_perms(1) + else: + is_allowed = self.check_perms(5) + + if not is_allowed: + raise IOError(errno.EPERM, "Permission into directory denied") + + if not domain: + domain = [] + + where2 = where + domain + [('ressource_parent_type_id','=',False)] + ids = dirobj.search(cr, uid, where2, context=ctx) + res = [] + for dirr in dirobj.browse(cr, uid, ids, context=ctx): + klass = dirr.get_node_class(dirr, context=ctx) + res.append(klass(dirr.name, self, self.context,dirr)) + + # Static directories should never return files with res_model/res_id + # because static dirs are /never/ related to a record. + # In fact, files related to some model and parented by the root dir + # (the default), will NOT be accessible in the node system unless + # a resource folder for that model exists (with resource_find_all=True). + # Having resource attachments in a common folder is bad practice, + # because they would be visible to all users, and their names may be + # the same, conflicting. + where += [('res_model', '=', False)] + fil_obj = dirobj.pool.get('ir.attachment') + ids = fil_obj.search(cr, uid, where, context=ctx) + if ids: + for fil in fil_obj.browse(cr, uid, ids, context=ctx): + klass = self.context.node_file_class + res.append(klass(fil.name, self, self.context, fil)) + return res def rmcol(self, cr): uid = self.context.uid @@ -699,13 +764,13 @@ class node_res_dir(node_class): # TODO: the write date should be MAX(file.write).. self.write_date = dirr.write_date or dirr.create_date self.content_length = 0 - self.unixperms = 040750 try: self.uuser = (dirr.user_id and dirr.user_id.login) or 'nobody' except Exception: self.uuser = 'nobody' self.ugroup = mkdosname(dirr.company_id and dirr.company_id.name, default='nogroup') self.uidperms = dirr.get_dir_permissions() + self.unixperms = 040000 | _uid2unixperms(self.uidperms, dirr and dirr.user_id) self.res_model = dirr.ressource_type_id and dirr.ressource_type_id.model or False self.resm_id = dirr.ressource_id self.res_find_all = dirr.resource_find_all @@ -759,7 +824,7 @@ class node_res_dir(node_class): ctx.update(self.dctx) where = [] if self.domain: - app = safe_eval(self.domain, self.dctx) + app = safe_eval(self.domain, ctx) if not app: pass elif isinstance(app, list): @@ -823,8 +888,8 @@ class node_res_obj(node_class): # TODO: the write date should be MAX(file.write).. self.write_date = parent.write_date self.content_length = 0 - self.unixperms = 040750 self.uidperms = parent.uidperms & 15 + self.unixperms = 040000 | _uid2unixperms(self.uidperms, True) self.uuser = parent.uuser self.ugroup = parent.ugroup self.res_model = res_model @@ -842,7 +907,7 @@ class node_res_obj(node_class): for fld,expr in self.dctx_dict.items(): try: self.dctx[fld] = safe_eval(expr, dc2) - except Exception: + except Exception,e: print "Cannot eval %s for %s" % (expr, fld) print e pass @@ -953,9 +1018,9 @@ class node_res_obj(node_class): where1 = [] if obj._parent_name in obj.fields_get(cr, uid): where1 = where + [(obj._parent_name, '=', self.res_id)] + namefield = directory.resource_field.name or 'name' resids = obj.search(cr, uid, where1, context=ctx) for bo in obj.browse(cr, uid, resids, context=ctx): - namefield = directory.resource_field.name or 'name' if not bo: continue res_name = getattr(bo, namefield) @@ -963,7 +1028,7 @@ class node_res_obj(node_class): continue # TODO Revise klass = directory.get_node_class(directory, dynamic=True, context=ctx) - res.append(klass(res_name, self.dir_id, self, self.context, self.res_model, res_bo = bo)) + res.append(klass(res_name, dir_id=self.dir_id, parent=self, context=self.context, res_model=self.res_model, res_bo=bo)) where2 = where + [('parent_id','=',self.dir_id) ] @@ -1361,11 +1426,13 @@ class nodefd_content(StringIO, node_descriptor): def __init__(self, parent, cr, mode, ctx): node_descriptor.__init__(self, parent) self._context=ctx + self._size = 0L if mode in ('r', 'r+'): cntobj = parent.context._dirobj.pool.get('document.directory.content') data = cntobj.process_read(cr, parent.context.uid, parent, ctx) if data: + self._size = len(data) parent.content_length = len(data) StringIO.__init__(self, data) elif mode in ('w', 'w+'): @@ -1379,6 +1446,9 @@ class nodefd_content(StringIO, node_descriptor): raise IOError(errno.EINVAL, "Invalid file mode") self.mode = mode + def size(self): + return self._size + def close(self): # we now open a *separate* cursor, to update the data. # FIXME: this may be improved, for concurrency handling @@ -1404,4 +1474,56 @@ class nodefd_content(StringIO, node_descriptor): cr.close() StringIO.close(self) +class nodefd_static(StringIO, node_descriptor): + """ A descriptor to nodes with static data. + """ + def __init__(self, parent, cr, mode, ctx=None): + node_descriptor.__init__(self, parent) + self._context=ctx + self._size = 0L + + if mode in ('r', 'r+'): + data = parent.get_data(cr) + if data: + self._size = len(data) + parent.content_length = len(data) + StringIO.__init__(self, data) + elif mode in ('w', 'w+'): + StringIO.__init__(self, None) + # at write, we start at 0 (= overwrite), but have the original + # data available, in case of a seek() + elif mode == 'a': + StringIO.__init__(self, None) + else: + logging.getLogger('document.nodes').error("Incorrect mode %s specified", mode) + raise IOError(errno.EINVAL, "Invalid file mode") + self.mode = mode + + def size(self): + return self._size + + def close(self): + # we now open a *separate* cursor, to update the data. + # FIXME: this may be improved, for concurrency handling + if self.mode == 'r': + StringIO.close(self) + return + + par = self._get_parent() + # uid = par.context.uid + cr = pooler.get_db(par.context.dbname).cursor() + try: + if self.mode in ('w', 'w+', 'r+'): + data = self.getvalue() + par.set_data(cr, data) + elif self.mode == 'a': + raise NotImplementedError + cr.commit() + except Exception: + logging.getLogger('document.nodes').exception('Cannot update db content #%d for close:', par.cnt_id) + raise + finally: + cr.close() + StringIO.close(self) + #eof
\ No newline at end of file diff --git a/addons/document/security/document_security.xml b/addons/document/security/document_security.xml index 2bf1a2adb57..ca55a8219c1 100644 --- a/addons/document/security/document_security.xml +++ b/addons/document/security/document_security.xml @@ -14,6 +14,28 @@ <field name="groups_id" eval="[(6,0,[ref('base.group_system')])]"/> </record> - + <record id="ir_rule_readpublicdirectories0" model="ir.rule"> + <field name="model_id" ref="document.model_document_directory"/> + <field name="domain_force">['|','|',('group_ids','in',[g.id for g in user.groups_id]), ('user_id', '=', user.id), '&', ('user_id', '=', False), ('group_ids','=',False), '|', ('company_id','=',False), ('company_id','child_of',[user.company_id.id])]</field> + <field name="name">Read public directories</field> + <field eval="0" name="global"/> + <field eval="[(6,0,[ref('base.group_user')])]" name="groups"/> + <field eval="0" name="perm_unlink"/> + <field eval="0" name="perm_write"/> + <field eval="1" name="perm_read"/> + <field eval="0" name="perm_create"/> + </record> + + <record id="ir_rule_documentmodifyowndirectories0" model="ir.rule"> + <field name="model_id" ref="document.model_document_directory"/> + <field name="domain_force">[ '|', ('user_id', '=', user.id), '&', ('group_ids','in',[g.id for g in user.groups_id]), ('user_id','=',False), '|', ('company_id','=',False), ('company_id','child_of',[user.company_id.id])]</field> + <field name="name">Document modify own directories</field> + <field eval="0" name="global"/> + <field eval="[(6,0,[ref('base.group_document_user')])]" name="groups"/> + <field eval="1" name="perm_unlink"/> + <field eval="1" name="perm_write"/> + <field eval="0" name="perm_read"/> + <field eval="1" name="perm_create"/> + </record> </data> </openerp> diff --git a/addons/document/security/ir.model.access.csv b/addons/document/security/ir.model.access.csv index 132daa1b7a6..d7aba7cbde7 100644 --- a/addons/document/security/ir.model.access.csv +++ b/addons/document/security/ir.model.access.csv @@ -1,6 +1,7 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_document_directory_all","document.directory all","model_document_directory",,1,0,0,0 "access_document_directory_group_document_manager","document.directory document manager","model_document_directory","base.group_system",1,1,1,1 +"access_document_directory_group_knowledge","document.directory modify","model_document_directory","base.group_document_user",1,1,1,1 "access_document_directory_group_system","document.directory group system","model_document_directory","base.group_system",1,1,1,1 "access_document_directory_content_all","document.directory.content all","model_document_directory_content",,1,0,0,0 "access_document_directory_content_group_document_manager","document.directory.content document manager","model_document_directory_content","base.group_system",1,1,1,1 diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py index 9c16e7dde55..65b17a52c51 100644 --- a/addons/document_ftp/ftpserver/abstracted_fs.py +++ b/addons/document_ftp/ftpserver/abstracted_fs.py @@ -146,16 +146,18 @@ class abstracted_fs(object): ret = child.open_data(cr, mode) cr.commit() + assert ret, "Cannot create descriptor for %r: %r" % (child, ret) return ret except EnvironmentError: raise - except Exception,e: + except Exception: self._log.exception('Cannot locate item %s at node %s', objname, repr(node)) pass try: child = node.create_child(cr, objname, data=None) ret = child.open_data(cr, mode) + assert ret, "cannot create descriptor for %r" % child cr.commit() return ret except EnvironmentError: diff --git a/addons/document_ftp/ftpserver/ftpserver.py b/addons/document_ftp/ftpserver/ftpserver.py index 710494bb9db..bd727427541 100644 --- a/addons/document_ftp/ftpserver/ftpserver.py +++ b/addons/document_ftp/ftpserver/ftpserver.py @@ -2223,6 +2223,7 @@ class FTPHandler(asynchat.async_chat): if self.restart_position: mode = 'r+' fd = self.try_as_current_user(self.fs.create, (datacr, datacr[2], mode + 'b')) + assert fd except FTPExceptionSent: self.fs.close_cr(datacr) return diff --git a/addons/document_ftp/test/document_ftp_test2.yml b/addons/document_ftp/test/document_ftp_test2.yml index da55c353767..5da4bcd83ef 100644 --- a/addons/document_ftp/test/document_ftp_test2.yml +++ b/addons/document_ftp/test/document_ftp_test2.yml @@ -7,6 +7,7 @@ from document_ftp import test_easyftp as te ftp = te.get_plain_ftp(timeout=2.0) assert ftp.sock and (ftp.lastresp == '220'), ftp.lastresp + ftp.close() - I read the list of databases at port 8021 and confirm our db is there @@ -15,6 +16,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_login(cr, uid, self) assert cr.dbname in ftp.nlst("/") + ftp.close() - I try to locate the default "Documents" folder in the db. - @@ -22,6 +24,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_login(cr, uid, self) ftp.cwd('Documents') + ftp.close() - I create a "test.txt" file at the server (directly). The file should have the "abcd" content @@ -32,6 +35,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents') fdata = StringIO('abcd') ftp.storbinary('STOR test.txt', fdata) + ftp.close() - I look for the "test.txt" file at the server - @@ -39,6 +43,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') assert ftp.nlst("test.txt") == ['test.txt'] + ftp.close() - I check that the content of "test.txt" is "abcd" - @@ -46,7 +51,9 @@ from document_ftp import test_easyftp as te from cStringIO import StringIO ftp = te.get_ftp_folder(cr, uid, self, 'Documents') - assert te.get_ftp_fulldata(ftp, "test.txt") == 'abcd' + gotdata = te.get_ftp_fulldata(ftp, "test.txt") + ftp.close() + assert gotdata == 'abcd', 'Data: %r' % gotdata - I append the string 'defgh' to "test.txt" - @@ -56,6 +63,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents') fdata = StringIO('defgh') ftp.storbinary('APPE test.txt', fdata) + ftp.close() - I check that the content of "text.txt" is 'abcddefgh' - @@ -63,7 +71,9 @@ from document_ftp import test_easyftp as te from cStringIO import StringIO ftp = te.get_ftp_folder(cr, uid, self, 'Documents') - assert te.get_ftp_fulldata(ftp, "test.txt") == 'abcddefgh' + gotdata = te.get_ftp_fulldata(ftp, "test.txt") + ftp.close() + assert gotdata == 'abcddefgh', 'Data: %r' % gotdata - I try to cd into an non-existing folder 'Not-This' - @@ -77,7 +87,9 @@ except ftplib.error_perm: pass except OSError, err: + ftp.close() assert err.errno == 2, err.errno + ftp.close() - I create a "test2.txt" file through FTP. - @@ -87,6 +99,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents') fdata = StringIO('abcd') ftp.storbinary('STOR test2.txt', fdata) + ftp.close() - I look for the "test2.txt" file at the server - @@ -101,6 +114,7 @@ from cStringIO import StringIO ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.delete('test2.txt') + ftp.close() - I check at the server that test2.txt is deleted - @@ -116,6 +130,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents') fdata = StringIO('abcd') ftp.storbinary('STOR test2.txt', fdata) + ftp.close() - I delete the test2.txt from the server (RPC). - @@ -137,6 +152,7 @@ except ftplib.error_perm: # 550 error: 'path not exists' nlst_result = [] assert "test2.txt" not in nlst_result, "Files: %r" % nlst_result + ftp.close() - I create a "test-name.txt" file - @@ -146,6 +162,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents') fdata = StringIO('abcd') ftp.storbinary('STOR test-name.txt', fdata) + ftp.close() - I rename the "test-name.txt" file through ftp. - @@ -153,6 +170,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.rename("test-name.txt", "test-renamed.txt") + ftp.close() - I check that test-name.txt has been renamed. - @@ -166,6 +184,7 @@ except error_perm, e: pass assert ftp.nlst("test-renamed.txt") == ['test-renamed.txt'] + ftp.close() - I create a new folder 'Test-Folder2' through FTP - @@ -173,6 +192,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.mkd("Test-Folder2") + ftp.close() - I create a file 'test3.txt' at the 'Test-Folder2' - @@ -182,6 +202,7 @@ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') fdata = StringIO('abcd') ftp.storbinary('STOR test3.txt', fdata) + ftp.close() - I try to retrieve test3.txt - @@ -189,6 +210,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Test-Folder2') assert ftp.nlst("test3.txt") == ['test3.txt'], "File test3.txt is not there!" + ftp.close() - I create a new folder, 'Test-Folder3', through FTP I try to move test3.txt to 'Test-Folder3' @@ -197,6 +219,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.mkd("Test-Folder3") + ftp.close() # TODO move - I remove the 'Test-Folder3' @@ -205,6 +228,7 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.rmd("Test-Folder3") + ftp.close() - I check that test3.txt is removed. - @@ -219,6 +243,7 @@ for i in range(0, 200): fdata.seek(0) ftp.storbinary('STOR test-name%s.txt' %i, fdata) + ftp.close() - I list the 200 files, check speed - @@ -245,6 +270,7 @@ ftp.delete('test3.txt') for i in range(0, 200): ftp.delete('test-name%s.txt' %i) + ftp.close() - I remove the 'Test-Folder2' - @@ -252,3 +278,4 @@ from document_ftp import test_easyftp as te ftp = te.get_ftp_folder(cr, uid, self, 'Documents') ftp.rmd("Test-Folder2") + ftp.close() diff --git a/addons/document_ftp/test/document_ftp_test4.yml b/addons/document_ftp/test/document_ftp_test4.yml index 2bb616dc1bd..2441be3bf92 100644 --- a/addons/document_ftp/test/document_ftp_test4.yml +++ b/addons/document_ftp/test/document_ftp_test4.yml @@ -114,6 +114,35 @@ - res_model == 'res.partner' - res_id != False - + I try to create a file directly under the Partners Testing folder +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + fdata = StringIO('abcd') + try: + ftp.storbinary('STOR stray.txt', fdata) + assert False, "We should't be able to create files here" + except ftplib.error_perm: + # That's what should happen + pass +- + I try to create a folder directly under the Partners Testing folder +- + !python {model: ir.attachment}: | + from document_ftp import test_easyftp as te + import ftplib + from cStringIO import StringIO + ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Partners Testing') + try: + ftp.mkd('Weird folder') + assert False, "We should't be able to create folders here" + except ftplib.error_perm: + # That's what should happen + pass +- I check that all/Partner1 also has the file - | Bonus Piste: diff --git a/addons/document_ftp/test/document_ftp_test5.yml b/addons/document_ftp/test/document_ftp_test5.yml new file mode 100644 index 00000000000..a66f409905b --- /dev/null +++ b/addons/document_ftp/test/document_ftp_test5.yml @@ -0,0 +1,30 @@ +- + In order to check the permissions setup and functionality of the + document module: +- + I create a testing user for the documents +- + I assign some ... group to the testing user +- + I create a "group testing" user, which also belongs to the same ... group +- + I create a "blocked" user. +- + I create (as root) a testing folder in the document hierarchy, and + assign ownership to the testing user, groups to the ... group. +- + I create a "private" folder inside the testing folder. +- + I try to read the testing folder as the testing user +- + I try to read the folder as the group user, it should fail. +- + I try to read the folder as the blocked user. +- + I create a "group" folder, with the ... group. +- + I try to read the "group" folder as the testing user +- + I try to read the "group" folder as the group user +- + I try to read the "group" folder as the blocked user diff --git a/addons/document_webdav/__openerp__.py b/addons/document_webdav/__openerp__.py index e6b8cfd3f94..6c1e24d1e96 100644 --- a/addons/document_webdav/__openerp__.py +++ b/addons/document_webdav/__openerp__.py @@ -57,6 +57,8 @@ 'webdav_setup.xml', ], "demo_xml" : [], + "test": [ #'test/webdav_test1.yml', + ], "active": False, "installable": True } diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py index 3e8e1c2b3e5..c34a323fadb 100644 --- a/addons/document_webdav/dav_fs.py +++ b/addons/document_webdav/dav_fs.py @@ -20,18 +20,16 @@ ############################################################################## import pooler -import base64 -import sys import os import time -from string import joinfields, split, lower +import errno import netsvc import urlparse -from DAV.constants import COLLECTION, OBJECT -from DAV.errors import * -from DAV.iface import * +from DAV.constants import COLLECTION #, OBJECT +from DAV.errors import DAV_Error, DAV_Forbidden, DAV_NotFound +from DAV.iface import dav_interface import urllib from DAV.davcmd import copyone, copytree, moveone, movetree, delone, deltree @@ -74,6 +72,89 @@ def _str2time(cre): cre = cre[:fdot] return time.mktime(time.strptime(cre,'%Y-%m-%d %H:%M:%S')) + frac +class BoundStream2(object): + """Wraps around a seekable buffer, reads a determined range of data + + Note that the supplied stream object MUST support a size() which + should return its data length (in bytes). + + A variation of the class in websrv_lib.py + """ + + def __init__(self, stream, offset=None, length=None, chunk_size=None): + self._stream = stream + self._offset = offset or 0 + self._length = length or self._stream.size() + self._rem_length = length + assert length and isinstance(length, (int, long)) + assert length and length >= 0, length + self._chunk_size = chunk_size + if offset is not None: + self._stream.seek(offset) + + def read(self, size=-1): + if not self._stream: + raise IOError(errno.EBADF, "read() without stream") + + if self._rem_length == 0: + return '' + elif self._rem_length < 0: + raise EOFError() + + rsize = self._rem_length + if size > 0 and size < rsize: + rsize = size + if self._chunk_size and self._chunk_size < rsize: + rsize = self._chunk_size + + data = self._stream.read(rsize) + self._rem_length -= len(data) + + return data + + def __len__(self): + return self._length + + def tell(self): + res = self._stream.tell() + if self._offset: + res -= self._offset + return res + + def __iter__(self): + return self + + def next(self): + return self.read(65536) + + def seek(self, pos, whence=os.SEEK_SET): + """ Seek, computing our limited range + """ + if whence == os.SEEK_SET: + if pos < 0 or pos > self._length: + raise IOError(errno.EINVAL,"Cannot seek") + self._stream.seek(pos - self._offset) + self._rem_length = self._length - pos + elif whence == os.SEEK_CUR: + if pos > 0: + if pos > self._rem_length: + raise IOError(errno.EINVAL,"Cannot seek past end") + elif pos < 0: + oldpos = self.tell() + if oldpos + pos < 0: + raise IOError(errno.EINVAL,"Cannot seek before start") + self._stream.seek(pos, os.SEEK_CUR) + self._rem_length -= pos + elif whence == os.SEEK_END: + if pos > 0: + raise IOError(errno.EINVAL,"Cannot seek past end") + else: + if self._length + pos < 0: + raise IOError(errno.EINVAL,"Cannot seek before start") + newpos = self._offset + self._length + pos + self._stream.seek(newpos, os.SEEK_SET) + self._rem_length = 0 - pos + class openerp_dav_handler(dav_interface): """ This class models a OpenERP interface for the DAV server @@ -396,11 +477,28 @@ class openerp_dav_handler(dav_interface): node = self.uri2object(cr, uid, pool, uri2) if not node: raise DAV_NotFound2(uri2) + # TODO: if node is a collection, for some specific set of + # clients ( web browsers; available in node context), + # we may return a pseydo-html page with the directory listing. try: + res = node.open_data(cr,'r') if rrange: - self.parent.log_error("Doc get_data cannot use range") - raise DAV_Error(409) - datas = node.get_data(cr) + assert isinstance(rrange, (tuple,list)) + start, end = map(long, rrange) + if not start: + start = 0 + assert start >= 0 + if end and end < start: + self.parent.log_error("Invalid range for data: %s-%s" %(start, end)) + raise DAV_Error(416, "Invalid range for data") + if end: + if end >= res.size(): + raise DAV_Error(416, "Requested data exceeds available size") + length = (end + 1) - start + else: + length = res.size() - start + res = BoundStream2(res, offset=start, length=length) + except TypeError,e: # for the collections that return this error, the DAV standard # says we'd better just return 200 OK with empty data @@ -413,7 +511,7 @@ class openerp_dav_handler(dav_interface): self.parent.log_error("GET exception: %s",str(e)) self.parent.log_message("Exc: %s", traceback.format_exc()) raise DAV_Error, 409 - return str(datas) # FIXME! + return res finally: if cr: cr.close() @@ -584,8 +682,7 @@ class openerp_dav_handler(dav_interface): node = False objname = uri2[-1] - ext = objname.find('.') >0 and objname.split('.')[1] or False - + ret = None if not node: dir_node = self.uri2object(cr, uid, pool, uri2[:-1]) @@ -668,7 +765,7 @@ class openerp_dav_handler(dav_interface): """ if uri[-1]=='/':uri=uri[:-1] res=delone(self,uri) - parent='/'.join(uri.split('/')[:-1]) + # parent='/'.join(uri.split('/')[:-1]) return res def deltree(self, uri): @@ -680,7 +777,7 @@ class openerp_dav_handler(dav_interface): """ if uri[-1]=='/':uri=uri[:-1] res=deltree(self, uri) - parent='/'.join(uri.split('/')[:-1]) + # parent='/'.join(uri.split('/')[:-1]) return res diff --git a/addons/document_webdav/document_webdav.py b/addons/document_webdav/document_webdav.py index 28b70c8d7e4..2e1eb8cabd2 100644 --- a/addons/document_webdav/document_webdav.py +++ b/addons/document_webdav/document_webdav.py @@ -37,7 +37,6 @@ class document_davdir(osv.osv): dbro = self.browse(cr, uid, ids, context=context) if dynamic: - assert dbro.type == 'directory' return nodes.node_res_obj elif dbro.type == 'directory': return nodes.node_dir diff --git a/addons/document_webdav/test/webdav_test1.yml b/addons/document_webdav/test/webdav_test1.yml new file mode 100644 index 00000000000..a0f15c10fc9 --- /dev/null +++ b/addons/document_webdav/test/webdav_test1.yml @@ -0,0 +1,59 @@ +- + In order to test the document_ftp functionality +- + I open the HTTP port and perform an OPTIONS request to the server +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + reload(te) # reload.. + dc = te.DAVClient() + dc.gd_options() + dc.get_creds(self, cr, uid) + dc.gd_options(path=cr.dbname, expect={'DAV': ['1',]}) +- + I will test the propnames at the document root +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + dc = te.DAVClient() + dc.get_creds(self, cr, uid) + dc.gd_propname(path=cr.dbname+'/Documents/') +- + I will test the ETags of the document root +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + dc = te.DAVClient() + dc.get_creds(self, cr, uid) + dc.gd_getetag(path=cr.dbname+'/Documents/') + +- + I will now ls -l the document root. +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + dc = te.DAVClient() + dc.get_creds(self, cr, uid) + res = dc.gd_lsl(path=cr.dbname+'/Documents/') + for lin in res: + print "%(type)s\t%(uid)s\t%(gid)s\t%(size)s\t%(mtime)s\t%(name)s" % lin +- + I will put a file to the server +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + import addons + dc = te.DAVClient() + dc.get_creds(self, cr, uid) + tdp = addons.get_module_resource('document_webdav', 'test_davclient.py') + res = dc.gd_put(path=cr.dbname+'/Documents/test_davclient.py', srcpath=tdp) +- + I will try to get the file from the root +- + !python {model: ir.attachment}: | + from document_webdav import test_davclient as te + import addons + dc = te.DAVClient() + dc.get_creds(self, cr, uid) + tdp = addons.get_module_resource('document_webdav', 'test_davclient.py') + res = dc.gd_get(path=cr.dbname+'/Documents/test_davclient.py', crange=(4,508), compare=tdp) diff --git a/addons/document_webdav/test_davclient.py b/addons/document_webdav/test_davclient.py new file mode 100644 index 00000000000..ac40d1a3d30 --- /dev/null +++ b/addons/document_webdav/test_davclient.py @@ -0,0 +1,702 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# +# Copyright P. Christeas <p_christ@hol.gr> 2008,2009 +# Copyright OpenERP SA. (http://www.openerp.com) 2010 +# +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +############################################################################### + +""" A trivial HTTP/WebDAV client, used for testing the server +""" +# code taken from the 'http-client.py' script: +# http://git.hellug.gr/?p=xrg/openerp;a=history;f=tests/http-client.py;hb=refs/heads/xrg-60 + +import gzip +import logging +import xml.dom.minidom + +import httplib + +from tools import config +from xmlrpclib import Transport, ProtocolError +import StringIO +import base64 + +log = logging.getLogger('http-client') + +class HTTP11(httplib.HTTP): + _http_vsn = 11 + _http_vsn_str = 'HTTP/1.1' + +class PersistentTransport(Transport): + """Handles an HTTP transaction to an XML-RPC server, persistently.""" + + def __init__(self, use_datetime=0): + self._use_datetime = use_datetime + self._http = {} + log.debug("Using persistent transport") + + def make_connection(self, host): + # create a HTTP connection object from a host descriptor + if not self._http.has_key(host): + host, extra_headers, x509 = self.get_host_info(host) + self._http[host] = HTTP11(host) + log.debug("New connection to %s", host) + return self._http[host] + + def get_host_info(self, host): + host, extra_headers, x509 = Transport.get_host_info(self,host) + if extra_headers == None: + extra_headers = [] + + extra_headers.append( ( 'Connection', 'keep-alive' )) + + return host, extra_headers, x509 + + def _parse_response(self, file, sock, response): + """ read response from input file/socket, and parse it + We are persistent, so it is important to only parse + the right amount of input + """ + + p, u = self.getparser() + + if response.msg.get('content-encoding') == 'gzip': + gzdata = StringIO.StringIO() + while not response.isclosed(): + rdata = response.read(1024) + if not rdata: + break + gzdata.write(rdata) + gzdata.seek(0) + rbuffer = gzip.GzipFile(mode='rb', fileobj=gzdata) + while True: + respdata = rbuffer.read() + if not respdata: + break + p.feed(respdata) + else: + while not response.isclosed(): + rdata = response.read(1024) + if not rdata: + break + p.feed(rdata) + if len(rdata)<1024: + break + + p.close() + return u.close() + + def request(self, host, handler, request_body, verbose=0): + # issue XML-RPC request + + h = self.make_connection(host) + if verbose: + h.set_debuglevel(1) + + self.send_request(h, handler, request_body) + self.send_host(h, host) + self.send_user_agent(h) + self.send_content(h, request_body) + + resp = h._conn.getresponse() + # TODO: except BadStatusLine, e: + + errcode, errmsg, headers = resp.status, resp.reason, resp.msg + + + if errcode != 200: + raise ProtocolError( + host + handler, + errcode, errmsg, + headers + ) + + self.verbose = verbose + + try: + sock = h._conn.sock + except AttributeError: + sock = None + + return self._parse_response(h.getfile(), sock, resp) + +class CompressedTransport(PersistentTransport): + def send_content(self, connection, request_body): + connection.putheader("Content-Type", "text/xml") + + if len(request_body) > 512 or True: + buffer = StringIO.StringIO() + output = gzip.GzipFile(mode='wb', fileobj=buffer) + output.write(request_body) + output.close() + buffer.seek(0) + request_body = buffer.getvalue() + connection.putheader('Content-Encoding', 'gzip') + + connection.putheader("Content-Length", str(len(request_body))) + connection.putheader("Accept-Encoding",'gzip') + connection.endheaders() + if request_body: + connection.send(request_body) + + def send_request(self, connection, handler, request_body): + connection.putrequest("POST", handler, skip_accept_encoding=1) + +class SafePersistentTransport(PersistentTransport): + def make_connection(self, host): + # create a HTTP connection object from a host descriptor + if not self._http.has_key(host): + host, extra_headers, x509 = self.get_host_info(host) + self._http[host] = httplib.HTTPS(host, None, **(x509 or {})) + log.debug("New connection to %s", host) + return self._http[host] + +class AuthClient(object): + def getAuth(self, atype, realm): + raise NotImplementedError("Cannot authenticate for %s" % atype) + + def resolveFailedRealm(self, realm): + """ Called when, using a known auth type, the realm is not in cache + """ + raise NotImplementedError("Cannot authenticate for realm %s" % realm) + +class BasicAuthClient(AuthClient): + def __init__(self): + self._realm_dict = {} + + def getAuth(self, atype, realm): + if atype != 'Basic' : + return super(BasicAuthClient,self).getAuth(atype, realm) + + if not self._realm_dict.has_key(realm): + log.debug("realm dict: %r", self._realm_dict) + log.debug("missing key: \"%s\"" % realm) + self.resolveFailedRealm(realm) + return 'Basic '+ self._realm_dict[realm] + + def addLogin(self, realm, username, passwd): + """ Add some known username/password for a specific login. + This function should be called once, for each realm + that we want to authenticate against + """ + assert realm + auths = base64.encodestring(username + ':' + passwd) + if auths[-1] == "\n": + auths = auths[:-1] + self._realm_dict[realm] = auths + +class addAuthTransport: + """ Intermediate class that authentication algorithm to http transport + """ + + def setAuthClient(self, authobj): + """ Set the authentication client object. + This method must be called before any request is issued, that + would require http authentication + """ + assert isinstance(authobj, AuthClient) + self._auth_client = authobj + + + def request(self, host, handler, request_body, verbose=0): + # issue XML-RPC request + + h = self.make_connection(host) + if verbose: + h.set_debuglevel(1) + + tries = 0 + atype = None + realm = None + + while(tries < 3): + self.send_request(h, handler, request_body) + self.send_host(h, host) + self.send_user_agent(h) + if atype: + # This line will bork if self.setAuthClient has not + # been issued. That is a programming error, fix your code! + auths = self._auth_client.getAuth(atype, realm) + log.debug("sending authorization: %s", auths) + h.putheader('Authorization', auths) + self.send_content(h, request_body) + + resp = h._conn.getresponse() + # except BadStatusLine, e: + tries += 1 + + if resp.status == 401: + if 'www-authenticate' in resp.msg: + (atype,realm) = resp.msg.getheader('www-authenticate').split(' ',1) + data1 = resp.read() + if data1: + log.warning("Why have data on a 401 auth. message?") + if realm.startswith('realm="') and realm.endswith('"'): + realm = realm[7:-1] + log.debug("Resp: %r %r", resp.version,resp.isclosed(), resp.will_close) + log.debug("Want to do auth %s for realm %s", atype, realm) + if atype != 'Basic': + raise ProtocolError(host+handler, 403, + "Unknown authentication method: %s" % atype, resp.msg) + continue # with the outer while loop + else: + raise ProtocolError(host+handler, 403, + 'Server-incomplete authentication', resp.msg) + + if resp.status != 200: + raise ProtocolError( host + handler, + resp.status, resp.reason, resp.msg ) + + self.verbose = verbose + + try: + sock = h._conn.sock + except AttributeError: + sock = None + + return self._parse_response(h.getfile(), sock, resp) + + raise ProtocolError(host+handler, 403, "No authentication",'') + +class PersistentAuthTransport(addAuthTransport,PersistentTransport): + pass + +class PersistentAuthCTransport(addAuthTransport,CompressedTransport): + pass + +class HTTPSConnection(httplib.HTTPSConnection): + certs_file = None + def connect(self): + "Connect to a host on a given (SSL) port. check the certificate" + import socket, ssl + + if HTTPSConnection.certs_file: + ca_certs = HTTPSConnection.certs_file + cert_reqs = ssl.CERT_REQUIRED + else: + ca_certs = None + cert_reqs = ssl.CERT_NONE + sock = socket.create_connection((self.host, self.port), self.timeout) + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + ca_certs=ca_certs, + cert_reqs=cert_reqs) + + + def getpeercert(self): + import ssl + cert = None + if self.sock: + cert = self.sock.getpeercert() + else: + cert = ssl.get_server_certificate((self.host,self.port), + ssl_version=ssl.PROTOCOL_SSLv23 ) + lf = (len(ssl.PEM_FOOTER)+1) + if cert[0-lf] != '\n': + cert = cert[:0-lf]+'\n'+cert[0-lf:] + log.debug("len-footer: %s cert: %r", lf, cert[0-lf]) + + return cert + + +class DAVClient(object): + """An instance of a WebDAV client, connected to the OpenERP server + """ + + def __init__(self, user=None, passwd=None, dbg=0, use_ssl=False, useragent=False): + if use_ssl: + self.host = config.get_misc('httpsd', 'interface', False) + self.port = config.get_misc('httpsd', 'port', 8071) + if not self.host: + self.host = config.get('xmlrpcs_interface') + self.port = config.get('xmlrpcs_port') + else: + self.host = config.get_misc('httpd', 'interface') + self.port = config.get_misc('httpd', 'port', 8069) + if not self.host: + self.host = config.get('xmlrpc_interface') + self.port = config.get('xmlrpc_port') or self.port + if self.host == '0.0.0.0' or not self.host: + self.host = '127.0.0.1' + self.port = int(self.port) + if not config.get_misc('webdav','enable',True): + raise Exception("WebDAV is disabled, cannot continue") + self.davpath = '/' + config.get_misc('webdav','vdir','webdav') + self.user = user + self.passwd = passwd + self.dbg = dbg + self.hdrs = {} + if useragent: + self.set_useragent(useragent) + + def get_creds(self, obj, cr, uid): + """Read back the user credentials from cr, uid + + @param obj is any orm object, in order to use its pool + @param uid is the numeric id, which we will try to reverse resolve + + note: this is a hackish way to get the credentials. It is expected + to break if "base_crypt" is used. + """ + ruob = obj.pool.get('res.users') + res = ruob.read(cr, 1, [uid,], ['login', 'password']) + assert res, "uid %s not found" % uid + self.user = res[0]['login'] + self.passwd = res[0]['password'] + return True + + def set_useragent(self, uastr): + """ Set the user-agent header to something meaningful. + Some shorthand names will be replaced by stock strings. + """ + if uastr in ('KDE4', 'Korganizer'): + self.hdrs['User-Agent'] = "Mozilla/5.0 (compatible; Konqueror/4.4; Linux) KHTML/4.4.3 (like Gecko)" + elif uastr == 'iPhone3': + self.hdrs['User-Agent'] = "DAVKit/5.0 (765); iCalendar/5.0 (79); iPhone/4.1 8B117" + elif uastr == "MacOS": + self.hdrs['User-Agent'] = "WebDAVFS/1.8 (01808000) Darwin/9.8.0 (i386)" + else: + self.hdrs['User-Agent'] = uastr + + def _http_request(self, path, method='GET', hdrs=None, body=None): + if not hdrs: + hdrs = {} + import base64 + dbg = self.dbg + hdrs.update(self.hdrs) + log.debug("Getting %s http://%s:%d/%s", method, self.host, self.port, path) + conn = httplib.HTTPConnection(self.host, port=self.port) + conn.set_debuglevel(dbg) + if not path: + path = "/index.html" + if not hdrs.has_key('Connection'): + hdrs['Connection']= 'keep-alive' + conn.request(method, path, body, hdrs ) + try: + r1 = conn.getresponse() + except httplib.BadStatusLine, bsl: + log.warning("Bad status line: %s", bsl.line) + raise Exception('Bad status line') + if r1.status == 401: # and r1.headers: + if 'www-authenticate' in r1.msg: + (atype,realm) = r1.msg.getheader('www-authenticate').split(' ',1) + data1 = r1.read() + if not self.user: + raise Exception('Must auth, have no user/pass!') + log.debug("Ver: %s, closed: %s, will close: %s", r1.version,r1.isclosed(), r1.will_close) + log.debug("Want to do auth %s for realm %s", atype, realm) + if atype == 'Basic' : + auths = base64.encodestring(self.user + ':' + self.passwd) + if auths[-1] == "\n": + auths = auths[:-1] + hdrs['Authorization']= 'Basic '+ auths + #sleep(1) + conn.request(method, path, body, hdrs ) + r1 = conn.getresponse() + else: + raise Exception("Unknown auth type %s" %atype) + else: + log.warning("Got 401, cannot auth") + raise Exception('No auth') + + log.debug("Reponse: %s %s",r1.status, r1.reason) + data1 = r1.read() + if method != 'GET': + log.debug("Body:\n%s\nEnd of body", data1) + try: + ctype = r1.msg.getheader('content-type') + if ctype and ';' in ctype: + ctype, encoding = ctype.split(';',1) + if ctype == 'text/xml': + doc = xml.dom.minidom.parseString(data1) + log.debug("XML Body:\n %s", doc.toprettyxml(indent="\t")) + except Exception: + log.warning("could not print xml", exc_info=True) + pass + conn.close() + return r1.status, r1.msg, data1 + + def _assert_headers(self, expect, msg): + """ Assert that the headers in msg contain the expect values + """ + for k, v in expect.items(): + hval = msg.getheader(k) + if not hval: + raise AssertionError("Header %s not defined in http response" % k) + if isinstance(v, (list, tuple)): + delim = ',' + hits = map(str.strip, hval.split(delim)) + mvits= [] + for vit in v: + if vit not in hits: + mvits.append(vit) + if mvits: + raise AssertionError("HTTP header \"%s\" is missing: %s" %(k, ', '.join(mvits))) + else: + if hval.strip() != v.strip(): + raise AssertionError("HTTP header \"%s: %s\"" % (k, hval)) + + def gd_options(self, path='*', expect=None): + """ Test the http options functionality + If a dictionary is defined in expect, those options are + asserted. + """ + if path != '*': + path = self.davpath + path + hdrs = { 'Content-Length': 0 + } + s, m, d = self._http_request(path, method='OPTIONS', hdrs=hdrs) + assert s == 200, "Status: %r" % s + assert 'OPTIONS' in m.getheader('Allow') + log.debug('Options: %r', m.getheader('Allow')) + + if expect: + self._assert_headers(expect, m) + + def _parse_prop_response(self, data): + """ Parse a propfind/propname response + """ + def getText(node): + rc = [] + for node in node.childNodes: + if node.nodeType == node.TEXT_NODE: + rc.append(node.data) + return ''.join(rc) + + def getElements(node, namespaces=None, strict=False): + for cnod in node.childNodes: + if cnod.nodeType != node.ELEMENT_NODE: + if strict: + log.debug("Found %r inside <%s>", cnod, node.tagName) + continue + if namespaces and (cnod.namespaceURI not in namespaces): + log.debug("Ignoring <%s> in <%s>", cnod.tagName, node.localName) + continue + yield cnod + + nod = xml.dom.minidom.parseString(data) + nod_r = nod.documentElement + res = {} + assert nod_r.localName == 'multistatus', nod_r.tagName + for resp in nod_r.getElementsByTagNameNS('DAV:', 'response'): + href = None + status = 200 + res_nss = {} + for cno in getElements(resp, namespaces=['DAV:',]): + if cno.localName == 'href': + assert href is None, "Second href in same response" + href = getText(cno) + elif cno.localName == 'propstat': + for pno in getElements(cno, namespaces=['DAV:',]): + rstatus = None + if pno.localName == 'prop': + for prop in getElements(pno): + key = prop.localName + tval = getText(prop).strip() + val = tval or (True, rstatus or status) + if prop.namespaceURI == 'DAV:' and prop.localName == 'resourcetype': + val = 'plain' + for rte in getElements(prop, namespaces=['DAV:',]): + # Note: we only look at DAV:... elements, we + # actually expect only one DAV:collection child + val = rte.localName + res_nss.setdefault(prop.namespaceURI,{})[key] = val + elif pno.localName == 'status': + rstr = getText(pno) + htver, sta, msg = rstr.split(' ', 3) + assert htver == 'HTTP/1.1' + rstatus = int(sta) + else: + log.debug("What is <%s> inside a <propstat>?", pno.tagName) + + else: + log.debug("Unknown node: %s", cno.tagName) + + res.setdefault(href,[]).append((status, res_nss)) + + return res + + def gd_propfind(self, path, props=None, depth=0): + if not props: + propstr = '<allprop/>' + else: + propstr = '<prop>' + nscount = 0 + for p in props: + ns = None + if isinstance(p, tuple): + p, ns = p + if ns is None or ns == 'DAV:': + propstr += '<%s/>' % p + else: + propstr += '<ns%d:%s xmlns:ns%d="%s" />' %(nscount, p, nscount, ns) + nscount += 1 + propstr += '</prop>' + + body="""<?xml version="1.0" encoding="utf-8"?> + <propfind xmlns="DAV:">%s</propfind>""" % propstr + hdrs = { 'Content-Type': 'text/xml; charset=utf-8', + 'Accept': 'text/xml', + 'Depth': depth, + } + + s, m, d = self._http_request(self.davpath + path, method='PROPFIND', + hdrs=hdrs, body=body) + assert s == 207, "Bad status: %s" % s + ctype = m.getheader('Content-Type').split(';',1)[0] + assert ctype == 'text/xml', m.getheader('Content-Type') + res = self._parse_prop_response(d) + if depth == 0: + assert len(res) == 1 + res = res.values()[0] + else: + assert len(res) >= 1 + return res + + + def gd_propname(self, path, depth=0): + body="""<?xml version="1.0" encoding="utf-8"?> + <propfind xmlns="DAV:"><propname/></propfind>""" + hdrs = { 'Content-Type': 'text/xml; charset=utf-8', + 'Accept': 'text/xml', + 'Depth': depth + } + s, m, d = self._http_request(self.davpath + path, method='PROPFIND', + hdrs=hdrs, body=body) + assert s == 207, "Bad status: %s" % s + ctype = m.getheader('Content-Type').split(';',1)[0] + assert ctype == 'text/xml', m.getheader('Content-Type') + res = self._parse_prop_response(d) + if depth == 0: + assert len(res) == 1 + res = res.values()[0] + else: + assert len(res) >= 1 + return res + + def gd_getetag(self, path, depth=0): + return self.gd_propfind(path, props=['getetag',], depth=depth) + + def gd_lsl(self, path): + """ Return a list of 'ls -l' kind of data for a folder + + This is based on propfind. + """ + + lspairs = [ ('name', 'displayname', 'n/a'), ('size', 'getcontentlength', '0'), + ('type', 'resourcetype', '----------'), ('uid', 'owner', 'nobody'), + ('gid', 'group', 'nogroup'), ('mtime', 'getlastmodified', 'n/a'), + ('mime', 'getcontenttype', 'application/data'), ] + + propnames = [ l[1] for l in lspairs] + propres = self.gd_propfind(path, props=propnames, depth=1) + + res = [] + for href, pr in propres.items(): + lsline = {} + for st, nsdic in pr: + davprops = nsdic['DAV:'] + if st == 200: + for lsp in lspairs: + if lsp[1] in davprops: + if lsp[1] == 'resourcetype': + if davprops[lsp[1]] == 'collection': + lsline[lsp[0]] = 'dr-xr-x---' + else: + lsline[lsp[0]] = '-r-xr-x---' + else: + lsline[lsp[0]] = davprops[lsp[1]] + elif st in (404, 403): + for lsp in lspairs: + if lsp[1] in davprops: + lsline[lsp[0]] = lsp[2] + else: + log.debug("Strange status: %s", st) + + res.append(lsline) + + return res + + def gd_get(self, path, crange=None, mime=None, compare=None): + """ HTTP GET for path, supporting Partial ranges + """ + hdrs = { 'Accept': mime or '*/*', } + if crange: + if isinstance(crange, tuple): + crange = [crange,] + if not isinstance(crange, list): + raise TypeError("Range must be a tuple or list of tuples") + rs = [] + for r in crange: + rs.append('%d-%d' % r) + hdrs['Range'] = 'bytes='+ (','.join(rs)) + s, m, d = self._http_request(self.davpath + path, method='GET', hdrs=hdrs) + assert s in (200, 206), "Bad status: %s" % s + ctype = m.getheader('Content-Type') + if ctype and ';' in ctype: + ctype = ctype.split(';',1)[0] + if mime: + assert ctype == mime, m.getheader('Content-Type') + rrange = None + rrh = m.getheader('Content-Range') + if rrh: + assert rrh.startswith('bytes '), rrh + rrh=rrh[6:].split('/',1)[0] + rrange = map(int, rrh.split('-',1)) + if compare: + # we need to compare the returned data with that of compare + fd = open(compare, 'rb') + d2 = fd.read() + fd.close() + if crange: + if len(crange) > 1: + raise NotImplementedError + r = crange[0] + d2 = d2[r[0]:r[1]+1] + assert d2 == d, "Data does not match" + return ctype, rrange, d + + def gd_put(self, path, body=None, srcpath=None, mime=None, noclobber=False, ): + """ HTTP PUT + @param noclobber will prevent overwritting a resource (If-None-Match) + @param mime will set the content-type + """ + hdrs = { } + if not (body or srcpath): + raise ValueError("PUT must have something to send") + if (not body) and srcpath: + fd = open(srcpath, 'rb') + body = fd.read() + fd.close() + if mime: + hdrs['Content-Type'] = mime + if noclobber: + hdrs['If-None-Match'] = '*' + s, m, d = self._http_request(self.davpath + path, method='PUT', + hdrs=hdrs, body=body) + assert s == (201), "Bad status: %s" % s + etag = m.getheader('ETag') + return etag or True + +#eof
\ No newline at end of file diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py index df2c4a871f6..0e5973c95b3 100644 --- a/addons/document_webdav/webdav_server.py +++ b/addons/document_webdav/webdav_server.py @@ -28,7 +28,6 @@ import netsvc -import tools from dav_fs import openerp_dav_handler from tools.config import config from DAV.WebDAVServer import DAVRequestHandler @@ -36,10 +35,13 @@ from service.websrv_lib import HTTPDir, FixSendError, HttpOptions from BaseHTTPServer import BaseHTTPRequestHandler import urlparse import urllib -from string import atoi,split +import re +from string import atoi from DAV.errors import * # from DAV.constants import DAV_VERSION_1, DAV_VERSION_2 +khtml_re = re.compile(r' KHTML/([0-9\.]+) ') + def OpenDAVConfig(**kw): class OpenDAV: def __init__(self, **kw): @@ -96,7 +98,6 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler): """ Our uri scheme removes the /webdav/ component from there, so we need to mangle the header, too. """ - dest = self.headers['Destination'] up = urlparse.urlparse(urllib.unquote(self.headers['Destination'])) if up.path.startswith(self.davpath): self.headers['Destination'] = up.path[len(self.davpath):] @@ -131,6 +132,16 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler): # the BufferingHttpServer will send Connection: close , while # the BaseHTTPRequestHandler will only accept int code. # workaround both of them. + if self.command == 'PROPFIND' and int(code) == 404: + kh = khtml_re.search(self.headers.get('User-Agent','')) + if kh and (kh.group(1) < '4.5'): + # There is an ugly bug in all khtml < 4.5.x, where the 404 + # response is treated as an immediate error, which would even + # break the flow of a subsequent PUT request. At the same time, + # the 200 response (rather than 207 with content) is treated + # as "path not exist", so we send this instead + # https://bugs.kde.org/show_bug.cgi?id=166081 + code = 200 BaseHTTPRequestHandler.send_response(self, int(code), message) def send_header(self, key, value): @@ -216,7 +227,7 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler): try: location = dc.put(uri, body, ct) except DAV_Error, (ec,dd): - self._logger.warning("Cannot PUT to %s: %s", uri, dd, exc_info=True) + self.log_error("Cannot PUT to %s: %s", uri, dd) return self.send_status(ec) headers = {} diff --git a/addons/document_webdav/webdav_setup.xml b/addons/document_webdav/webdav_setup.xml index 2bd41ddb69c..6ea894b6a22 100644 --- a/addons/document_webdav/webdav_setup.xml +++ b/addons/document_webdav/webdav_setup.xml @@ -12,7 +12,7 @@ <field name="domain">[]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field name="storage_id" ref="document.storage_default"/> <field name="type">directory</field> @@ -24,7 +24,7 @@ <field name="domain">[]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_principals0"/> <field name="storage_id" ref="document.storage_default"/> @@ -45,9 +45,10 @@ <field name="name">resources</field> </record> <record id="document_directory_uids1" model="document.directory"> - <field name="domain">[]</field> + <field name="domain">[('id','=',uid)]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> + <field name="user_id" eval="False"/> <field name="resource_field" ref="base.field_res_users_login"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_principals0"/> @@ -58,10 +59,10 @@ <field name="name">__uids__</field> </record> <record id="document_directory_users1" model="document.directory"> - <field name="domain">[]</field> + <field name="domain">[('id','=',uid)]</field> <field eval="1" name="resource_find_all"/> <field eval="0" name="ressource_tree"/> - <field name="user_id" ref="base.user_root"/> + <field name="user_id" eval="False"/> <field name="resource_field" ref="base.field_res_users_login"/> <field name="company_id" ref="base.main_company"/> <field model="document.directory" name="parent_id" ref="document_directory_principals0"/> diff --git a/addons/event/wizard/event_confirm_registration.py b/addons/event/wizard/event_confirm_registration.py index 6527a602444..a2fe8170bfd 100644 --- a/addons/event/wizard/event_confirm_registration.py +++ b/addons/event/wizard/event_confirm_registration.py @@ -48,7 +48,6 @@ class event_confirm_registration(osv.osv_memory): msg = "" overlimit_event_ids = [] for registration in registration_pool.browse(cr, uid, registration_ids, context=context): - total_confirmed = registration.event_id.register_current register_max = registration.event_id.register_max if registration.event_id.id not in overlimit_event_ids: overlimit_event_ids.append(registration.event_id.id) diff --git a/addons/event/wizard/event_make_invoice.py b/addons/event/wizard/event_make_invoice.py index 7d9dee61cdd..73a0acff104 100644 --- a/addons/event/wizard/event_make_invoice.py +++ b/addons/event/wizard/event_make_invoice.py @@ -68,7 +68,6 @@ class event_make_invoice(osv.osv_memory): def make_invoice(self, cr, uid, ids, context=None): reg_obj = self.pool.get('event.registration') mod_obj = self.pool.get('ir.model.data') - newinv = [] if context is None: context = {} diff --git a/addons/fetchmail/__init__.py b/addons/fetchmail/__init__.py index 0f50df83255..d58bfd1d81b 100644 --- a/addons/fetchmail/__init__.py +++ b/addons/fetchmail/__init__.py @@ -7,16 +7,16 @@ # mga@tinyerp.com # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/fetchmail/__openerp__.py b/addons/fetchmail/__openerp__.py index e9050fda075..8fe375997aa 100644 --- a/addons/fetchmail/__openerp__.py +++ b/addons/fetchmail/__openerp__.py @@ -7,16 +7,16 @@ # mga@tinyerp.com # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/fetchmail/fetchmail.py b/addons/fetchmail/fetchmail.py index 0f58419d1e1..77748adf017 100644 --- a/addons/fetchmail/fetchmail.py +++ b/addons/fetchmail/fetchmail.py @@ -42,7 +42,7 @@ class email_server(osv.osv): 'active':fields.boolean('Active', required=False), 'state':fields.selection([ ('draft', 'Not Confirmed'), - ('wating', 'Waiting for Verification'), + ('waiting', 'Waiting for Verification'), ('done', 'Confirmed'), ], 'State', select=True, readonly=True), 'server' : fields.char('Server', size=256, required=True, readonly=True, states={'draft':[('readonly', False)]}), @@ -52,15 +52,17 @@ class email_server(osv.osv): ('imap', 'IMAP Server'), ], 'Server Type', select=True, readonly=False), 'is_ssl':fields.boolean('SSL ?', required=False), - 'attach':fields.boolean('Add Attachments ?', required=False), + 'attach':fields.boolean('Add Attachments ?', required=False, help="Fetches mail with attachments if true."), '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'), - 'action_id':fields.many2one('ir.actions.server', 'Reply Email', required=False, domain="[('state','=','email')]"), - 'object_id': fields.many2one('ir.model', "Model", required=True), + 'action_id':fields.many2one('ir.actions.server', 'Reply Email', required=False, domain="[('state','=','email')]", + help="An Email Server Action. It will be run whenever an e-mail is fetched from server."), + 'object_id': fields.many2one('ir.model', "Model", required=True, help="OpenObject Model. Generates a record of this model."), 'priority': fields.integer('Server Priority', readonly=True, states={'draft':[('readonly', False)]}, help="Priority between 0 to 10, select define the order of Processing"), 'user_id':fields.many2one('res.users', 'User', required=False), + 'message_ids': fields.one2many('mailgate.message', 'server_id', 'Messages', readonly=True), } _defaults = { 'state': lambda *a: "draft", @@ -96,20 +98,8 @@ class email_server(osv.osv): 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) - return True - - def _fetch_mails(self, cr, uid, ids=False, context={}): - if not ids: - ids = self.search(cr, uid, []) - return self.fetch_mail(cr, uid, ids, context) - - def fetch_mail(self, cr, uid, ids, context=None): - if not context: - context = {} - email_tool = self.pool.get('email.server.tools') + + def button_confirm_login(self, cr, uid, ids, context={}): for server in self.browse(cr, uid, ids, context): logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail start checking for new emails on %s' % (server.name)) context.update({'server_id': server.id, 'server_type': server.type}) @@ -123,13 +113,52 @@ class email_server(osv.osv): imap_server = IMAP4(server.server, int(server.port)) imap_server.login(server.user, server.password) + ret_server = imap_server + + elif server.type == 'pop': + pop_server = None + if server.is_ssl: + pop_server = POP3_SSL(server.server, int(server.port)) + else: + pop_server = POP3(server.server, int(server.port)) + + #TODO: use this to remove only unread messages + #pop_server.user("recent:"+server.user) + pop_server.user(server.user) + pop_server.pass_(server.password) + ret_server = pop_server + + self.write(cr, uid, [server.id], {'state':'done'}) + if context.get('get_server',False): + return ret_server + except Exception, e: + logger.notifyChannel(server.type, netsvc.LOG_WARNING, '%s' % (e)) + return True + + def button_fetch_mail(self, cr, uid, ids, context={}): + self.fetch_mail(cr, uid, ids, context=context) + return True + + def _fetch_mails(self, cr, uid, ids=False, context={}): + if not ids: + ids = self.search(cr, uid, []) + return self.fetch_mail(cr, uid, ids, context=context) + + def fetch_mail(self, cr, uid, ids, context={}): + email_tool = self.pool.get('email.server.tools') + action_pool = self.pool.get('ir.actions.server') + context.update({'get_server': True}) + for server in self.browse(cr, uid, ids, context): + count = 0 + try: + if server.type == 'imap': + imap_server = self.button_confirm_login(cr, uid, [server.id], context=context) imap_server.select() result, data = imap_server.search(None, '(UNSEEN)') for num in data[0].split(): result, data = imap_server.fetch(num, '(RFC822)') res_id = email_tool.process_email(cr, uid, server.object_id.model, data[0][1], attach=server.attach, context=context) if res_id and server.action_id: - action_pool = self.pool.get('ir.actions.server') action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]}) imap_server.store(num, '+FLAGS', '\\Seen') @@ -139,25 +168,14 @@ class email_server(osv.osv): imap_server.close() imap_server.logout() elif server.type == 'pop': - pop_server = None - if server.is_ssl: - pop_server = POP3_SSL(server.server, int(server.port)) - else: - pop_server = POP3(server.server, int(server.port)) - - #TODO: use this to remove only unread messages - #pop_server.user("recent:"+server.user) - pop_server.user(server.user) - pop_server.pass_(server.password) + pop_server = self.button_confirm_login(cr, uid, [server.id], context=context) pop_server.list() - (numMsgs, totalSize) = pop_server.stat() for num in range(1, numMsgs + 1): (header, msges, octets) = pop_server.retr(num) msg = '\n'.join(msges) res_id = email_tool.process_email(cr, uid, server.object_id.model, msg, attach=server.attach, context=context) if res_id and server.action_id: - action_pool = self.pool.get('ir.actions.server') action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]}) pop_server.dele(num) @@ -166,7 +184,6 @@ class email_server(osv.osv): logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail fetch %s email(s) from %s' % (numMsgs, server.name)) - self.write(cr, uid, [server.id], {'state':'done'}) except Exception, e: logger.notifyChannel(server.type, netsvc.LOG_WARNING, '%s' % (e)) diff --git a/addons/fetchmail/fetchmail_view.xml b/addons/fetchmail/fetchmail_view.xml index 7f751f7c5a2..ecdb4acfb3b 100644 --- a/addons/fetchmail/fetchmail_view.xml +++ b/addons/fetchmail/fetchmail_view.xml @@ -8,11 +8,13 @@ <field name="type">tree</field> <field name="arch" type="xml"> <tree colors="blue:state in ('draft');black:state in ('wating');gray:state in('done')" string="POP/IMAP Servers"> - <field name="name" select="1"/> - <field name="type" select="1"/> - <field name="user" select="1"/> - <field name="is_ssl" select="1"/> - <field name="state" select="1"/> + <field name="name"/> + <field name="type"/> + <field name="user"/> + <field name="is_ssl"/> + <field name="object_id"/> + <field name="message_ids" string="# of emails"/> + <field name="state"/> </tree> </field> </record> @@ -58,99 +60,99 @@ </notebook> <group col="6" colspan="4"> <field name="state" select="1"/> - <button string="Fetch Emails" type="object" name="button_fetch_mail"/> + <button string="Confirm" type="object" name="button_confirm_login" states="draft"/> + <button string="Fetch Emails" type="object" name="button_fetch_mail" states="done"/> <button string="Set to Draft" type="object" name="set_draft"/> </group> </form> </field> </record> + <record model="ir.ui.view" id="view_email_server_search"> + <field name="name">email.server.search</field> + <field name="model">email.server</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Search Email Servers"> + <filter string="IMAP" icon="terp-folder-green" domain="[('type','=','imap')]" help="Server type IMAP."/> + <filter string="POP" icon="terp-folder-orange" domain="[('type','=','pop')]" help="Server type POP."/> + <separator orientation="vertical"/> + <filter string="SSL" icon="terp-camera_test" domain="[('is_ssl','=',True)]" help="If SSL required."/> + <separator orientation="vertical"/> + <field name="name"/> + <field name="object_id"/> + <newline/> + <group expand="0" string="Group By..." groups="base.group_extended"> + <filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}"/> + <separator orientation="vertical"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + </group> + </search> + </field> + </record> + <record model="ir.actions.act_window" id="action_email_server_tree"> - <field name="name">POP Servers</field> + <field name="name">Email Servers</field> <field name="res_model">email.server</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> <field name="view_id" ref="view_email_server_tree"/> - <field name="context">{'type':'pop'}</field> - <field name="domain">[('type','=','pop')]</field> + <field name="search_view_id" ref="view_email_server_search"/> </record> <menuitem - parent="base.menu_config" - id="menu_action_fetchmail_server_tree" - name="Fetchmail Services" - /> - - <menuitem - parent="menu_action_fetchmail_server_tree" - id="menu_action_email_server_tree" - action="action_email_server_tree" + parent="base.menu_mail_gateway" + id="menu_action_fetchmail_server_tree" + action="action_email_server_tree" + name="Email Servers" /> - <record model="ir.actions.act_window" id="action_email_server_tree_imap"> - <field name="name">IMAP Servers</field> - <field name="res_model">email.server</field> + <record model="ir.ui.view" id="mailgate_message_tree_view"> + <field name="name">mailgate.message.tree</field> + <field name="model">mailgate.message</field> + <field name="type">tree</field> + <field name="inherit_id" ref="mail_gateway.view_mailgate_message_tree"/> + <field name="arch" type="xml"> + <field name="user_id" position="after"> + <field name="server_id" select="1"/> + <field name="ref_id"/> + </field> + </field> + </record> + + <record model="ir.ui.view" id="mailgate_message_search_view"> + <field name="name">mailgate.message.inherit.search</field> + <field name="model">mailgate.message</field> + <field name="type">search</field> + <field name="inherit_id" ref="mail_gateway.view_mailgate_message_search"/> + <field name="arch" type="xml"> + <xpath expr="/search/field[@name='name']" position="before"> + <filter string="Emails" name="emails" domain="[('server_id','!=',False)]" icon="terp-mail-message-new"/> + <separator orientation="vertical"/> + </xpath> + <xpath expr="/search/group/filter[@string='Thread']" position="before"> + <filter string="Mail Server" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'server_id'}"/> + </xpath> + </field> + </record> + + <record id="action_view_mail_message_emails" model="ir.actions.act_window"> + <field name="name">Messages</field> + <field name="res_model">mailgate.message</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> - <field name="view_id" ref="view_email_server_tree"/> - <field name="context">{'type':'imap'}</field> - <field name="domain">[('type','=','imap')]</field> - </record> - - <menuitem - parent="menu_action_fetchmail_server_tree" - id="menu_action_email_server_tree_imap" - action="action_email_server_tree_imap" - /> + <field name="context">{'search_default_emails': 1}</field> + <field name="search_view_id" ref="mailgate_message_search_view"/> + </record> - <record model="ir.ui.view" id="mailgate_message_tree_view"> - <field name="name">mailgate.message.tree</field> - <field name="model">mailgate.message</field> - <field name="type">tree</field> - <field name="inherit_id" ref="mail_gateway.view_mailgate_message_tree"/> - <field name="arch" type="xml"> - <field name="user_id" position="after"> - <field name="server_id" select="1"/> - <field name="ref_id"/> - </field> - </field> - </record> + <menuitem id="base.menu_email_gateway_form" + parent="base.menu_mail_gateway" action="action_view_mail_message_emails" /> - <act_window + <act_window context="{'server_id': active_id}" domain="[('server_id', '=', active_id)]" - id="act_server_history" name="Email History" + id="act_server_history" name="Emails" res_model="mailgate.message" src_model="email.server"/> - <record model="ir.actions.act_window" id="action_mailgate_message_tree"> - <field name="name">Received Email History</field> - <field name="res_model">mailgate.message</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form</field> - <field name="view_id" ref="mailgate_message_tree_view"/> - <field name="context">{'server_type':'imap'}</field> - <field name="domain">[('server_type','=','imap')]</field> - </record> - - <menuitem - parent="menu_action_email_server_tree_imap" - id="menu_action_mailgate_message_tree" - action="action_mailgate_message_tree"/> - - <record model="ir.actions.act_window" id="action_mailgate_message_tree_pop"> - <field name="name">Received Email History</field> - <field name="res_model">mailgate.message</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form</field> - <field name="view_id" ref="mailgate_message_tree_view"/> - <field name="context">{'server_type':'pop'}</field> - <field name="domain">[('server_type','=','pop')]</field> - </record> - - <menuitem - parent="menu_action_email_server_tree" - id="menu_action_mailgate_message_tree_pop" - action="action_mailgate_message_tree_pop"/> - </data> </openerp> diff --git a/addons/hr_payroll/__init__.py b/addons/hr_payroll/__init__.py index c66b5ab7948..bf7fc8a67e4 100644 --- a/addons/hr_payroll/__init__.py +++ b/addons/hr_payroll/__init__.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/__openerp__.py b/addons/hr_payroll/__openerp__.py index 65b593c5891..7d66f25b445 100644 --- a/addons/hr_payroll/__openerp__.py +++ b/addons/hr_payroll/__openerp__.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py index aaad03d1de7..54b16442699 100644 --- a/addons/hr_payroll/hr_payroll.py +++ b/addons/hr_payroll/hr_payroll.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/__init__.py b/addons/hr_payroll/report/__init__.py index 925b5e4c97d..3113f281326 100755 --- a/addons/hr_payroll/report/__init__.py +++ b/addons/hr_payroll/report/__init__.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_emp_salary_structure.py b/addons/hr_payroll/report/report_emp_salary_structure.py index 6d22ab2a2a2..0da09d16562 100644 --- a/addons/hr_payroll/report/report_emp_salary_structure.py +++ b/addons/hr_payroll/report/report_emp_salary_structure.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_employees_detail.py b/addons/hr_payroll/report/report_employees_detail.py index 6b6f83a6257..0ee57545daf 100644 --- a/addons/hr_payroll/report/report_employees_detail.py +++ b/addons/hr_payroll/report/report_employees_detail.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_payroll_advice.py b/addons/hr_payroll/report/report_payroll_advice.py index 71955a9330f..d5019a82c50 100644 --- a/addons/hr_payroll/report/report_payroll_advice.py +++ b/addons/hr_payroll/report/report_payroll_advice.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_payroll_register.py b/addons/hr_payroll/report/report_payroll_register.py index a67fc1e6b70..9410a4eedb2 100644 --- a/addons/hr_payroll/report/report_payroll_register.py +++ b/addons/hr_payroll/report/report_payroll_register.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_payslip.py b/addons/hr_payroll/report/report_payslip.py index d2804a764de..9eb5204624b 100755 --- a/addons/hr_payroll/report/report_payslip.py +++ b/addons/hr_payroll/report/report_payslip.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/report_year_salary.py b/addons/hr_payroll/report/report_year_salary.py index b1f11b417fc..a11e1aa44ad 100755 --- a/addons/hr_payroll/report/report_year_salary.py +++ b/addons/hr_payroll/report/report_year_salary.py @@ -8,16 +8,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/report/rml_parse.py b/addons/hr_payroll/report/rml_parse.py index b74a62e955d..b8a1791768e 100755 --- a/addons/hr_payroll/report/rml_parse.py +++ b/addons/hr_payroll/report/rml_parse.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll/wizard/__init__.py b/addons/hr_payroll/wizard/__init__.py index 4fb72fb4695..2cf78e17b1c 100755 --- a/addons/hr_payroll/wizard/__init__.py +++ b/addons/hr_payroll/wizard/__init__.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll_account/__init__.py b/addons/hr_payroll_account/__init__.py index de1b7b6c0ba..ee7125d5411 100644 --- a/addons/hr_payroll_account/__init__.py +++ b/addons/hr_payroll_account/__init__.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll_account/__openerp__.py b/addons/hr_payroll_account/__openerp__.py index 563f1b52bc1..e3ebdf625e7 100644 --- a/addons/hr_payroll_account/__openerp__.py +++ b/addons/hr_payroll_account/__openerp__.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_payroll_account/hr_payroll_account.py b/addons/hr_payroll_account/hr_payroll_account.py index 0d5b315df62..71dfa3cad0f 100644 --- a/addons/hr_payroll_account/hr_payroll_account.py +++ b/addons/hr_payroll_account/hr_payroll_account.py @@ -6,16 +6,16 @@ # d$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_recruitment/__init__.py b/addons/hr_recruitment/__init__.py index 2619a3139f2..643a15e94f1 100644 --- a/addons/hr_recruitment/__init__.py +++ b/addons/hr_recruitment/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_recruitment/__openerp__.py b/addons/hr_recruitment/__openerp__.py index 69bdd97da58..9d38657bc98 100644 --- a/addons/hr_recruitment/__openerp__.py +++ b/addons/hr_recruitment/__openerp__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_recruitment/report/__init__.py b/addons/hr_recruitment/report/__init__.py index 86094f98916..c7bd37be09a 100644 --- a/addons/hr_recruitment/report/__init__.py +++ b/addons/hr_recruitment/report/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py b/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py index 28de96db4e4..dd1667aecef 100644 --- a/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py +++ b/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py index 0f557d8b3bf..08d749ecfd1 100644 --- a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py +++ b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/idea/security/idea_security.xml b/addons/idea/security/idea_security.xml index 4b060c51e6c..40e16cc2b17 100644 --- a/addons/idea/security/idea_security.xml +++ b/addons/idea/security/idea_security.xml @@ -8,6 +8,10 @@ <record model="res.groups" id="base.group_tool_user"> <field name="name">Tools / User</field> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('base.group_tool_user'))]"/> + </record> </data> </openerp> diff --git a/addons/knowledge/security/knowledge_security.xml b/addons/knowledge/security/knowledge_security.xml index b4c7bb99c1b..d0afba371a9 100644 --- a/addons/knowledge/security/knowledge_security.xml +++ b/addons/knowledge/security/knowledge_security.xml @@ -8,6 +8,10 @@ <record id="base.group_document_user" model="res.groups"> <field name="name">Knowledge / User</field> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('base.group_document_user'))]"/> + </record> </data> </openerp> diff --git a/addons/lunch/security/lunch_security.xml b/addons/lunch/security/lunch_security.xml index 0014f38182b..b4c184b3482 100644 --- a/addons/lunch/security/lunch_security.xml +++ b/addons/lunch/security/lunch_security.xml @@ -8,6 +8,10 @@ <record model="res.groups" id="base.group_tool_user"> <field name="name">Tools / User</field> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('base.group_tool_user'))]"/> + </record> </data> </openerp> diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py index a116a18b56d..696c7571cfb 100644 --- a/addons/mail_gateway/mail_gateway.py +++ b/addons/mail_gateway/mail_gateway.py @@ -250,6 +250,8 @@ class mailgate_message(osv.osv): elif message.name == _('Note'): msg_txt = (message.user_id.name or '/') + _(' added note on ') + format_date_tz(message.date, tz) + ':\n\t' msg_txt += self.truncate_data(cr, uid, message.description, context=context) + elif message.name == _('Stage'): + msg_txt += _("Changed Stage to: ") + message.description else: msg_txt += _("Changed Status to: ") + message.name result[message.id] = msg_txt diff --git a/addons/mail_gateway/mail_gateway_view.xml b/addons/mail_gateway/mail_gateway_view.xml index f3be1eff422..b2aaab21a36 100644 --- a/addons/mail_gateway/mail_gateway_view.xml +++ b/addons/mail_gateway/mail_gateway_view.xml @@ -2,7 +2,7 @@ <openerp> <data> - <menuitem id="base.menu_mail_gateway" name="Email" + <menuitem id="base.menu_mail_gateway" name="Emails" parent="base.menu_base_config" sequence="1" /> <record model="ir.ui.view" id="view_mailgate_message_form"> @@ -93,7 +93,7 @@ <record id="action_view_mail_message" model="ir.actions.act_window"> - <field name="name">Message</field> + <field name="name">Messages</field> <field name="res_model">mailgate.message</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> @@ -213,7 +213,7 @@ src_model="mailgate.message" domain="[('res_id', '=', res_id),('res_model','=',model)]"/> - <menuitem id="menu_email_gateway_form" + <menuitem id="base.menu_email_gateway_form" parent="base.menu_mail_gateway" action="action_view_mail_message" /> </data> diff --git a/addons/outlook/README b/addons/outlook/README index adfd4401cb3..a737a700496 100644 --- a/addons/outlook/README +++ b/addons/outlook/README @@ -2,31 +2,22 @@ OpenERP Outlook PLUG-IN Installation Guide Pre requirements : ====================================================================================== -1.Python 2.6+ . python can be downloaded from http://www.python.org/download/releases/ . -2.Python for Windows extensions - PyWin32 this module for python must be installed for appropriate version of the Python. It can be downloaded from http://sourceforge.net/projects/pywin32/files/ or http://starship.python.net/crew/mhammond/win32/ -3.If you are using MS Outlook 2007 than you are required to install "Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1 (CDO 1.21)". It can be downloaded from http://www.microsoft.com/downloads/en/details.aspx?FamilyID=e17e7f31-079a-43a9-bff2-0a110307611e&displaylang=en + 1.Python 2.6+ . python can be downloaded from http://www.python.org/download/releases/ . + 2.Python for Windows extensions - PyWin32 this module for python must be installed for appropriate version of the Python. It can be downloaded from http://sourceforge.net/projects/pywin32/files/ or http://starship.python.net/crew/mhammond/win32/ + 3.If you are using MS Outlook 2007 than you are required to install "Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1 (CDO 1.21)". It can be downloaded from http://www.microsoft.com/downloads/en/details.aspx?FamilyID=e17e7f31-079a-43a9-bff2-0a110307611e&displaylang=en How to install openerp-outlook plug-in? ====================================================================================== -1.Open your Python installation directory (e.g.: C:\Python26). -2.Create folder named “openerp-outlook-plugin”. -3.Extract your zip file “outlook-plugin.zip” to the folder. -4.Open the folder outlook-plugin. -5.And Run “Register-plugin.bat” file. -6.Run Outlook and Check addin has been registered. -7.Tools->OpenERP Configuration and test your connection. -8.See User Guide for More. + 1. Save the executable plug-in file. + 2. Close Outlook Application if Running. + 3. Run executable plug-in file and the folllow the instruction. How to uninstall openerp-outlook plug-in? ===================================================================================== -1.Open the folder outlook-plugin. -2.And Run “Unregister-plugin.bat” file. + 1. Go to Control Panel Click "Add/Remove Programmes" + 2. You will entry, you will find entry named 'OpenERP Outlook Addin 1.0' select it and click Uninstall. Note : Plug In has been successfully tested with MS Office 2003 and MS Offcie 2007. - Enjoy Archiving your Outlook E-mails to OpenERP. - - - diff --git a/addons/outlook/installer.py b/addons/outlook/installer.py index 0f71b6c33dc..3718b3687a0 100755 --- a/addons/outlook/installer.py +++ b/addons/outlook/installer.py @@ -32,7 +32,7 @@ class outlook_installer(osv.osv_memory): def default_get(self, cr, uid, fields, context={}): data = super(outlook_installer, self).default_get(cr, uid, fields, context) data['doc_file'] = 'http://doc.openerp.com/book/2/2_6_Comms/2_6_Comms_outlook.html' - file = open(addons.get_module_resource('outlook','plugin','openerp-outlook-plugin.zip'), 'r') + file = open(addons.get_module_resource('outlook','plugin','openerp-outlook-addin.exe'), 'r') data['plugin_file'] = base64.encodestring(file.read()) return data @@ -47,7 +47,7 @@ class outlook_installer(osv.osv_memory): _defaults = { 'outlook' : True, - 'name' : 'OpenERP-Outlook-PlugIn.zip', + 'name' : 'Openerp-Outlook-Addin.exe', 'doc_name' : 'Installation Guide to OpenERP Outlook Plug-in.doc', 'description' : """ * Save the Outlook plug-in. @@ -58,15 +58,10 @@ Pre-requirements : 3. If you are using MS Outlook 2007 than you are required to install "Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1 (CDO 1.21)". How to install openerp-outlook plug-in? - 1. Extract zip file “openerp-outlook-plugin.zip” . - 2. Open the folder openerp-outlook-plugin. - 3. Run “Register-plugin.bat” file. - 4. Run Outlook and Check addon has been registered. - 5. Tools->OpenERP Configuration and test your connection. - 6. See User Guide for more information. - 7. Keep All extratced files in some safe places - (e.g. python installation Directory "C:\pythonXX\" or Windows installation Directory "C:\Program Files\" ). - + 1. Save the executable plug-in file. + 2. Close Outlook Application if Running. + 3. Run executable plug-in file and the folllow the instruction. + Note : Please refer README file for dependecies external link, openobject-addons/outlook/README. """ diff --git a/addons/outlook/plugin/openerp-outlook-plugin/addin.py b/addons/outlook/plugin/openerp-outlook-plugin/addin.py index dbd6f172182..a86bcb88e6b 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/addin.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/addin.py @@ -24,45 +24,33 @@ ##############################################################################
from win32com import universal
-from win32com.server.exception import COMException
from win32com.client import gencache, DispatchWithEvents
-import winerror
import pythoncom
from win32com.client import constants
import sys
import os
from win32com.client import Dispatch
import win32con
-
sys.path.append(os.path.abspath(os.path.dirname(__file__))) #outlook
sys.path.append(os.path.abspath(__file__)) #outlook/addin
-
import manager
from win32com.client import CastTo
import win32ui
-from tiny_xmlrpc import *
-
+from tiny_xmlrpc import XMLRpcConn
import locale
locale.setlocale(locale.LC_NUMERIC, "C")
-
# Support for COM objects we use.
gencache.EnsureModule('{00062FFF-0000-0000-C000-000000000046}', 0, 9, 0, bForDemand=True) # Outlook 9
gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 1, bForDemand=True) # Office 9
-
# The TLB defiining the interfaces we implement
universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, ["_IDTExtensibility2"])
-
global NewConn
-
# Retrieves registered XMLRPC connection
def GetConn():
d=Dispatch("Python.OpenERP.XMLRpcConn")
- mngr = manager.GetManager()
return d
-
-class ButtonEvent:
+class Configuration:
def OnClick(self, button, cancel):
- import win32ui
try:
mngr = manager.GetManager()
mngr.ShowManager()
@@ -91,8 +79,6 @@ class ViewPartners: #
class OpenPartner:
def OnClick(self, button, cancel):
- import win32ui
- from manager import ustr
mngr = manager.GetManager()
data=mngr.LoadConfig()
outlook = Dispatch("Outlook.Application")
@@ -170,7 +156,7 @@ class OutlookAddin: item = tools_menu.Controls.Add(Type=constants.msoControlButton, Temporary=True)
# Hook events for the item
- item = self.menu_bar_Button = DispatchWithEvents(item, ButtonEvent)
+ item = self.menu_bar_Button = DispatchWithEvents(item, Configuration)
item.Caption="OpenERP Configuration"
item.TooltipText = "Click to configure OpenERP"
item.Enabled = True
@@ -192,7 +178,6 @@ class OutlookAddin: item.Enabled = True
# Adding Menu in Menu Bar to the Web Menu of the Outlook
- toolbaradvance = bars.Item("Advanced")
toolbarweb = bars.Item("Web")
item = toolbarweb.Controls.Add(Type = constants.msoControlButton, Temporary = True)
@@ -205,29 +190,36 @@ class OutlookAddin: item = toolbarweb.Controls.Add(Type = constants.msoControlButton, Temporary = True)
item = self.toolbarButtonOpenDocument = DispatchWithEvents(item, OpenDocument)
item.Caption = "Open Document"
- item.TooltipText = "Click to Open Document that ha been pushed to server."
+ item.TooltipText = "Click to Open Document that has been pushed to server."
item.Enabled = True
# Hook events for the item
- item = toolbarweb.Controls.Add(Type = constants.msoControlButton, Temporary = True)
- item = self.toolbarButtonPartner = DispatchWithEvents(item, ViewPartners)
- item.Caption = "Open Contact"
- item.TooltipText = "Click to Open OpenERP Partner Contact Information."
- item.Enabled = True
+# item = toolbarweb.Controls.Add(Type = constants.msoControlButton, Temporary = True)
+# item = self.toolbarButtonPartner = DispatchWithEvents(item, ViewPartners)
+# item.Caption = "Open Contact"
+# item.TooltipText = "Click to Open OpenERP Partner Contact Information."
+# item.Enabled = True
+
+# item = tools_menu.Controls.Add(Type=constants.msoControlButton, Temporary=True)
+# # Hook events for the item
+# item = self.menu_bar_viewpartner_Button = DispatchWithEvents(item, ViewPartners)
+# item.Caption = "Open Contact"
+# item.TooltipText = "Click to Open Partner detail"
+# item.Enabled = True
item = tools_menu.Controls.Add(Type=constants.msoControlButton, Temporary=True)
# Hook events for the item
- item = self.menu_bar_viewpartner_Button = DispatchWithEvents(item, ViewPartners)
- item.Caption = "Open Contact"
+ item = self.menu_bar_openpartner_Button = DispatchWithEvents(item, OpenPartner)
+ item.Caption = "Open Partner"
item.TooltipText = "Click to Open Partner detail"
item.Enabled = True
item = tools_menu.Controls.Add(Type=constants.msoControlButton, Temporary=True)
# Hook events for the item
- item = self.menu_bar_openpartner_Button = DispatchWithEvents(item, OpenPartner)
- item.Caption = "Open Partner"
- item.TooltipText = "Click to Open Partner detail"
+ item = self.menu_bar_opendocument_Button = DispatchWithEvents(item, OpenDocument)
+ item.Caption = "Open Document"
+ item.TooltipText = "Click to Open Document that has been pushed to server."
item.Enabled = True
@@ -259,14 +251,14 @@ def UnregisterAddin(klass): import _winreg
try:
_winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Outlook\\Addins\\" + klass._reg_progid_)
- except WindowsError:
+ except:
pass
def UnregisterXMLConn(klass):
import _winreg
try:
_winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Outlook\\Addins\\XMLConnection" + klass._reg_progid_)
- except WindowsError:
+ except:
pass
def RegisterXMLConn(klass):
@@ -279,7 +271,6 @@ def RegisterXMLConn(klass): _winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, klass._reg_progid_)
if __name__ == '__main__':
-
import win32com.server.register
NewConn=XMLRpcConn()
win32com.server.register.UseCommandLine(OutlookAddin)
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/chilkat.py b/addons/outlook/plugin/openerp-outlook-plugin/chilkat.py index e9e68c6e2d0..1afd9f85fdd 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/chilkat.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/chilkat.py @@ -3790,7 +3790,6 @@ class CkSpider(_object): def CanonicalizeUrl(self, *args): return _chilkat.CkSpider_CanonicalizeUrl(self, *args)
def getDomain(self, *args): return _chilkat.CkSpider_getDomain(self, *args)
def getBaseDomain(self, *args): return _chilkat.CkSpider_getBaseDomain(self, *args)
-
def canonicalizeUrl(self, *args): return _chilkat.CkSpider_canonicalizeUrl(self, *args)
def lastErrorText(self): return _chilkat.CkSpider_lastErrorText(self)
def lastErrorXml(self): return _chilkat.CkSpider_lastErrorXml(self)
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/__init__.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/__init__.py index 3b3d8973497..3b3d8973497 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/__init__.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/__init__.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dialog_map.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dialog_map.py index c82a7a7fc85..c78895e74c1 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dialog_map.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dialog_map.py @@ -25,7 +25,6 @@ from processors import *
from opt_processors import *
-import sys
import os
import addin
from dialogs import ShowDialog, MakePropertyPage
@@ -301,7 +300,7 @@ class WEBOKButtonProcessor(ButtonProcessor): server = win32gui.GetDlgItemText(self.window.hwnd, self.other_ids[0])
try:
port = int(win32gui.GetDlgItemText(self.window.hwnd, self.other_ids[1]))
- except ValueError, e:
+ except ValueError:
win32ui.MessageBox("Port should be an integer", "OpenERP Connection", flag_excl)
return
if server.strip() == "" or server.strip() == "http:\\\\":
@@ -409,18 +408,9 @@ class DialogCommand(ButtonProcessor): dd = self.window.manager.dialog_parser.dialogs[self.idd]
return "Displays the %s dialog" % dd.caption
-def ReloadAllControls(btnProcessor,*args):
- server = NewConn.getitem('_server')
- port = NewConn.getitem('_port')
- btnProcessor.window.LoadAllControls()
- if str(NewConn.getitem('_running')) == 'False':
- win32ui.MessageBox("No server running on host "+ server+" at port "+str(port), "OpenERP Connection", flag_excl)
- return
-
def TestConnection(btnProcessor,*args):
server = NewConn.getitem('_server')
port = NewConn.getitem('_port')
- url = NewConn.getitem('_uri')
NewConn.GetDBList()
if str(NewConn.getitem('_running')) == 'False':
btnProcessor.window.LoadAllControls()
@@ -438,8 +428,6 @@ def TestConnection(btnProcessor,*args): win32ui.MessageBox("No database found on host "+ server+" at port "+str(port), "OpenERP Connection", flag_excl)
return
-
-
uname = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
pwd = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[2])
@@ -600,7 +588,6 @@ def DeleteSelectedObjects(btnProcessor,*args): for n in extra:
nombre = n.tostring()
sel_text = nombre[0:r]
- s = win32gui.SendMessage(hwndList, commctrl.LVM_DELETEITEM, sel)
try:
NewConn.DeleteObject(sel_text)
except Exception,e:
@@ -632,8 +619,6 @@ def GetSelectedItems(hwndList): def MakeAttachment(btnProcessor,*args):
#Check if server running or user logged in
- from win32com.client import Dispatch
- import win32com
b = check()
if not b:
return
@@ -694,6 +679,7 @@ def CreateCase(btnProcessor,*args): flag=flag_error
if f:
win32ui.MessageBox(msg, "Create Document", flag)
+ win32gui.EndDialog(btnProcessor.window.hwnd, btnProcessor.other_ids[2])
return
else:
win32ui.MessageBox("Error While creating document.\n Document can not be created.", "Create Document", flag_error)
@@ -721,7 +707,7 @@ def GetSearchText(txtProcessor,*args): mail = ex.Selection.Item(1)
try:
search_text = ustr(mail.SenderEmailAddress).encode('iso-8859-1')
- except Exception,e:
+ except Exception:
pass
win32gui.SendMessage(search_box, win32con.WM_SETTEXT, 0, search_text)
txtProcessor.init_done=True
@@ -765,9 +751,6 @@ def SearchObjectsForText(btnProcessor,*args): return
search_txt = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0])
- if not search_txt:
- win32ui.MessageBox("Enter text to search for", "Push to OpenERP", flag_info)
- return
# Get titles from list
obj_titles=[]
for ch in hwndChk_list:
@@ -845,8 +828,10 @@ def CreateContact(btnProcessor,*args): 'state_id':ustr(state),
'country_id':ustr(country)
}
+ if res.get('name').strip == '' or res.get('email').strip == '':
+ win32ui.MessageBox("Contact name or Email id is Missing\nPlease fill those information", "Create Contact", flag_error)
+ return
try:
- id = NewConn.CreateContact(str(res))
if not partner:
msg="New contact created."
else:
@@ -869,7 +854,6 @@ def SetAllText(txtProcessor,*args): url = NewConn.getitem('_uri')
tbox = txtProcessor.GetControl()
win32gui.SendMessage(tbox, win32con.WM_SETTEXT, 0, str(url))
- k=win32gui.GetDlgItemText(txtProcessor.window.hwnd, txtProcessor.control_id)
uname = NewConn.getitem('_uname')
tbox = txtProcessor.GetControl(txtProcessor.other_ids[0])
win32gui.SendMessage(tbox, win32con.WM_SETTEXT, 0, str(uname))
@@ -935,9 +919,6 @@ def SetDefaultList(listProcessor,*args): def SetDefaultContact(txtProcessor,*args):
# Acquiring the control of the text box
- txt_name = txtProcessor.GetControl()
- txt_email = txtProcessor.GetControl(txtProcessor.other_ids[0])
-
global name
global email
global partner_ref
@@ -967,7 +948,7 @@ def SetDefaultContact(txtProcessor,*args): mail = GetMail(txtProcessor)
name = ustr(mail.SenderName).encode('iso-8859-1')
email = ustr(mail.SenderEmailAddress).encode('iso-8859-1')
- except Exception,e:
+ except Exception:
pass
win32gui.SetDlgItemText(txtProcessor.window.hwnd, txtProcessor.control_id,name)
@@ -977,7 +958,6 @@ def SetDefaultContact(txtProcessor,*args): def setCheckList(groupProcessor,*args):
try:
- child_style = win32con.BS_AUTOCHECKBOX | win32con.WS_TABSTOP
hinst = win32gui.dllhandle
objs = groupProcessor.window.manager.config['objects']
ins_objs = NewConn.GetAllObjects()
@@ -986,33 +966,12 @@ def setCheckList(groupProcessor,*args): cnt=0
id=4001
id1=6001
- load_bmp_flags=win32con.LR_LOADFROMFILE | win32con.LR_LOADTRANSPARENT
if groupProcessor.init_done:
return
else:
for obj in objs:
if obj[1] in ins_objs:
groupProcessor.init_done = True
- #Add image
- hwndImg = win32gui.CreateWindowEx(0, "STATIC","",
- win32con.SS_CENTERIMAGE | win32con.SS_REALSIZEIMAGE | win32con.SS_BITMAP | win32con.WS_CHILD | win32con.WS_VISIBLE,
- left,top+3,13,13,
- groupProcessor.window.hwnd,
- id,
- 0,
- None
- );
- image_path = os.path.join(groupProcessor.window.manager.application_directory, "dialogs\\resources\\openerp_logo1.bmp")
- if obj[2]:
- image_path = obj[2]
- try:
- hicon = win32gui.LoadImage(0, image_path, win32con.IMAGE_BITMAP, 40, 40, load_bmp_flags)
- except Exception,e:
- msg="Problem loading the image \n\n" + getMessage(e)
- hicon = None
- win32ui.MessageBox(msg, "Load Image", flag_error)
-
- win32gui.SendMessage(hwndImg, win32con.STM_SETIMAGE, win32con.IMAGE_BITMAP, hicon);
#Add Checkbox
left+= 17
hwndChk = win32gui.CreateWindowEx(
@@ -1028,7 +987,6 @@ def setCheckList(groupProcessor,*args): id+=1
id1+=1
left+=17
- win32gui.UpdateWindow(hwndImg)
left+=140
if cnt > 1:
left = 20
@@ -1079,7 +1037,6 @@ def set_name_email(dialogProcessor,*args): #setting values to the appropriate text areas
def GetDefaultEmail(txtProcessor,*args):
- from win32com.client import Dispatch
import win32con
b = check()
global partner_ref
@@ -1106,6 +1063,8 @@ def GetDefaultEmail(txtProcessor,*args): new_con_state = ""
if country_ref == None:
country_ref = ""
+
+
if not b:
return
#Acquiring control of the text box
@@ -1121,7 +1080,7 @@ def GetDefaultEmail(txtProcessor,*args): #Fetching Sender MailID from Selected Mail
try:
search_partner_text = ustr(mail.SenderEmailAddress).encode('iso-8859-1')
- except Exception,e:
+ except Exception:
win32ui.MessageBox("Error In reading email ID from Email ","Open Contact", flag_error)
pass
win32gui.SendMessage(search_partner_box, win32con.WM_SETTEXT, 0, search_partner_text)
@@ -1314,6 +1273,17 @@ def SetPartnerNameColumn(listProcessor,*args): lvc.text = "Partner Name"
lvc.cx = 275
win32gui.SendMessage(hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam())
+
+ partners = list(NewConn.GetPartners(''))
+ win32gui.SendMessage(hwndList, commctrl.LVM_DELETEALLITEMS)
+ if not partners:
+ win32gui.SetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0],"<enter text to search>")
+ win32ui.MessageBox("No Partner found with name {0}.".format(search_partner),"Search Partner",flag_error)
+ for partner in partners[::-1]:
+ num_items = win32gui.SendMessage(hwndList, commctrl.LVM_GETITEMCOUNT)
+ item = LVITEM(text=partner[1],iItem = num_items)
+ win32gui.SendMessage(hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam())
+
listProcessor.init_done = True
def SelectPartnerFromList(btnProcessor,*args):
@@ -1337,7 +1307,7 @@ def SelectPartnerFromList(btnProcessor,*args): return
try:
partner_ref = str(sel_text)
- except Exception,e:
+ except Exception:
pass
win32gui.EndDialog(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
return
@@ -1354,9 +1324,6 @@ def SearchPartnerList(btnProcessor,*args): return
try :
search_partner = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0])
- if not search_partner:
- win32ui.MessageBox("Please enter Partner name to search for.", "Search Partner", flag_excl)
- return
#Searching the contact.
hwndList = win32gui.GetDlgItem(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
partners = list(NewConn.GetPartners(search_partner))
@@ -1364,7 +1331,7 @@ def SearchPartnerList(btnProcessor,*args): if not partners:
win32gui.SetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0],"<enter text to search>")
win32ui.MessageBox("No Partner found with name {0}.".format(search_partner),"Search Partner",flag_error)
- for partner in partners:
+ for partner in partners[::-1]:
num_items = win32gui.SendMessage(hwndList, commctrl.LVM_GETITEMCOUNT)
item = LVITEM(text=partner[1],iItem = num_items)
win32gui.SendMessage(hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam())
@@ -1382,7 +1349,6 @@ def ConnectWebServer(btnProcessor, *args): def OpenPartnerForm(txtProcessor,*args):
- from win32com.client import Dispatch
import win32con
b = check()
if not b:
@@ -1396,12 +1362,18 @@ def OpenPartnerForm(txtProcessor,*args): partner_text = ""
try:
partner_text = ustr(mail.SenderName).encode('iso-8859-1')
- except Exception,e:
+ sender_mail = ustr(mail.SenderEmailAddress).encode('iso-8859-1')
+
+ except Exception:
win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, "< Error in reading email.>")
pass
- vals = NewConn.SearchPartner(partner_text)
+ vals = NewConn.SearchPartner(sender_mail)
+ if vals == True:
+ win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, "< Their is contact related to "+str(partner_text)+" email address, but no partner is linked to contact>")
+ txtProcessor.init_done=True
+ return
if vals == None:
- win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, "< No Partner with named "+str(partner_text)+" found.>")
+ win32gui.SendMessage(partner_link, win32con.WM_SETTEXT, 0, "< No Partner found linked to "+str(partner_text)+" email address.>")
txtProcessor.init_done=True
return
global web_server
@@ -1419,12 +1391,10 @@ def OpenPartnerForm(txtProcessor,*args): txtProcessor.init_done=True
def SerachOpenDocuemnt(txtProcessor,*args):
- from win32com.client import Dispatch
import win32con
import win32ui
import win32com
- from win32com.mapi import mapi, mapiutil, mapitags
- import pythoncom
+ from win32com.mapi import mapitags
b = check()
if not b:
return
@@ -1442,9 +1412,9 @@ def SerachOpenDocuemnt(txtProcessor,*args): txtProcessor.init_done=True
return
linktodoc = ""
+
message_id = None
try:
- outlook = win32com.client.Dispatch("Outlook.Application")
session = win32com.client.Dispatch("MAPI.session")
session.Logon('Outlook')
objMessage = session.GetMessage(mail.EntryID, mail.Parent.StoreID)
@@ -1484,9 +1454,6 @@ def SearchCountry(btnProcessor, *args): return
try :
search_country = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0])
- if not search_country:
- win32ui.MessageBox("Please enter country name to search for.", "Search Country", flag_excl)
- return
#Searching the contact.
hwndList = win32gui.GetDlgItem(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
countries = list(NewConn.GetCountry(search_country))
@@ -1520,6 +1487,17 @@ def SetCountryList(listProcessor,*args): lvc.text = "Country Name"
lvc.cx = 275
win32gui.SendMessage(hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam())
+
+ countries = list(NewConn.GetCountry(''))
+ win32gui.SendMessage(hwndList, commctrl.LVM_DELETEALLITEMS)
+ if not countries:
+ win32gui.SetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0],"<enter text to search>")
+ win32ui.MessageBox("No country found with name {0}.".format(search_country),"Search Country",flag_error)
+ for country in countries:
+ num_items = win32gui.SendMessage(hwndList, commctrl.LVM_GETITEMCOUNT)
+ item = LVITEM(text=country[1],iItem = num_items)
+ win32gui.SendMessage(hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam())
+
listProcessor.init_done = True
def SelectCountryFromList(btnProcessor,*args):
@@ -1547,7 +1525,7 @@ def SelectCountryFromList(btnProcessor,*args): country_ref = str(sel_text)
new_con_country = str(sel_text)
search_country = str(sel_text)
- except Exception,e:
+ except Exception:
pass
win32gui.EndDialog(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
return
@@ -1566,9 +1544,6 @@ def SearchState(btnProcessor, *args): global new_con_country
global search_country
search_state = win32gui.GetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0])
- if not search_state:
- win32ui.MessageBox("Please enter state name to search for.", "Search Fed.State", flag_excl)
- return
#Searching the contact.
hwndList = win32gui.GetDlgItem(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
states = list(NewConn.GetStates(search_state, search_country))
@@ -1601,6 +1576,18 @@ def SetStateList(listProcessor,*args): lvc.text = "Fed.State Name"
lvc.cx = 275
win32gui.SendMessage(hwndList, commctrl.LVM_INSERTCOLUMN, 0, lvc.toparam())
+
+ global new_con_country
+ global search_country
+ states = list(NewConn.GetStates('', search_country))
+ win32gui.SendMessage(hwndList, commctrl.LVM_DELETEALLITEMS)
+ if not states:
+ win32gui.SetDlgItemText(btnProcessor.window.hwnd, btnProcessor.other_ids[0],"<enter text to search>")
+ win32ui.MessageBox("No state found with name {0}.".format(search_state),"Search Fed.State",flag_error)
+ for state in states:
+ num_items = win32gui.SendMessage(hwndList, commctrl.LVM_GETITEMCOUNT)
+ item = LVITEM(text=state[1],iItem = num_items)
+ win32gui.SendMessage(hwndList, commctrl.LVM_INSERTITEM, 0, item.toparam())
listProcessor.init_done = True
def SelectStateFromList(btnProcessor,*args):
@@ -1627,7 +1614,7 @@ def SelectStateFromList(btnProcessor,*args): state_ref = str(sel_text)
new_con_state = str(sel_text)
win32gui.EndDialog(btnProcessor.window.hwnd, btnProcessor.other_ids[1])
- except Exception,e:
+ except Exception:
pass
return
@@ -1653,7 +1640,6 @@ dialog_map = { (TextProcessor, "ID_SERVER_PORT ID_USERNAME ID_PASSWORD IDET_WED_SERVER", SetAllText, ()),
(CommandButtonProcessor, "ID_BUT_TESTCONNECTION ID_DB_DROPDOWNLIST ID_USERNAME \
ID_PASSWORD", TestConnection, ()),
- (CommandButtonProcessor, "IDC_RELOAD", ReloadAllControls, ()),
(DialogCommand, "IDC_BUT_SET_SERVER_PORT", "IDD_SERVER_PORT_DIALOG"),
(DialogCommand, "ID_SET_WEB_CONNECTION", "IDD_WEB_SERVER_PORT_DIALOG" ),
(CommandButtonProcessor, "IDPB_WEB_CONNECTION IDET_WED_SERVER", ConnectWebServer, ()),
@@ -1685,7 +1671,7 @@ dialog_map = { (DialogCommand, "ID_CREATE_CONTACT ID_SEARCH_TEXT", "IDD_NEW_CONTACT_DIALOG", set_search_text, ()),
(CloseButtonProcessor, "IDCANCEL"),
(CommandButtonProcessor, "ID_MAKE_ATTACHMENT IDC_NAME_LIST IDD_SYNC", MakeAttachment, ()),
- (CommandButtonProcessor, "ID_CREATE_CASE ID_ATT_METHOD_DROPDOWNLIST IDC_NAME_LIST", CreateCase, ()),
+ (CommandButtonProcessor, "ID_CREATE_CASE ID_ATT_METHOD_DROPDOWNLIST IDC_NAME_LIST IDD_SYNC", CreateCase, ()),
(ListBoxProcessor, "IDC_NAME_LIST", SetNameColumn, ())
),
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgcore.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgcore.py index efccf4f494e..efccf4f494e 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgcore.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgcore.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgutils.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgutils.py index 8ffc4e62d22..8ffc4e62d22 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgutils.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/dlgutils.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/opt_processors.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/opt_processors.py index ae21ba1c538..4c8224e4939 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/opt_processors.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/opt_processors.py @@ -227,10 +227,10 @@ class CSComboProcessor(ComboProcessor): objlist = conn.GetAllObjects()
# if 'crm.claim' in objlist:
# list.append('CRM Claim')
- if 'crm.helpdesk' in objlist:
- list.append('CRM Helpdesk')
- if 'crm.fundraising' in objlist:
- list.append('CRM Fundraising')
+# if 'crm.helpdesk' in objlist:
+# list.append('CRM Helpdesk')
+# if 'crm.fundraising' in objlist:
+# list.append('CRM Fundraising')
if'hr.applicant' in objlist:
list.append('HR Applicant')
if'project.issue' in objlist:
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/processors.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/processors.py index 0b427852c89..0b427852c89 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/processors.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/processors.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/OpenERP_Logo.bmp b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/OpenERP_Logo.bmp Binary files differindex c8bb6091839..c8bb6091839 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/OpenERP_Logo.bmp +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/OpenERP_Logo.bmp diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/__init__.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/__init__.py index abeff9ae69b..abeff9ae69b 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/__init__.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/__init__.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.h b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.h index a816b9838ab..a816b9838ab 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.h +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.h diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.py index 5f5a0cdca50..f63d66274af 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.py @@ -1,9 +1,9 @@ #C:\workspace\openerp-outlook-plugin\dialogs\resources\dialogs.py
#This is a generated file. Please edit C:\workspace\openerp-outlook-plugin\dialogs\resources\dialogs.rc instead.
-_rc_size_=16028
-_rc_mtime_=1286860723
+_rc_size_=15985
+_rc_mtime_=1288860503
class FakeParser:
- dialogs = {'IDD_OPEN_DOCUEMNT_DIALOG': [['Open Document', (0, 0, 200, 65), -1865940928, 1024, (8, 'Tahoma')], [130, 'Link to Document : (If this link does not opens directly in web browser then copy an the link and paste in web browser.) ', -1, (5, 3, 190, 25), 1342177280], [129, '', 2086, (5, 31, 190, 12), 1350631552], [128, 'Ok', 2, (150, 45, 45, 14), 1342242816]], 'IDD_VIEW_PARTNER_DIALOG': [['Open Contact', (0, 0, 350, 215), -1865940928, 1024, (8, 'Tahoma')], [130, 'Email ID : ', -1, (32, 17, 40, 12), 1342177280], [129, '', 2051, (70, 15, 200, 12), 1350631552], [128, 'Search Contact ', 2052, (280, 15, 60, 14), 1342242816], [130, 'Partner Name : ', -1, (13, 42, 50, 17), 1342177280], [129, '', 2064, (70, 42, 150, 12), 1350568064], [128, 'Search Partner', 2070, (225, 41, 60, 14), 1342242816], [128, 'New Partner', 2093, (290, 41, 50, 14), 1342242816], [128, 'Postal Address ', 2024, (10, 65, 175, 125), 1342177287], [130, 'Contact Name : ', -1, (18, 83, 50, 17), 1342177280], [129, '', 2046, (76, 82, 100, 12), 1350631552], [130, 'Street : ', -1, (18, 97, 50, 17), 1342177280], [129, '', 2053, (76, 96, 100, 12), 1350631552], [130, 'Street2 : ', -1, (18, 112, 50, 17), 1342177280], [129, '', 2054, (76, 111, 100, 12), 1350631552], [130, 'Zip : ', -1, (18, 126, 50, 14), 1342177280], [129, '', 40010, (76, 125, 100, 12), 1350631552], [130, 'City : ', -1, (18, 140, 50, 17), 1342177280], [129, '', 40011, (76, 139, 100, 12), 1350631552], [130, 'Fed. State : ', -1, (18, 154, 50, 17), 1342177280], [129, '', 2062, (76, 153, 54, 12), 1350568064], [128, 'Search', 2104, (135, 153, 40, 12), 1342242816], [130, 'Country :', -1, (18, 169, 35, 17), 1342177280], [129, '', 2063, (76, 168, 54, 12), 1350568064], [128, 'Search', 2105, (135, 168, 40, 12), 1342242816], [128, 'Communication ', 2024, (188, 65, 152, 125), 1342177287], [130, 'Phone : ', -1, (194, 83, 30, 17), 1342177280], [129, '', 2048, (224, 82, 100, 12), 1350631552], [130, 'Mobile : ', -1, (194, 97, 30, 17), 1342177280], [129, '', 2050, (224, 96, 100, 12), 1350631552], [130, 'Email : ', -1, (194, 111, 30, 17), 1342177280], [129, '', 2058, (224, 110, 100, 12), 1350568064], [130, 'Fax : ', -1, (194, 125, 30, 17), 1342177280], [129, '', 2047, (224, 124, 100, 12), 1350631552], [128, 'Create a New Contact', 2071, (124, 195, 82, 14), 1342242816], [128, 'Save', 2059, (213, 195, 60, 14), 1342242816], [128, 'Cancel', 2, (281, 195, 60, 14), 1342242816]], 'IDD_OPEN_PARTNER_DIALOG': [['Open Partner', (0, 0, 200, 65), -1865940928, 1024, (8, 'Tahoma')], [130, 'Link to Partner : (If this link does not opens directly in web browser then copy an the link and paste in web browser.) ', -1, (5, 3, 190, 25), 1342177280], [129, '', 2085, (5, 31, 190, 12), 1350631552], [128, 'Ok', 2, (150, 45, 45, 13), 1342242816]], 'IDD_SELECT_STATE': [['Search Fed. State', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2100, (55, 10, 100, 12), 1350631552], [128, 'Search', 40012, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2101, (8, 40, 200, 185), 1353711657], [128, 'Select', 2102, (170, 230, 40, 14), 1342242816]], 'IDD_GENERAL': [['Connection Parameters', (0, 0, 430, 210), 1355284544, None, (8, 'Tahoma')], [128, '', 2024, (10, 10, 250, 130), 1342177287], [130, 'Server : ', -1, (30, 30, 100, 17), 1342177280], [129, '', 2003, (85, 30, 120, 12), 1350633472], [128, 'Change', 2021, (210, 30, 30, 13), 1342242816], [130, 'Database : ', -1, (30, 50, 100, 17), 1342177280], [133, '', 2004, (85, 50, 120, 40), 1344339971], [128, 'Reload', 2038, (210, 50, 30, 13), 1342242816], [130, 'Username : ', -1, (30, 70, 100, 17), 1342177280], [129, '', 2005, (85, 70, 154, 12), 1350631552], [130, 'Password : ', -1, (30, 90, 100, 17), 1342177280], [129, '', 2006, (85, 90, 154, 12), 1350631584], [128, 'Connect', 2007, (179, 110, 60, 13), 1342242816], [128, 'WebServer Parameters', 2024, (270, 10, 150, 130), 1342177287], [130, 'Server : ', -1, (280, 30, 50, 15), 1342177280], [129, '', 2080, (310, 29, 90, 12), 1350568064], [128, 'Change', 2082, (295, 50, 50, 12), 1342242816], [128, 'Connect', 2083, (350, 50, 50, 12), 1342242816]], 'IDD_OBJECT_SETTINGS': [['Documents Setting', (0, 0, 430, 210), 1355284672, 1024, (8, 'Tahoma')], [128, 'Document Attributes', 2024, (2, 2, 340, 32), 1342177287], [130, 'Title', -1, (6, 15, 30, 17), 1342177280], [129, '', 2013, (20, 14, 57, 12), 1350631552], [130, 'Document Name', -1, (83, 15, 60, 17), 1342177280], [129, '', 2014, (138, 14, 57, 12), 1350631552], [130, 'Image', -1, (200, 15, 20, 17), 1342177280], [129, '', 2015, (220, 14, 57, 12), 1350631552], [128, 'Load Image', 2010, (286, 13, 50, 15), 1342242816], [128, 'Add', 2011, (347, 13, 38, 15), 1342242816], [128, 'Remove', 2012, (391, 13, 38, 15), 1342242816], ['SysListView32', 'List1', 2016, (8, 40, 535, 160), 1353711657]], 'IDD_NEW_PARTNER_DIALOG': [['Create a New Partner', (0, 0, 140, 40), -1865940928, 1024, (8, 'Tahoma')], [130, 'Name : ', -1, (5, 3, 100, 17), 1342177280], [129, '', 2036, (40, 3, 94, 12), 1350631552], [128, 'Cancel', 2, (90, 22, 45, 14), 1342242816], [128, 'Save', 2035, (40, 22, 45, 14), 1342242817]], 'IDD_MANAGER': [['OpenERP Configuration', (0, 0, 460, 260), -1865940800, None, (8, 'Tahoma')], [128, 'Close', 2008, (400, 239, 50, 14), 1342177281], ['SysTabControl32', '', 1068, (8, 7, 440, 228), 1342177280], ['SysListView32', '', 2016, (0, 0, 0, 0), 1353711657]], 'IDD_WEB_SERVER_PORT_DIALOG': [['OpenERP Connection', (0, 0, 160, 55), -1865940928, 1024, (8, 'Tahoma')], [130, 'Server : ', -1, (5, 3, 150, 17), 1342177280], [129, '', 2089, (40, 3, 100, 12), 1350631552], [130, 'Port : ', -1, (5, 18, 100, 17), 1342177280], [129, '', 2090, (40, 18, 100, 12), 1350631552], [128, 'Close', 2, (110, 35, 45, 14), 1342242816], [128, 'OK', 2091, (60, 35, 45, 14), 1342242817]], 'IDD_ABOUT': [['About', (0, 0, 430, 210), 1355284672, 1024, (8, 'Tahoma')], [128, 'About Plugin', -1, (7, 3, 422, 200), 1342177287], [130, '1062', 1062, (60, 30, 20, 20), 1342179342], [130, '', 2028, (80, 90, 300, 100), 1342177280]], 'IDD_NEW_CONTACT_DIALOG': [['Create a New Contact', (0, 0, 350, 180), -1865940928, 1024, (8, 'Tahoma')], [130, 'Select Partner : ', -1, (13, 20, 50, 17), 1342177280], [129, '', 2079, (70, 18, 150, 12), 1350568064], [128, 'Search Partner', 2033, (225, 17, 60, 14), 1342242816], [128, 'New Partner', 2092, (290, 17, 50, 14), 1342242816], [128, 'Postal Address ', 2024, (10, 35, 175, 123), 1342177287], [130, 'Contact Name : ', -1, (18, 53, 100, 17), 1342177280], [129, '', 40005, (76, 52, 100, 12), 1350631552], [130, 'Street : ', -1, (18, 67, 40, 17), 1342177280], [129, '', 2062, (76, 66, 100, 12), 1350631552], [130, 'Street2 : ', -1, (18, 81, 40, 17), 1342177280], [129, '', 2063, (76, 80, 100, 12), 1350631552], [130, 'Zip : ', -1, (18, 94, 50, 17), 1342177280], [129, '', 2068, (76, 93, 100, 12), 1350631552], [130, 'City : ', -1, (18, 106, 50, 17), 1342177280], [129, '', 2067, (76, 107, 100, 12), 1350631552], [130, 'Fed. State : ', -1, (18, 121, 50, 17), 1342177280], [129, '', 2106, (76, 122, 54, 12), 1350568064], [128, 'Search', 2107, (135, 121, 40, 12), 1342242816], [130, 'Country :', -1, (18, 134, 35, 17), 1342177280], [129, '', 2108, (76, 135, 54, 12), 1350568064], [128, 'Search', 2109, (135, 136, 40, 12), 1342242816], [128, 'Communication ', 2024, (188, 35, 150, 123), 1342177287], [130, 'Office : ', -1, (194, 53, 30, 17), 1342177280], [129, '', 40006, (224, 52, 100, 12), 1350631552], [130, 'Mobile : ', -1, (194, 67, 30, 17), 1342177280], [129, '', 40007, (224, 66, 100, 12), 1350631552], [130, 'Fax : ', -1, (194, 81, 30, 17), 1342177280], [129, '', 2066, (224, 80, 100, 12), 1350631552], [130, 'Email : ', -1, (194, 95, 30, 17), 1342177280], [129, '', 40008, (224, 94, 100, 12), 1350631552], [128, 'Cancel', 2, (290, 162, 45, 13), 1342242816], [128, 'Save', 40009, (240, 162, 45, 13), 1342242816]], 'IDD_SERVER_PORT_DIALOG': [['OpenERP Connection', (0, 0, 160, 55), -1865940928, 1024, (8, 'Tahoma')], [130, 'Server : ', -1, (5, 3, 150, 17), 1342177280], [129, '', 2001, (40, 3, 100, 12), 1350631552], [130, 'Port : ', -1, (5, 18, 100, 17), 1342177280], [129, '', 2002, (40, 18, 100, 12), 1350631552], [128, 'Close', 2, (110, 35, 45, 14), 1342242816], [128, 'OK', 1, (60, 35, 45, 14), 1342242817]], 'IDD_SELECT_PARTNER': [['Search Partner', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2076, (55, 10, 100, 12), 1350631552], [128, 'Search', 2077, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2072, (8, 40, 200, 185), 1353711657], [128, 'Create New Partner', 2078, (10, 230, 100, 14), 1342242816], [128, 'Select', 2075, (170, 230, 40, 14), 1342242816]], 'IDD_SYNC': [['Push to OpenERP', (0, 0, 470, 320), -1865940928, 1024, (8, 'Tahoma')], [128, 'Link to an Existing Documents ', 2024, (8, 5, 250, 290), 1342242823], [130, 'Search for : ', -1, (15, 17, 40, 12), 1342177280], [129, '', 40003, (60, 15, 120, 12), 1350631552], [128, 'Search', 40004, (187, 15, 40, 14), 1342242816], [130, 'Documents : ', -1, (15, 140, 100, 14), 1342177280], ['SysListView32', 'List1', 2026, (15, 150, 234, 110), 1350631433], [128, 'Push', 2019, (160, 270, 85, 14), 1342242816], [128, ' Create a Document ', 2024, (263, 5, 202, 100), 1342242823], [130, 'Type of Document : ', -1, (266, 25, 100, 12), 1342177280], [133, '', 2025, (332, 24, 75, 45), 1344339971], [128, 'Create', 2020, (412, 23, 50, 14), 1342242816], [128, ' Create a Contact ', 2024, (263, 110, 202, 185), 1342242823], [130, 'Create a New Contact : ', -1, (280, 140, 100, 12), 1342177280], [128, 'Create Contact', 2018, (360, 138, 60, 14), 1342242816], [128, 'Close', 2, (385, 300, 60, 14), 1342242816]], 'IDD_SELECT_COUNTRY': [['Search Country', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2095, (55, 10, 100, 12), 1350631552], [128, 'Search', 2098, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2096, (8, 40, 200, 185), 1353711657], [128, 'Select', 2097, (170, 230, 40, 14), 1342242816]]}
+ dialogs = {'IDD_OPEN_DOCUEMNT_DIALOG': [['Open Document', (0, 0, 200, 65), -1865940928, 1024, (8, 'Tahoma')], [130, 'Link to Document : (If this link does not opens directly in web browser then copy an the link and paste in web browser.) ', -1, (5, 3, 190, 25), 1342177280], [129, '', 2086, (5, 31, 190, 12), 1350631552], [128, 'Ok', 2, (150, 45, 45, 14), 1342242816]], 'IDD_VIEW_PARTNER_DIALOG': [['Open Contact', (0, 0, 350, 215), -1865940928, 1024, (8, 'Tahoma')], [130, 'Email ID : ', -1, (32, 17, 40, 12), 1342177280], [129, '', 2051, (70, 15, 200, 12), 1350631552], [128, 'Search Contact ', 2052, (280, 15, 60, 14), 1342242816], [130, 'Partner Name : ', -1, (13, 42, 50, 17), 1342177280], [129, '', 2064, (70, 42, 150, 12), 1350568064], [128, 'Search Partner', 2070, (225, 41, 60, 14), 1342242816], [128, 'New Partner', 2093, (290, 41, 50, 14), 1342242816], [128, 'Postal Address ', 2024, (10, 65, 175, 125), 1342177287], [130, 'Contact Name : ', -1, (18, 83, 50, 17), 1342177280], [129, '', 2046, (76, 82, 100, 12), 1350631552], [130, 'Street : ', -1, (18, 97, 50, 17), 1342177280], [129, '', 2053, (76, 96, 100, 12), 1350631552], [130, 'Street2 : ', -1, (18, 112, 50, 17), 1342177280], [129, '', 2054, (76, 111, 100, 12), 1350631552], [130, 'Zip : ', -1, (18, 126, 50, 14), 1342177280], [129, '', 40010, (76, 125, 100, 12), 1350631552], [130, 'City : ', -1, (18, 140, 50, 17), 1342177280], [129, '', 40011, (76, 139, 100, 12), 1350631552], [130, 'Fed. State : ', -1, (18, 154, 50, 17), 1342177280], [129, '', 2062, (76, 153, 54, 12), 1350568064], [128, 'Search', 2104, (135, 153, 40, 12), 1342242816], [130, 'Country :', -1, (18, 169, 35, 17), 1342177280], [129, '', 2063, (76, 168, 54, 12), 1350568064], [128, 'Search', 2105, (135, 168, 40, 12), 1342242816], [128, 'Communication ', 2024, (188, 65, 152, 125), 1342177287], [130, 'Phone : ', -1, (194, 83, 30, 17), 1342177280], [129, '', 2048, (224, 82, 100, 12), 1350631552], [130, 'Mobile : ', -1, (194, 97, 30, 17), 1342177280], [129, '', 2050, (224, 96, 100, 12), 1350631552], [130, 'Email : ', -1, (194, 111, 30, 17), 1342177280], [129, '', 2058, (224, 110, 100, 12), 1350568064], [130, 'Fax : ', -1, (194, 125, 30, 17), 1342177280], [129, '', 2047, (224, 124, 100, 12), 1350631552], [128, 'Create a New Contact', 2071, (124, 195, 82, 14), 1342242816], [128, 'Save', 2059, (213, 195, 60, 14), 1342242816], [128, 'Cancel', 2, (281, 195, 60, 14), 1342242816]], 'IDD_OPEN_PARTNER_DIALOG': [['Open Partner', (0, 0, 200, 65), -1865940928, 1024, (8, 'Tahoma')], [130, 'Link to Partner : (If this link does not opens directly in web browser then copy an the link and paste in web browser.) ', -1, (5, 3, 190, 25), 1342177280], [129, '', 2085, (5, 31, 190, 12), 1350631552], [128, 'Ok', 2, (150, 45, 45, 13), 1342242816]], 'IDD_SELECT_STATE': [['Search Fed. State', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2100, (55, 10, 100, 12), 1350631552], [128, 'Search', 40012, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2101, (8, 40, 200, 185), 1353711657], [128, 'Select', 2102, (170, 230, 40, 14), 1342242816]], 'IDD_GENERAL': [['Connection Parameters', (0, 0, 430, 210), 1355284544, None, (8, 'Tahoma')], [128, 'Connection Parameters', 2024, (10, 10, 250, 130), 1342177287], [130, 'Server : ', -1, (30, 30, 100, 17), 1342177280], [129, '', 2003, (85, 30, 120, 12), 1350633472], [128, 'Change', 2021, (210, 30, 30, 13), 1342242816], [130, 'Database : ', -1, (30, 50, 100, 17), 1342177280], [133, '', 2004, (85, 50, 154, 40), 1344339971], [130, 'Username : ', -1, (30, 70, 100, 17), 1342177280], [129, '', 2005, (85, 70, 154, 12), 1350631552], [130, 'Password : ', -1, (30, 90, 100, 17), 1342177280], [129, '', 2006, (85, 90, 154, 12), 1350631584], [128, 'Connect', 2007, (179, 110, 60, 13), 1342242816], [128, 'WebServer Parameters', 2024, (270, 10, 150, 130), 1342177287], [130, 'Server : ', -1, (280, 30, 50, 15), 1342177280], [129, '', 2080, (310, 29, 90, 12), 1350568064], [128, 'Change', 2082, (295, 50, 50, 12), 1342242816], [128, 'Connect', 2083, (350, 50, 50, 12), 1342242816]], 'IDD_OBJECT_SETTINGS': [['Documents Setting', (0, 0, 430, 210), 1355284672, 1024, (8, 'Tahoma')], [128, 'Document Attributes', 2024, (2, 2, 343, 32), 1342177287], [130, 'Title:', -1, (5, 16, 30, 17), 1342177280], [129, '', 2013, (22, 14, 57, 12), 1350631552], [130, 'Document Name:', -1, (83, 16, 60, 17), 1342177280], [129, '', 2014, (138, 14, 57, 12), 1350631552], [130, 'Image:', -1, (200, 16, 22, 17), 1342177280], [129, '', 2015, (223, 14, 57, 12), 1350631552], [128, 'Load Image', 2010, (289, 13, 50, 15), 1342242816], [128, 'Add', 2011, (350, 13, 38, 15), 1342242816], [128, 'Delete', 2012, (392, 13, 38, 15), 1342242816], ['SysListView32', 'List1', 2016, (8, 40, 535, 160), 1353711657]], 'IDD_NEW_PARTNER_DIALOG': [['Create a New Partner', (0, 0, 140, 40), -1865940928, 1024, (8, 'Tahoma')], [130, 'Name : ', -1, (5, 3, 100, 17), 1342177280], [129, '', 2036, (40, 3, 94, 12), 1350631552], [128, 'Cancel', 2, (90, 22, 45, 14), 1342242816], [128, 'Save', 2035, (40, 22, 45, 14), 1342242817]], 'IDD_MANAGER': [['OpenERP Configuration', (0, 0, 460, 260), -1865940800, None, (8, 'Tahoma')], [128, 'Close', 2008, (400, 239, 50, 14), 1342177281], ['SysTabControl32', '', 1068, (8, 7, 440, 228), 1342177280], ['SysListView32', '', 2016, (0, 0, 0, 0), 1353711657]], 'IDD_WEB_SERVER_PORT_DIALOG': [['OpenERP Connection', (0, 0, 160, 55), -1865940928, 1024, (8, 'Tahoma')], [130, 'Server : ', -1, (5, 3, 150, 17), 1342177280], [129, '', 2089, (40, 3, 100, 12), 1350631552], [130, 'Port : ', -1, (5, 18, 100, 17), 1342177280], [129, '', 2090, (40, 18, 100, 12), 1350631552], [128, 'Close', 2, (110, 35, 45, 14), 1342242816], [128, 'OK', 2091, (60, 35, 45, 14), 1342242817]], 'IDD_ABOUT': [['About', (0, 0, 430, 210), 1355284672, 1024, (8, 'Tahoma')], [128, 'About Plugin', -1, (7, 3, 422, 200), 1342177287], [130, '1062', 1062, (60, 30, 20, 20), 1342179342], [130, '', 2028, (80, 90, 300, 100), 1342177280]], 'IDD_NEW_CONTACT_DIALOG': [['Create a New Contact', (0, 0, 350, 180), -1865940928, 1024, (8, 'Tahoma')], [130, 'Select Partner : ', -1, (13, 20, 50, 17), 1342177280], [129, '', 2079, (70, 18, 150, 12), 1350568064], [128, 'Search Partner', 2033, (225, 17, 60, 14), 1342242816], [128, 'New Partner', 2092, (290, 17, 50, 14), 1342242816], [128, 'Postal Address ', 2024, (10, 35, 175, 123), 1342177287], [130, 'Contact Name : ', -1, (18, 53, 100, 17), 1342177280], [129, '', 40005, (76, 52, 100, 12), 1350631552], [130, 'Street : ', -1, (18, 67, 40, 17), 1342177280], [129, '', 2062, (76, 66, 100, 12), 1350631552], [130, 'Street2 : ', -1, (18, 81, 40, 17), 1342177280], [129, '', 2063, (76, 80, 100, 12), 1350631552], [130, 'Zip : ', -1, (18, 94, 50, 17), 1342177280], [129, '', 2068, (76, 93, 100, 12), 1350631552], [130, 'City : ', -1, (18, 106, 50, 17), 1342177280], [129, '', 2067, (76, 107, 100, 12), 1350631552], [130, 'Fed. State : ', -1, (18, 134, 50, 15), 1342177280], [129, '', 2106, (76, 135, 54, 12), 1350568064], [128, 'Search', 2107, (135, 136, 40, 12), 1342242816], [130, 'Country :', -1, (18, 121, 35, 15), 1342177280], [129, '', 2108, (76, 122, 54, 12), 1350568064], [128, 'Search', 2109, (135, 121, 40, 12), 1342242816], [128, 'Communication ', 2024, (188, 35, 150, 123), 1342177287], [130, 'Office : ', -1, (194, 53, 30, 17), 1342177280], [129, '', 40006, (224, 52, 100, 12), 1350631552], [130, 'Mobile : ', -1, (194, 67, 30, 17), 1342177280], [129, '', 40007, (224, 66, 100, 12), 1350631552], [130, 'Fax : ', -1, (194, 81, 30, 17), 1342177280], [129, '', 2066, (224, 80, 100, 12), 1350631552], [130, 'Email : ', -1, (194, 95, 30, 17), 1342177280], [129, '', 40008, (224, 94, 100, 12), 1350631552], [128, 'Cancel', 2, (290, 162, 45, 13), 1342242816], [128, 'Save', 40009, (240, 162, 45, 13), 1342242816]], 'IDD_SERVER_PORT_DIALOG': [['OpenERP Connection', (0, 0, 160, 55), -1865940928, 1024, (8, 'Tahoma')], [130, 'Server : ', -1, (5, 3, 150, 17), 1342177280], [129, '', 2001, (40, 3, 100, 12), 1350631552], [130, 'Port : ', -1, (5, 18, 100, 17), 1342177280], [129, '', 2002, (40, 18, 100, 12), 1350631552], [128, 'Close', 2, (110, 35, 45, 14), 1342242816], [128, 'OK', 1, (60, 35, 45, 14), 1342242817]], 'IDD_SELECT_PARTNER': [['Search Partner', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2076, (55, 10, 100, 12), 1350631552], [128, 'Search', 2077, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2072, (8, 40, 200, 185), 1353711657], [128, 'Create New Partner', 2078, (10, 230, 100, 14), 1342242816], [128, 'Select', 2075, (170, 230, 40, 14), 1342242816]], 'IDD_SYNC': [['Push to OpenERP', (0, 0, 470, 320), -1865940928, 1024, (8, 'Tahoma')], [128, 'Link to an Existing Documents ', 2024, (8, 5, 250, 290), 1342242823], [130, 'Search : ', -1, (15, 17, 40, 12), 1342177280], [129, '', 40003, (60, 15, 120, 12), 1350631552], [128, 'Search', 40004, (187, 15, 40, 14), 1342242816], [130, 'Documents : ', -1, (15, 140, 100, 14), 1342177280], ['SysListView32', 'List1', 2026, (15, 150, 234, 110), 1350631433], [128, 'Push', 2019, (160, 270, 85, 14), 1342242816], [128, ' Create a New Document ', 2024, (263, 5, 202, 100), 1342242823], [130, 'Type of Document : ', -1, (266, 25, 100, 12), 1342177280], [133, '', 2025, (332, 24, 75, 45), 1344339971], [128, 'Create', 2020, (412, 23, 50, 14), 1342242816], [128, ' Create a New Contact ', 2024, (263, 110, 202, 185), 1342242823], [130, 'Create a New Contact : ', -1, (280, 140, 100, 12), 1342177280], [128, 'Create Contact', 2018, (360, 138, 60, 14), 1342242816], [128, 'Close', 2, (385, 300, 60, 14), 1342242816]], 'IDD_SELECT_COUNTRY': [['Search Country', (0, 0, 220, 250), -1865940928, 1024, (8, 'Tahoma')], [130, 'Enter Name : ', -1, (8, 12, 80, 17), 1342177280], [129, '', 2095, (55, 10, 100, 12), 1350631552], [128, 'Search', 2098, (160, 10, 50, 14), 1342242816], ['SysListView32', 'List1', 2096, (8, 40, 200, 185), 1353711657], [128, 'Select', 2097, (170, 230, 40, 14), 1342242816]]}
ids = {'IDC_BUT_DEL_OBJECT': 2012, 'IDD_OPEN_PARTNER_DIALOG': 2084, 'IDD_SELECT_STATE': 2099, 'IDC_DELAY1_SLIDER': 1056, 'IDC_PROGRESS': 1000, 'IDD_MANAGER': 101, 'IDC_ABOUT': 2028, 'IDD_DIAGNOSTIC': 113, 'IDET_PARTNER_COUNTRY': 2063, 'IDD_TRAINING': 102, 'ID_CONTACT_EMAIL_TEXT': 40008, 'IDC_DELAY2_TEXT': 1059, 'IDC_DELAY1_TEXT': 1057, 'IDD_WIZARD': 114, 'IDC_CHKBX': 2023, 'IDC_STATIC_HAM': 1002, 'IDC_PROGRESS_TEXT': 1001, 'IDR_XMLS_PROTOCOL': 2042, 'IDD_GENERAL': 108, 'IDD_ABOUT': 2027, 'IDD_SYNC': 40002, 'IDC_TAB': 1068, 'IDC_FOLDER_UNSURE': 1033, '_APS_NEXT_SYMED_VALUE': 101, 'IDC_VERBOSE_LOG': 1061, 'IDC_EDIT1': 1094, 'IDC_BROWSE': 1037, 'ID_DB_DROPDOWNLIST': 2004, 'IDC_BACK_BTN': 1069, 'ID_CONTACT_NAME_TEXT': 40005, 'IDPB_PARTNER_SEARCH': 2077, 'IDD_WIZARD_FINISHED_UNCONFIGURED': 119, 'IDC_ACTION_CERTAIN': 1025, 'IDC_BUT_ACT_ALL': 1019, 'IDD_FILTER_NOW': 104, 'IDET_WED_SERVER': 2080, 'ID_WEB_OK': 2091, 'ID_PROTOCOL_GRP': 2040, 'IDC_HEADER': 2017, 'IDC_MARK_SPAM_AS_READ': 1047, 'IDPB_NEW_PARTNER_BUTTON': 2092, 'ID_PARTNER_NAME_TEXT': 2036, 'IDC_RECOVER_RS': 1075, 'IDC_NAME_LIST1': 2037, 'ID_CONTACT_OFFICE_TEXT': 40006, 'IDC_STATIC': -1, 'IDC_PAGE_PLACEHOLDER': 1078, 'IDC_BROWSE_WATCH': 1039, 'IDET_ZIP': 40010, 'IDET_PARTNER_CITY': 40011, 'IDET_PARTNER_LINK_TEXT': 2085, 'IDC_FOLDER_HAM': 1083, 'IDC_LIST_COUNTRY': 2096, 'IDD_WIZARD_FOLDERS_REST': 117, 'IDC_SHOW_DATA_FOLDER': 1071, 'IDC_BUT_ACT_SCORE': 1018, 'IDET_STATE_SEARCH_NAME': 2100, 'IDET_WEB_SERVER': 2089, '_APS_NEXT_RESOURCE_VALUE': 128, 'ID_SET_WEB_CONNECTION': 2082, 'IDC_LIST_STATE': 2101, 'IDC_CONTACT_LIST': 2029, 'IDC_SLIDER_CERTAIN': 1023, 'IDET_PARTNER_STREET': 2053, 'IDC_BUT_UNREAD': 1020, 'ID_PARTNER_DROPDOWNLIST': 2032, 'ID_COUNTRY_DROPLIST': 2065, 'IDC_BUT_ABOUT': 1017, 'IDC_BUT_RESCORE': 1008, 'IDC_BUT_SEARCHSUB': 1041, 'IDC_BUT_TRAIN_FROM_SPAM_FOLDER': 1010, 'IDET_PARTNER_MOBILENO': 2050, 'ID_CONTACT_MOBILE_TEXT': 40007, 'IDD_VIEW_PARTNER_DIALOG': 2044, 'IDD_WIZARD_FOLDERS_TRAIN': 120, 'IDC_BUT_FILTER_ENABLE': 1013, 'IDPB_WEB_CONNECTION': 2083, 'IDC_ABOUT_BTN': 1072, 'IDD_WIZARD_FINISHED_TRAINED': 122, 'ID_SERVER': 2001, 'IDD_SELECT_PARTNER': 2073, 'IDET_NC_PARTNER_STATE': 2106, 'IDD_FOLDER_SELECTOR': 105, 'IDC_BUT_SET_SERVER_PORT': 2021, 'ID_DONE': 2008, 'IDC_LIST_FOLDERS': 1040, 'IDC_IMAGE_PATH': 2015, 'IDB_SBWIZLOGO': 125, 'IDB_OPENERPLOGO': 1062, 'ID_ZIP_TEXT': 2068, 'IDEB_OPENDOC_LINK_TEXT': 2086, 'IDD_NEW_PARTNER_DIALOG': 2034, 'ID_PARTNER_DROPLIST': 2069, 'IDC_BUT_VIEW_LOG': 1093, 'IDC_STATUS2': 1044, 'IDC_STATUS1': 1043, 'IDCANCEL': 2, 'IDC_BROWSE_HAM': 1004, 'ID_BUT_TESTCONNECTION': 2007, 'IDR_NETRPC_PROTOCOL': 2043, 'IDC_BROWSE_SPAM': 1005, 'IDD_OPEN_DOCUEMNT_DIALOG': 2087, 'IDD_WIZARD_FINISHED_UNTRAINED': 116, 'IDC_MARK_UNSURE_AS_READ': 1051, 'IDPB_SEARCH_COUNTRY1': 2105, 'ID_PARTNER_CITY_TEXT': 2067, 'IDC_BUT_WIZARD': 1070, 'IDC_VERSION': 1009, 'ID_NEW_PARTNER_BUTTON': 2033, 'IDC_FOLDER_NAMES': 1036, 'ID_ATT_METHOD_DROPDOWNLIST': 2025, 'IDC_BUT_TIMER_ENABLED': 1091, 'IDPB_WRITE_CHANGES': 2059, 'IDC_SLIDER_UNSURE': 1029, 'IDC_BUT_NEW': 1046, 'IDC_FOLDER_WATCH': 1038, 'IDPB_CREATE_NEW_PARTNER': 2078, 'IDC_BUT_UNTRAINED': 1088, 'IDC_STATIC_SPAM': 1003, 'IDD_NEW_CONTACT_DIALOG': 2031, 'IDC_EDIT_UNSURE': 1030, 'IDC_BUT_CLEARALL': 1042, 'IDC_BUT_UNSEEN': 1021, 'IDC_OBJECT_NAME': 2014, 'IDD_WIZARD_FOLDERS_WATCH': 118, 'IDPB_SEARCH_STATE': 2103, 'IDET_COUNTRY_SEARCH_NAME': 2095, 'IDC_BUT_SAVE_OBJECT': 2011, 'ID_FED_STATE_DROPLIST': 2064, 'ID_ALL_COUNTRY_DROPDOWNLIST': 2061, 'IDC_EDIT_CERTAIN': 1024, 'IDC_BUT_FILTER_DEFINE': 1016, 'ID_NEW_PART_BUTTON': 2070, 'ID_FAX_TEXT': 2066, 'IDD_WIZARD_TRAINING_IS_IMPORTANT': 123, 'ID_ALL_STATE_DROPDOWNLIST': 2060, 'IDPB_SEARCH_STATE1': 2104, 'IDC_INBOX_TIMER_ONLY': 1060, 'IDPB_SEARCH_PARTNER': 2052, 'ID_USERNAME': 2005, '_APS_NEXT_CONTROL_VALUE': 1096, 'IDC_WIZ_GRAPHIC': 1092, 'IDD_OBJECT_SETTINGS': 2009, 'IDD_FILTER_UNSURE': 111, 'IDC_DEL_SPAM_RS': 1074, 'IDD_SELECT_COUNTRY': 2094, 'ID_SERVER_PORT': 2003, 'IDR_XML_PROTOCOL': 2041, 'IDET_PARTNER_OFFICENO': 2048, 'IDB_FOLDERS': 127, 'IDC_BUT_PREPARATION': 1081, 'ID_STREET2_TEXT': 2063, 'IDC_DELAY2_SLIDER': 1058, 'IDET_PARTNER': 2064, 'IDC_SAVE_SPAM_SCORE': 1048, 'IDC_OBJECT_TITLE': 2013, 'IDC_FOLDER_CERTAIN': 1027, 'IDET_WEB_PORT': 2090, 'IDC_BROWSE_UNSURE': 1034, 'IDC_STATISTICS': 1095, 'IDPB_STATE_SEARCH': 40012, 'ID_MAKE_ATTACHMENT': 2019, 'IDC_BUT_LOAD_IMAGE': 2010, 'IDC_NAME_LIST': 2026, 'IDC_BUT_TRAIN_TO_SPAM_FOLDER': 1011, 'IDET_PARTNER_SEARCH_NAME': 2076, 'IDC_BUT_RESET': 1073, 'ID_SEARCH': 40004, 'IDET_PARTNER_CONTACT_NAME': 2046, 'IDPB_SELECT_STATE': 2102, 'IDC_ACTION_UNSURE': 1031, 'IDD_WIZARD_TRAIN': 121, 'IDC_STATIC_GROUP': 2024, 'IDPB_NEWPARTNER_BUTTON': 2071, 'ID_PARTNER_TEXT': 2079, 'IDD_WIZARD_FINISHED_TRAIN_LATER': 124, 'IDET_PARTNER_NAME': 2045, 'IDPB_NEW_PART_BUTTON': 2093, 'IDC_BUT_REBUILD': 1007, 'IDET_PARTNER_STREET2': 2054, 'IDPB_SEARCH_COUNTRY': 2098, 'ID_SAVE_PARTNER_BUTTON': 2035, 'IDPB_SELECT_PARTNER': 2075, 'ID_STREET_TEXT': 2062, '_APS_NEXT_COMMAND_VALUE': 40001, 'IDET_SEARCH_PARTNER': 2051, 'IDC_LIST_PARTNER': 2072, 'IDD_WEB_SERVER_PORT_DIALOG': 2088, 'ID_PORT': 2002, 'IDD_SERVER_PORT_DIALOG': 2022, 'IDET_PARTNER_STATE': 2062, 'IDPB_SELECT_COUNTRY': 2097, 'ID_SEARCH_TEXT': 40003, 'IDET_NC_PARTNER_COUNTRY': 2108, 'ID_CREATE_CONTACT': 2018, 'IDC_FORWARD_BTN': 1077, 'IDC_TRAINING_STATUS': 1035, 'IDD_WIZARD_WELCOME': 115, 'IDET_PARTNER_FAX': 2058, 'IDC_BUT_TRAIN': 1089, 'IDC_LIST': 2016, 'ID_CREATE_CASE': 2020, 'IDET_PARTNER_EMAIL': 2047, 'IDC_START': 1006, 'IDD_FILTER': 103, 'IDC_RELOAD': 2038, 'ID_PASSWORD': 2006, 'ID_NAME_TEXT': 2030, 'IDC_FILTER_STATUS': 1014, 'IDPB_NC_SEARCH_STATE1': 2107, 'ID_CONTACT_SAVE_BUTTON': 40009, 'IDOK': 1, 'IDC_BROWSE_CERTAIN': 1028, 'IDC_BUT_SHOW_DIAGNOSTICS': 1080, 'IDC_BUT_TRAIN_NOW': 1012, 'IDPB_NC_SEARCH_COUNTRY1': 2109}
names = {1024: 'IDC_EDIT_CERTAIN', 1: 'IDOK', 2: 'IDCANCEL', 1027: 'IDC_FOLDER_CERTAIN', 1028: 'IDC_BROWSE_CERTAIN', 1029: 'IDC_SLIDER_UNSURE', 1030: 'IDC_EDIT_UNSURE', 1031: 'IDC_ACTION_UNSURE', 1033: 'IDC_FOLDER_UNSURE', 1034: 'IDC_BROWSE_UNSURE', 1035: 'IDC_TRAINING_STATUS', 1036: 'IDC_FOLDER_NAMES', 1037: 'IDC_BROWSE', 1038: 'IDC_FOLDER_WATCH', 1039: 'IDC_BROWSE_WATCH', 1040: 'IDC_LIST_FOLDERS', 1041: 'IDC_BUT_SEARCHSUB', 1042: 'IDC_BUT_CLEARALL', 1043: 'IDC_STATUS1', 1044: 'IDC_STATUS2', 2069: 'ID_PARTNER_DROPLIST', 1046: 'IDC_BUT_NEW', 1047: 'IDC_MARK_SPAM_AS_READ', 1048: 'IDC_SAVE_SPAM_SCORE', 2052: 'IDPB_SEARCH_PARTNER', 1051: 'IDC_MARK_UNSURE_AS_READ', 2076: 'IDET_PARTNER_SEARCH_NAME', 2077: 'IDPB_PARTNER_SEARCH', 2078: 'IDPB_CREATE_NEW_PARTNER', 2053: 'IDET_PARTNER_STREET', 1056: 'IDC_DELAY1_SLIDER', 1057: 'IDC_DELAY1_TEXT', 1058: 'IDC_DELAY2_SLIDER', 1059: 'IDC_DELAY2_TEXT', 1060: 'IDC_INBOX_TIMER_ONLY', 1061: 'IDC_VERBOSE_LOG', 1062: 'IDB_OPENERPLOGO', 2047: 'IDET_PARTNER_EMAIL', 2088: 'IDD_WEB_SERVER_PORT_DIALOG', 2089: 'IDET_WEB_SERVER', 2090: 'IDET_WEB_PORT', 2091: 'ID_WEB_OK', 1068: 'IDC_TAB', 1069: 'IDC_BACK_BTN', 1070: 'IDC_BUT_WIZARD', 1071: 'IDC_SHOW_DATA_FOLDER', 1072: 'IDC_ABOUT_BTN', 1073: 'IDC_BUT_RESET', 1074: 'IDC_DEL_SPAM_RS', 1075: 'IDC_RECOVER_RS', 2100: 'IDET_STATE_SEARCH_NAME', 1077: 'IDC_FORWARD_BTN', 1078: 'IDC_PAGE_PLACEHOLDER', 2057: 'IDET_PARTNER_COUNTRY', 1080: 'IDC_BUT_SHOW_DIAGNOSTICS', 1081: 'IDC_BUT_PREPARATION', 2106: 'IDET_NC_PARTNER_STATE', 1083: 'IDC_FOLDER_HAM', 2108: 'IDET_NC_PARTNER_COUNTRY', 2058: 'IDET_PARTNER_FAX', 1088: 'IDC_BUT_UNTRAINED', 1089: 'IDC_BUT_TRAIN', 40002: 'IDD_SYNC', 1091: 'IDC_BUT_TIMER_ENABLED', 1025: 'IDC_ACTION_CERTAIN', 1093: 'IDC_BUT_VIEW_LOG', 1094: 'IDC_EDIT1', 1095: 'IDC_STATISTICS', 1096: '_APS_NEXT_CONTROL_VALUE', 2060: 'ID_ALL_STATE_DROPDOWNLIST', 40010: 'IDET_ZIP', 40011: 'IDET_PARTNER_CITY', 40012: 'IDPB_STATE_SEARCH', 2061: 'ID_ALL_COUNTRY_DROPDOWNLIST', 2062: 'IDET_PARTNER_STATE', 2063: 'IDET_PARTNER_COUNTRY', 2064: 'IDET_PARTNER', 101: 'IDD_MANAGER', 102: 'IDD_TRAINING', 103: 'IDD_FILTER', 104: 'IDD_FILTER_NOW', 105: 'IDD_FOLDER_SELECTOR', 106: 'IDD_ABOUT', 108: 'IDD_GENERAL', 2066: 'ID_FAX_TEXT', 111: 'IDD_FILTER_UNSURE', 113: 'IDD_DIAGNOSTIC', 114: 'IDD_WIZARD', 115: 'IDD_WIZARD_WELCOME', 116: 'IDD_WIZARD_FINISHED_UNTRAINED', 117: 'IDD_WIZARD_FOLDERS_REST', 118: 'IDD_WIZARD_FOLDERS_WATCH', 119: 'IDD_WIZARD_FINISHED_UNCONFIGURED', 120: 'IDD_WIZARD_FOLDERS_TRAIN', 121: 'IDD_WIZARD_TRAIN', 122: 'IDD_WIZARD_FINISHED_TRAINED', 123: 'IDD_WIZARD_TRAINING_IS_IMPORTANT', 124: 'IDD_WIZARD_FINISHED_TRAIN_LATER', 125: 'IDB_SBWIZLOGO', 127: 'IDB_FOLDERS', 2067: 'ID_PARTNER_CITY_TEXT', 2050: 'IDET_PARTNER_MOBILENO', 2070: 'ID_NEW_PART_BUTTON', 2071: 'IDPB_NEWPARTNER_BUTTON', 2072: 'IDC_LIST_PARTNER', 2073: 'IDD_SELECT_PARTNER', 2068: 'ID_ZIP_TEXT', 2051: 'IDET_SEARCH_PARTNER', 2075: 'IDPB_SELECT_PARTNER', 2079: 'ID_PARTNER_TEXT', 2080: 'IDET_WED_SERVER', 2081: 'IDET_WEB_PORT', 2082: 'ID_SET_WEB_CONNECTION', 2083: 'IDPB_WEB_CONNECTION', 2084: 'IDD_OPEN_PARTNER_DIALOG', 2085: 'IDET_PARTNER_LINK_TEXT', 40004: 'ID_SEARCH', 2086: 'IDEB_OPENDOC_LINK_TEXT', 2087: 'IDD_OPEN_DOCUEMNT_DIALOG', 2046: 'IDET_PARTNER_CONTACT_NAME', 2105: 'IDPB_SEARCH_COUNTRY1', 2054: 'IDET_PARTNER_STREET2', 128: '_APS_NEXT_RESOURCE_VALUE', 2092: 'IDPB_NEW_PARTNER_BUTTON', 2093: 'IDPB_NEW_PART_BUTTON', 2094: 'IDD_SELECT_COUNTRY', 2095: 'IDET_COUNTRY_SEARCH_NAME', 2096: 'IDC_LIST_COUNTRY', 2097: 'IDPB_SELECT_COUNTRY', 2098: 'IDPB_SEARCH_COUNTRY', 2099: 'IDD_SELECT_STATE', 2101: 'IDC_LIST_STATE', 2102: 'IDPB_SELECT_STATE', 2103: 'IDPB_SEARCH_STATE', 2104: 'IDPB_SEARCH_STATE1', 2040: 'ID_PROTOCOL_GRP', 2065: 'ID_COUNTRY_DROPLIST', 2048: 'IDET_PARTNER_OFFICENO', 2107: 'IDPB_NC_SEARCH_STATE1', 2109: 'IDPB_NC_SEARCH_COUNTRY1', 2024: 'IDC_STATIC_GROUP', 2041: 'IDR_XML_PROTOCOL', 2025: 'ID_ATT_METHOD_DROPDOWNLIST', 2026: 'IDC_NAME_LIST', 2027: 'IDD_ABOUT', 40001: '_APS_NEXT_COMMAND_VALUE', 2028: 'IDC_ABOUT', 2029: 'IDC_CONTACT_LIST', 2059: 'IDPB_WRITE_CHANGES', 2042: 'IDR_XMLS_PROTOCOL', 40003: 'ID_SEARCH_TEXT', 2030: 'ID_NAME_TEXT', 1092: 'IDC_WIZ_GRAPHIC', 2031: 'IDD_NEW_CONTACT_DIALOG', 40005: 'ID_CONTACT_NAME_TEXT', 2032: 'ID_PARTNER_DROPDOWNLIST', 40006: 'ID_CONTACT_OFFICE_TEXT', 2033: 'ID_NEW_PARTNER_BUTTON', 40007: 'ID_CONTACT_MOBILE_TEXT', 2034: 'IDD_NEW_PARTNER_DIALOG', 2043: 'IDR_NETRPC_PROTOCOL', 40008: 'ID_CONTACT_EMAIL_TEXT', 2035: 'ID_SAVE_PARTNER_BUTTON', 40009: 'ID_CONTACT_SAVE_BUTTON', 2036: 'ID_PARTNER_NAME_TEXT', 2037: 'IDC_NAME_LIST1', 2038: 'IDC_RELOAD', 2044: 'IDD_VIEW_PARTNER_DIALOG', 2001: 'ID_SERVER', 2002: 'ID_PORT', 2003: 'ID_SERVER_PORT', 2004: 'ID_DB_DROPDOWNLIST', 2005: 'ID_USERNAME', 2006: 'ID_PASSWORD', 2007: 'ID_BUT_TESTCONNECTION', 2008: 'ID_DONE', 2009: 'IDD_OBJECT_SETTINGS', 2010: 'IDC_BUT_LOAD_IMAGE', 2011: 'IDC_BUT_SAVE_OBJECT', 2012: 'IDC_BUT_DEL_OBJECT', 2013: 'IDC_OBJECT_TITLE', 2014: 'IDC_OBJECT_NAME', 2015: 'IDC_IMAGE_PATH', 2016: 'IDC_LIST', 2017: 'IDC_HEADER', 2018: 'ID_CREATE_CONTACT', 2019: 'ID_MAKE_ATTACHMENT', 2020: 'ID_CREATE_CASE', 2021: 'IDC_BUT_SET_SERVER_PORT', 2022: 'IDD_SERVER_PORT_DIALOG', 2023: 'IDC_CHKBX', 1000: 'IDC_PROGRESS', 1001: 'IDC_PROGRESS_TEXT', 1002: 'IDC_STATIC_HAM', 1003: 'IDC_STATIC_SPAM', 1004: 'IDC_BROWSE_HAM', 1005: 'IDC_BROWSE_SPAM', 1006: 'IDC_START', 1007: 'IDC_BUT_REBUILD', 1008: 'IDC_BUT_RESCORE', 1009: 'IDC_VERSION', 1010: 'IDC_BUT_TRAIN_FROM_SPAM_FOLDER', 1011: 'IDC_BUT_TRAIN_TO_SPAM_FOLDER', 1012: 'IDC_BUT_TRAIN_NOW', 1013: 'IDC_BUT_FILTER_ENABLE', 1014: 'IDC_FILTER_STATUS', 2045: 'IDET_PARTNER_NAME', 1016: 'IDC_BUT_FILTER_DEFINE', 1017: 'IDC_BUT_ABOUT', 1018: 'IDC_BUT_ACT_SCORE', 1019: 'IDC_BUT_ACT_ALL', 1020: 'IDC_BUT_UNREAD', 1021: 'IDC_BUT_UNSEEN', -1: 'IDC_STATIC', 1023: 'IDC_SLIDER_CERTAIN'}
bitmaps = {'IDB_OPENERPLOGO': 'OpenERP_Logo.bmp'}
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.rc b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.rc index 4514d17b0eb..6b620127a33 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.rc +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/dialogs.rc @@ -44,14 +44,14 @@ STYLE DS_SETFONT | WS_CHILD | WS_CAPTION | WS_SYSMENU CAPTION "Connection Parameters"
FONT 8, "Tahoma", 0, 0, 0x1
BEGIN
- GROUPBOX "",IDC_STATIC_GROUP, 10, 10,250,130
+ GROUPBOX "Connection Parameters",IDC_STATIC_GROUP, 10, 10,250,130
LTEXT "Server : ",IDC_STATIC,30,30,100,17
EDITTEXT ID_SERVER_PORT,85,30,120,12,ES_READONLY | WS_VISIBLE | WS_TABSTOP// left top width height
PUSHBUTTON "Change",IDC_BUT_SET_SERVER_PORT,210,30,30,13, WS_VISIBLE | WS_TABSTOP
LTEXT "Database : ",IDC_STATIC,30,50,100,17
- COMBOBOX ID_DB_DROPDOWNLIST,85,50,120,40,CBS_DROPDOWNLIST |
+ COMBOBOX ID_DB_DROPDOWNLIST,85,50,154,40,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_VISIBLE | WS_TABSTOP
- PUSHBUTTON "Reload",IDC_RELOAD,210,50,30,13, WS_VISIBLE | WS_TABSTOP
+
LTEXT "Username : ",IDC_STATIC,30,70,100,17
EDITTEXT ID_USERNAME,85,70,154,12,ES_AUTOHSCROLL | WS_VISIBLE | WS_TABSTOP
LTEXT "Password : ",IDC_STATIC,30,90,100,17
@@ -71,17 +71,17 @@ EXSTYLE WS_EX_CONTEXTHELP CAPTION "Documents Setting"
FONT 8, "Tahoma", 0, 0, 0x1
BEGIN
- GROUPBOX "Document Attributes",IDC_STATIC_GROUP, 2, 2, 340, 32
+ GROUPBOX "Document Attributes",IDC_STATIC_GROUP, 2, 2, 343, 32
- LTEXT "Title",IDC_STATIC,6,15,30,17
- EDITTEXT IDC_OBJECT_TITLE,20,14,57,12,ES_AUTOHSCROLL | WS_TABSTOP// left top width height
- LTEXT "Document Name",IDC_STATIC,83,15,60,17
+ LTEXT "Title:",IDC_STATIC,5,16,30,17
+ EDITTEXT IDC_OBJECT_TITLE,22,14,57,12,ES_AUTOHSCROLL | WS_TABSTOP// left top width height
+ LTEXT "Document Name:",IDC_STATIC,83,16,60,17
EDITTEXT IDC_OBJECT_NAME,138,14,57,12,ES_AUTOHSCROLL | WS_TABSTOP
- LTEXT "Image",IDC_STATIC,200,15,20,17
- EDITTEXT IDC_IMAGE_PATH,220,14,57,12,ES_AUTOHSCROLL | WS_TABSTOP
- PUSHBUTTON "Load Image",IDC_BUT_LOAD_IMAGE,286,13,50,15,WS_TABSTOP
- PUSHBUTTON "Add",IDC_BUT_SAVE_OBJECT,347,13,38,15,WS_TABSTOP
- PUSHBUTTON "Remove",IDC_BUT_DEL_OBJECT,391,13,38,15,WS_TABSTOP
+ LTEXT "Image:",IDC_STATIC,200,16,22,17
+ EDITTEXT IDC_IMAGE_PATH,223,14,57,12,ES_AUTOHSCROLL | WS_TABSTOP
+ PUSHBUTTON "Load Image",IDC_BUT_LOAD_IMAGE,289,13,50,15,WS_TABSTOP
+ PUSHBUTTON "Add",IDC_BUT_SAVE_OBJECT,350,13,38,15,WS_TABSTOP
+ PUSHBUTTON "Delete",IDC_BUT_DEL_OBJECT,392,13,38,15,WS_TABSTOP
CONTROL "List1",IDC_LIST,"SysListView32",WS_CHILD | WS_VISIBLE | WS_BORDER | WS_HSCROLL | WS_VSCROLL |
LVS_SHOWSELALWAYS | LVS_EX_GRIDLINES | LVS_REPORT | LVS_EX_FULLROWSELECT, 8,40,535,160
END
@@ -118,20 +118,20 @@ CAPTION "Push to OpenERP" FONT 8, "Tahoma", 1000, 0, 0x0
BEGIN
GROUPBOX "Link to an Existing Documents ", IDC_STATIC_GROUP, 8,5,250,290,WS_TABSTOP
- LTEXT "Search for : ",IDC_STATIC,15,17,40,12
+ LTEXT "Search : ",IDC_STATIC,15,17,40,12
EDITTEXT ID_SEARCH_TEXT,60,15,120,12,ES_AUTOHSCROLL | WS_TABSTOP// left top width height
PUSHBUTTON "Search",ID_SEARCH,187,15,40,14,WS_TABSTOP
LTEXT "Documents : ",IDC_STATIC,15,140,100,14
CONTROL "List1",IDC_NAME_LIST,"SysListView32",WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_SHOWSELALWAYS | LVS_REPORT | WS_TABSTOP, 15,150,234,110
PUSHBUTTON "Push",ID_MAKE_ATTACHMENT,160,270,85,14,WS_TABSTOP
- GROUPBOX " Create a Document ", IDC_STATIC_GROUP, 263,5,202,100,WS_TABSTOP
+ GROUPBOX " Create a New Document ", IDC_STATIC_GROUP, 263,5,202,100,WS_TABSTOP
LTEXT "Type of Document : ",IDC_STATIC,266,25,100,12
COMBOBOX ID_ATT_METHOD_DROPDOWNLIST,332,24,75,45,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Create",ID_CREATE_CASE,412,23,50,14,WS_TABSTOP
- GROUPBOX " Create a Contact ", IDC_STATIC_GROUP, 263, 110,202,185,WS_TABSTOP
+ GROUPBOX " Create a New Contact ", IDC_STATIC_GROUP, 263, 110,202,185,WS_TABSTOP
LTEXT "Create a New Contact : ",IDC_STATIC,280,140,100,12
PUSHBUTTON "Create Contact",ID_CREATE_CONTACT,360,138,60,14,WS_TABSTOP
PUSHBUTTON "Close",IDCANCEL,385,300,60,14,WS_TABSTOP
@@ -160,12 +160,15 @@ BEGIN EDITTEXT ID_ZIP_TEXT,76, 93, 100, 12,ES_AUTOHSCROLL | WS_TABSTOP
LTEXT "City : ",IDC_STATIC, 18,106, 50, 17
EDITTEXT ID_PARTNER_CITY_TEXT,76,107,100,12,ES_AUTOHSCROLL | WS_TABSTOP
- LTEXT "Fed. State : ",IDC_STATIC,18,121,50,17
- EDITTEXT IDET_NC_PARTNER_STATE, 76, 122, 54, 12,ES_AUTOHSCROLL |ES_READONLY
- PUSHBUTTON "Search", IDPB_NC_SEARCH_STATE1 ,135, 121, 40, 12, WS_TABSTOP
- LTEXT "Country :",IDC_STATIC, 18, 134, 35, 17
- EDITTEXT IDET_NC_PARTNER_COUNTRY, 76, 135, 54, 12,ES_AUTOHSCROLL |ES_READONLY
- PUSHBUTTON "Search", IDPB_NC_SEARCH_COUNTRY1, 135, 136, 40, 12, WS_TABSTOP
+
+
+ LTEXT "Fed. State : ",IDC_STATIC,18, 134, 50, 15
+ EDITTEXT IDET_NC_PARTNER_STATE, 76, 135, 54, 12,ES_AUTOHSCROLL |ES_READONLY
+ PUSHBUTTON "Search", IDPB_NC_SEARCH_STATE1 ,135, 136, 40, 12, WS_TABSTOP
+
+ LTEXT "Country :",IDC_STATIC, 18,121,35,15
+ EDITTEXT IDET_NC_PARTNER_COUNTRY, 76, 122, 54, 12,ES_AUTOHSCROLL |ES_READONLY
+ PUSHBUTTON "Search", IDPB_NC_SEARCH_COUNTRY1, 135, 121, 40, 12, WS_TABSTOP
GROUPBOX "Communication ", IDC_STATIC_GROUP, 188, 35, 150, 123
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo.png b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo.png Binary files differindex 1b7461953a1..1b7461953a1 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo.png +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo.png diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo1.bmp b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo1.bmp Binary files differindex 45b745dec86..4e40d9e989a 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo1.bmp +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/openerp_logo1.bmp diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rc2py.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rc2py.py index d944fc2dd99..d944fc2dd99 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rc2py.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rc2py.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rcparser.py b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rcparser.py index 0b05af3f0be..0b05af3f0be 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rcparser.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/dialogs/resources/rcparser.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/eml.py b/addons/outlook/plugin/openerp-outlook-plugin/eml.py index ded81a16c6d..84d5a50df44 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/eml.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/eml.py @@ -94,4 +94,4 @@ def generateEML(mail): if (success == False):
print cemail.lastErrorText()
sys.exit()
- return new_mail
+ return new_mail
\ No newline at end of file diff --git a/addons/outlook/plugin/openerp-outlook-plugin/manager.py b/addons/outlook/plugin/openerp-outlook-plugin/manager.py index 783da92bb2a..783da92bb2a 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/manager.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/manager.py diff --git a/addons/outlook/plugin/openerp-outlook-plugin/outlookaddin.iss b/addons/outlook/plugin/openerp-outlook-plugin/outlookaddin.iss new file mode 100644 index 00000000000..b47f87c60d0 --- /dev/null +++ b/addons/outlook/plugin/openerp-outlook-plugin/outlookaddin.iss @@ -0,0 +1,107 @@ +; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{AF02E62E-3A5A-4E86-B4CF-03F2B2AC25BF}
+AppName=Openerp Outlook Addin
+AppVersion=1.0
+AppVerName=Openerp Outlook Addin 1.0
+AppPublisher=Openerp SA
+AppPublisherURL=http://www.openerp.com/
+AppSupportURL=http://www.openerp.com/
+AppUpdatesURL=http://www.openerp.com/
+DefaultDirName={pf}\Openerp Outlook Addin
+DefaultGroupName=Openerp Outlook Addin
+DisableProgramGroupPage=true
+OutputBaseFilename=openerp-outlook-addin
+Compression=lzma
+SolidCompression=true
+UserInfoPage=true
+UninstallDisplayIcon={app}\*
+VersionInfoVersion=1.0
+VersionInfoCompany=OpenERP
+VersionInfoDescription=OpenERP Outlook Addin
+VersionInfoProductName=OpenERP
+VersionInfoProductVersion=1.0
+ChangesAssociations=true
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+Name: "basque"; MessagesFile: "compiler:Languages\Basque.isl"
+Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
+Name: "catalan"; MessagesFile: "compiler:Languages\Catalan.isl"
+Name: "czech"; MessagesFile: "compiler:Languages\Czech.isl"
+Name: "danish"; MessagesFile: "compiler:Languages\Danish.isl"
+Name: "dutch"; MessagesFile: "compiler:Languages\Dutch.isl"
+Name: "finnish"; MessagesFile: "compiler:Languages\Finnish.isl"
+Name: "french"; MessagesFile: "compiler:Languages\French.isl"
+Name: "german"; MessagesFile: "compiler:Languages\German.isl"
+Name: "hebrew"; MessagesFile: "compiler:Languages\Hebrew.isl"
+Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl"
+Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
+Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
+Name: "norwegian"; MessagesFile: "compiler:Languages\Norwegian.isl"
+Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
+Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
+Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
+Name: "slovak"; MessagesFile: "compiler:Languages\Slovak.isl"
+Name: "slovenian"; MessagesFile: "compiler:Languages\Slovenian.isl"
+Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
+
+[Files]
+Source: "C:\workspace\openerp-outlook-plugin\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Messages]
+AboutSetupNote=Inno Setup Preprocessor home page:%nhttp://ispp.sourceforge.net/
+
+
+[Run]
+Filename: "{app}\Register-plugin.bat"; StatusMsg: "Registering Outlook Addin";
+[UninstallDelete]
+Type: files; Name: "{app}\Openerp Outlook Addin\*"
+Type: dirifempty; Name: "{app}\Openerp Outlook Addin"
+
+[UninstallRun]
+Filename: "{app}\Unregister-plugin.bat"; StatusMsg: "Unregistering Outlook Addin";
+
+
+[Code]
+function InitializeSetup(): Boolean;
+begin
+ Result := true;
+
+ if not RegKeyExists( HKLM, 'Software\Python\PythonCore') then begin
+ Result := MsgBox(
+ 'Python appears to not be installed.' + #13 + #13 +
+ 'This addin requires Python 2.5 or above installed with compatible pywin32 for python for working.'+ #13 + #13 +
+ 'If you know that Python is installed, you may with to continue.' + #13 + #13 +
+ 'Continue with installation?',
+ mbConfirmation, MB_YESNO) = idYes;
+ end;
+ if not RegKeyExists( HKCU, 'Software\Microsoft\Office\Outlook') then begin
+ Result := MsgBox(
+ 'Outlook appears to not be installed.' + #13 + #13 +
+ 'This addin only works with Microsoft Outlook 2000 and later - it' + #13 +
+ 'does not work with Outlook express.' + #13 + #13 +
+ 'If you know that Outlook is installed, you may with to continue.' + #13 + #13 +
+ 'Continue with installation?',
+ mbConfirmation, MB_YESNO) = idYes;
+ end;
+ while Result do begin
+ if not CheckForMutexes('_outlook_mutex_') then
+ break;
+
+ Result := MsgBox(
+ 'You must close Outlook before OpenERP Outlook Addin can be installed.' + #13 + #13 +
+ 'Please close all Outlook Windows (using "File->Exit and Log off"' + #13 +
+ 'if available) and click Retry, or click Cancel to exit the installation.'+ #13 + #13 +
+ 'If this message persists after closing all Outlook windows, you may' + #13 +
+ 'need to log off from Windows, and try again.',
+ mbConfirmation, MB_RETRYCANCEL) = idRetry;
+ end;
+end;
+
diff --git a/addons/outlook/plugin/openerp-outlook-plugin/tiny_xmlrpc.py b/addons/outlook/plugin/openerp-outlook-plugin/tiny_xmlrpc.py index d520283bd2d..dc02d956f3c 100755..100644 --- a/addons/outlook/plugin/openerp-outlook-plugin/tiny_xmlrpc.py +++ b/addons/outlook/plugin/openerp-outlook-plugin/tiny_xmlrpc.py @@ -23,17 +23,15 @@ import xmlrpclib import sys
import socket
import os
-import pythoncom
import time
from manager import ustr
-import email
-from win32com.mapi import mapi, mapiutil, mapitags
+from win32com.mapi import mapitags
import pythoncom
-import win32com
+import win32com
+import win32ui
waittime = 10
wait_count = 0
wait_limit = 12
-
def execute(connector, method, *args):
global wait_count
res = False
@@ -42,9 +40,9 @@ def execute(connector, method, *args): except socket.error,e:
if e.args[0] == 111:
if wait_count > wait_limit:
- print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit)
- # clean() Commented...
- sys.exit(1)
+ print "Server is taking too long to start, it has exceeded the maximum limit of %d seconds."%(wait_limit)
+ clean()
+ sys.exit(1)
print 'Please wait %d sec to start server....'%(waittime)
wait_count += 1
time.sleep(waittime)
@@ -58,10 +56,10 @@ class XMLRpcConn(object): __name__ = 'XMLRpcConn'
_com_interfaces_ = ['_IDTExtensibility2']
_public_methods_ = ['GetDBList', 'login', 'GetAllObjects', 'GetObjList', 'InsertObj', 'DeleteObject', 'GetCSList', \
- 'ArchiveToOpenERP', 'IsCRMInstalled', 'GetPartners', 'GetObjectItems', \
- 'CreateCase', 'MakeAttachment', 'CreateContact', 'CreatePartner', 'getitem', 'setitem', \
- 'SearchPartnerDetail', 'WritePartnerValues', 'GetAllState', 'GetAllCountry', 'SearchPartner', 'SearchEmailResources', \
- 'GetCountry', 'GetStates', 'FindCountryForState']
+ 'ArchiveToOpenERP', 'IsCRMInstalled', 'GetPartners', 'GetObjectItems', \
+ 'CreateCase', 'MakeAttachment', 'CreateContact', 'CreatePartner', 'getitem', 'setitem', \
+ 'SearchPartnerDetail', 'WritePartnerValues', 'GetAllState', 'GetAllCountry', 'SearchPartner', 'SearchEmailResources', \
+ 'GetCountry', 'GetStates', 'FindCountryForState','CreateEmailAttachment']
_reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
_reg_clsid_ = "{C6399AFD-763A-400F-8191-7F9D0503CAE2}"
_reg_progid_ = "Python.OpenERP.XMLRpcConn"
@@ -82,426 +80,460 @@ class XMLRpcConn(object): self.protocol=None
def getitem(self, attrib):
- v=self.__getattribute__(attrib)
- return str(v)
+ v=self.__getattribute__(attrib)
+ return str(v)
def setitem(self, attrib, value):
- return self.__setattr__(attrib, value)
+ return self.__setattr__(attrib, value)
def GetDBList(self):
- conn = xmlrpclib.ServerProxy(self._uri + '/xmlrpc/db')
- try:
- db_list = execute(conn, 'list')
- if db_list == False:
- self._running=False
- return []
- else:
- self._running=True
- except:
- db_list=-1
- self._running=True
- return db_list
+ conn = xmlrpclib.ServerProxy(self._uri + '/xmlrpc/db')
+ try:
+ db_list = execute(conn, 'list')
+ if db_list == False:
+ self._running=False
+ return []
+ else:
+ self._running=True
+ except:
+ db_list=-1
+ self._running=True
+ return db_list
def login(self,dbname, user, pwd):
- self._dbname = dbname
- self._uname = user
- self._pwd = pwd
- conn = xmlrpclib.ServerProxy(str(self._uri) + '/xmlrpc/common')
- uid = execute(conn,'login',dbname, ustr(user), ustr(pwd))
- return uid
+ self._dbname = dbname
+ self._uname = user
+ self._pwd = pwd
+ conn = xmlrpclib.ServerProxy(str(self._uri) + '/xmlrpc/common')
+ uid = execute(conn,'login',dbname, ustr(user), ustr(pwd))
+ return uid
def GetAllObjects(self):
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[])
- objects = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','read',ids,['model'])
- obj_list = [item['model'] for item in objects]
- return obj_list
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[])
+ objects = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','read',ids,['model'])
+ obj_list = [item['model'] for item in objects]
+ return obj_list
def GetObjList(self):
- self._obj_list=list(self._obj_list)
- self._obj_list.sort(reverse=True)
- return self._obj_list
+ self._obj_list=list(self._obj_list)
+ self._obj_list.sort(reverse=True)
+ return self._obj_list
def InsertObj(self, obj_title,obj_name,image_path):
- self._obj_list=list(self._obj_list)
- self._obj_list.append((obj_title,obj_name,ustr(image_path)))
- self._obj_list.sort(reverse=True)
+ self._obj_list=list(self._obj_list)
+ self._obj_list.append((obj_title,obj_name,ustr(image_path)))
+ self._obj_list.sort(reverse=True)
def DeleteObject(self,sel_text):
- self._obj_list=list(self._obj_list)
- for obj in self._obj_list:
- if obj[0] == sel_text:
- self._obj_list.remove(obj)
- break
+ self._obj_list=list(self._obj_list)
+ for obj in self._obj_list:
+ if obj[0] == sel_text:
+ self._obj_list.remove(obj)
+ break
def ArchiveToOpenERP(self, recs, mail):
- import win32ui, win32con
- conn = xmlrpclib.ServerProxy(self._uri + '/xmlrpc/object')
- import eml
- flag = False
- new_msg = files = ext_msg =""
- message_id = referances = None
- try:
- outlook = win32com.client.Dispatch("Outlook.Application")
- session = win32com.client.Dispatch("MAPI.session")
- session.Logon('Outlook')
- objMessage = session.GetMessage(mail.EntryID, mail.Parent.StoreID)
- objFields = objMessage.Fields
- strheader = objFields.Item(mapitags.PR_TRANSPORT_MESSAGE_HEADERS)
- strheader = ustr(strheader).encode('iso-8859-1')
- headers = {}
- strheader = strheader.replace("\n ", " ").splitlines()
- for line in strheader:
- split_here = line.find(":")
- headers[line[:split_here]] = line[split_here:]
- temp1 = headers.get('Message-ID')
- temp2 = headers.get('Message-Id')
- referances = headers.get('References')
- if temp1 == None: message_id = temp2
- if temp2 == None: message_id = temp1
- startCut = message_id.find("<")
- endCut = message_id.find(">")
- message_id = message_id[startCut:endCut+1]
- if not referances == None:
- startCut = referances.find("<")
- endCut = referances.find(">")
- referances = referances[startCut:endCut+1]
- except Exception,e:
- win32ui.MessageBox(str(e),"Archive To OpenERP")
- return
- new_mail=eml.generateEML(mail)
- attachments=mail.Attachments
- for rec in recs: #[('res.partner', 3, 'Agrolait')]
+ import win32con
+ conn = xmlrpclib.ServerProxy(self._uri + '/xmlrpc/object')
+ flag = False
+ new_msg = ext_msg =""
+ message_id = referances = None
+ try:
+ session = win32com.client.Dispatch("MAPI.session")
+ session.Logon('Outlook')
+ objMessage = session.GetMessage(mail.EntryID, mail.Parent.StoreID)
+ objFields = objMessage.Fields
+ strheader = objFields.Item(mapitags.PR_TRANSPORT_MESSAGE_HEADERS)
+ strheader = ustr(strheader).encode('iso-8859-1')
+ headers = {}
+ strheader = strheader.replace("\n ", " ").splitlines()
+ for line in strheader:
+ split_here = line.find(":")
+ headers[line[:split_here]] = line[split_here:]
+ temp1 = headers.get('Message-ID')
+ temp2 = headers.get('Message-Id')
+ referances = headers.get('References')
+ if temp1 == None: message_id = temp2
+ if temp2 == None: message_id = temp1
+ startCut = message_id.find("<")
+ endCut = message_id.find(">")
+ message_id = message_id[startCut:endCut+1]
+ if not referances == None:
+ startCut = referances.find("<")
+ endCut = referances.find(">")
+ referances = referances[startCut:endCut+1]
+ except Exception,e:
+ win32ui.MessageBox(str(e),"Archive To OpenERP")
+ return
+ attachments=mail.Attachments
+ for rec in recs: #[('res.partner', 3, 'Agrolait')]
model = rec[0]
res_id = rec[1]
#Check if mailgate installed
object_id = execute ( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=','mailgate.message')])
if not object_id:
- win32ui.MessageBox("Mailgate is not installed on your configured database '%s' !!\n\nPlease install it to archive the mail."%(self._dbname),"Mailgate not installed",win32con.MB_ICONERROR)
- return
-
+ win32ui.MessageBox("Mailgate is not installed on your configured database '%s' !!\n\nPlease install it to archive the mail."%(self._dbname),"Mailgate not installed",win32con.MB_ICONERROR)
+ return
object_ids = execute ( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=',model)])
object_name = execute( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','read',object_ids,['name'])[0]['name']
-
#Reading the Object ir.model Name
-
ext_ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'mailgate.message','search',[('message_id','=',message_id),('model','=',model),('res_id','=',res_id)])
if ext_ids:
- name = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,model,'read',res_id,['name'])['name']
- ext_msg += """This mail is already archived to {0} '{1}'.\n""".format(object_name,name)
- flag = True
- continue
+ name = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,model,'read',res_id,['name'])['name']
+ ext_msg += """This mail is already archived to {0} '{1}'.\n""".format(object_name,name)
+ flag = True
+ continue
msg = {
- 'subject':mail.Subject,
- 'date':str(mail.ReceivedTime),
- 'body':mail.Body,
- 'cc':mail.CC,
- 'from':mail.SenderEmailAddress,
- 'to':mail.To,
- 'message-id':message_id,
- 'references':ustr(referances),
+ 'subject':mail.Subject,
+ 'date':str(mail.ReceivedTime),
+ 'body':mail.Body,
+ 'cc':mail.CC,
+ 'from':mail.SenderEmailAddress,
+ 'to':mail.To,
+ 'message-id':message_id,
+ 'references':ustr(referances),
}
+ obj_list= ['crm.lead','project.issue','hr.applicant','res.partner']
+ if rec[0] not in obj_list:
+ ids = self.CreateEmailAttachment(rec,mail)
result = {}
if attachments:
- result = self.MakeAttachment([rec], mail)
+ result = self.MakeAttachment([rec], mail)
attachment_ids = result.get(model, {}).get(res_id, [])
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'email.server.tools','history',model, res_id, msg, attachment_ids)
new_msg += """- {0} : {1}\n""".format(object_name,str(rec[2]))
flag = True
- if flag:
- t = """Mail archived Successfully with attachments.\n"""+ext_msg
- t += "\n"+new_msg
- win32ui.MessageBox(t,"Archived to OpenERP",win32con.MB_ICONINFORMATION)
- return flag
+ if flag:
+ t = """Mail archived Successfully with attachments.\n"""+ext_msg
+ t += "\n"+new_msg
+ win32ui.MessageBox(t,"Archived to OpenERP",win32con.MB_ICONINFORMATION)
+ return flag
def IsCRMInstalled(self):
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=','crm.lead')])
- return id
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=','crm.lead')])
+ return id
def GetCSList(self):
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids = execute(conn,'execute',self._dbname,int(int(self._uid)),self._pwd,'crm.case.section','search',[])
- objects = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'crm.case.section','read',ids,['name'])
- obj_list = [ustr(item['name']).encode('iso-8859-1') for item in objects]
- return obj_list
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids = execute(conn,'execute',self._dbname,int(int(self._uid)),self._pwd,'crm.case.section','search',[])
+ objects = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'crm.case.section','read',ids,['name'])
+ obj_list = [ustr(item['name']).encode('iso-8859-1') for item in objects]
+ return obj_list
def GetPartners(self, search_partner=''):
- import win32ui
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids=[]
- obj_list=[]
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','search',[('name','ilike',ustr(search_partner))])
- if ids:
- ids.sort()
- obj_list.append((-999, ustr('')))
- for id in ids:
- object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','read',[id],['id','name'])[0]
- obj_list.append((object['id'], ustr(object['name'])))
- obj_list.sort(lambda x, y: cmp(x[1],y[1]))
- return obj_list
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids=[]
+ obj_list=[]
+ domain = []
+ if not search_partner.strip() == '':
+ domain.append(('name','ilike',ustr(search_partner)))
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','search',domain)
+ if ids:
+ ids.sort()
+ obj_list.append((-999, ustr('')))
+ for id in ids:
+ object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','read',[id],['id','name'])[0]
+ obj_list.append((object['id'], ustr(object['name'])))
+ obj_list.sort(lambda x, y: cmp(x[1],y[1]))
+ return obj_list
def GetObjectItems(self, search_list=[], search_text=''):
- import win32ui
- res = []
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- for obj in search_list:
- object_ids = execute ( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=',obj)])
- object_name = execute( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','read',object_ids,['name'])[0]['name']
- if obj == "res.partner.address":
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'search',['|',('name','ilike',ustr(search_text)),('email','ilike',ustr(search_text))])
- recs = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'read',ids,['id','name','street','city'])
- for rec in recs:
- name = ustr(rec['name'])
- if rec['street']:
- name += ', ' + ustr(rec['street'])
- if rec['city']:
- name += ', ' + ustr(rec['city'])
- res.append((obj,rec['id'],name,object_name))
- else:
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'search',[('name','ilike',ustr(search_text))])
- recs = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'read',ids,['id','name'])
- for rec in recs:
- name = ustr(rec['name'])
- res.append((obj,rec['id'],name,object_name))
- return res
+ res = []
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ for obj in search_list:
+ object_ids = execute ( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','search',[('model','=',obj)])
+ object_name = execute( conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.model','read',object_ids,['name'])[0]['name']
+ if obj == "res.partner.address":
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'search',['|',('name','ilike',ustr(search_text)),('email','ilike',ustr(search_text))])
+ recs = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'read',ids,['id','name','street','city'])
+ for rec in recs:
+ name = ustr(rec['name'])
+ if rec['street']:
+ name += ', ' + ustr(rec['street'])
+ if rec['city']:
+ name += ', ' + ustr(rec['city'])
+ res.append((obj,rec['id'],name,object_name))
+ else:
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'search',[('name','ilike',ustr(search_text))])
+ recs = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,obj,'read',ids,['id','name'])
+ for rec in recs:
+ name = ustr(rec['name'])
+ res.append((obj,rec['id'],name,object_name))
+ return res
def CreateCase(self, section, mail, partner_ids, with_attachments=True):
- import win32ui
- import eml
- flag = False
- id = -1
- try:
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- email=eml.generateEML(mail)
- message_id = referances = None
- outlook = win32com.client.Dispatch("Outlook.Application")
- session = win32com.client.Dispatch("MAPI.session")
- session.Logon('Outlook')
- objMessage = session.GetMessage(mail.EntryID, mail.Parent.StoreID)
- objFields = objMessage.Fields
- strheader = objFields.Item(mapitags.PR_TRANSPORT_MESSAGE_HEADERS)
- strheader = ustr(strheader).encode('iso-8859-1')
- headers = {}
- strheader = strheader.replace("\n ", " ").splitlines()
- for line in strheader:
- split_here = line.find(":")
- headers[line[:split_here]] = line[split_here:]
- temp1 = headers.get('Message-ID')
- temp2 = headers.get('Message-Id')
- if temp1 == None: message_id = temp2
- if temp2 == None: message_id = temp1
- startCut = message_id.find("<")
- endCut = message_id.find(">")
- message_id = message_id[startCut:endCut+1]
- email.replace_header('Message-Id',message_id)
- id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'email.server.tools','process_email',section, str(email))
- if id > 0:
- flag = True
- return flag
- else:
- flag = False
- return flag
- except Exception,e:
- win32ui.MessageBox("Create Case\n"+str(e),"Mail Reading Error")
- return flag
+ import eml
+ flag = False
+ id = -1
+ try:
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ email=eml.generateEML(mail)
+ message_id = None
+ session = win32com.client.Dispatch("MAPI.session")
+ session.Logon('Outlook')
+ objMessage = session.GetMessage(mail.EntryID, mail.Parent.StoreID)
+ objFields = objMessage.Fields
+ strheader = objFields.Item(mapitags.PR_TRANSPORT_MESSAGE_HEADERS)
+ strheader = ustr(strheader).encode('iso-8859-1')
+ headers = {}
+ strheader = strheader.replace("\n ", " ").splitlines()
+ for line in strheader:
+ split_here = line.find(":")
+ headers[line[:split_here]] = line[split_here:]
+ temp1 = headers.get('Message-ID')
+ temp2 = headers.get('Message-Id')
+ if temp1 == None: message_id = temp2
+ if temp2 == None: message_id = temp1
+ startCut = message_id.find("<")
+ endCut = message_id.find(">")
+ message_id = message_id[startCut:endCut+1]
+ email.replace_header('Message-Id',message_id)
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'email.server.tools','process_email',section, str(email))
+ if id > 0:
+ flag = True
+ return flag
+ else:
+ flag = False
+ return flag
+ except Exception,e:
+ win32ui.MessageBox("Create Case\n"+str(e),"Mail Reading Error")
+ return flag
def MakeAttachment(self, recs, mail):
- attachments = mail.Attachments
- result = {}
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- att_folder_path = os.path.abspath(os.path.dirname("%temp%\\"))
- if not os.path.exists(att_folder_path):
- os.makedirs(att_folder_path)
- for rec in recs: #[('res.partner', 3, 'Agrolait')]
-
- obj = rec[0]
- obj_id = rec[1]
- res={}
- res['res_model'] = obj
- attachment_ids = []
- if obj not in result:
- result[obj] = {}
- for i in xrange(1, attachments.Count+1):
- fn = ustr(attachments[i].FileName)
- if len(fn) > 64:
- l = 64 - len(fn)
- f = fn.split('.')
- fn = f[0][0:l] + '.' + f[-1]
- att_path = os.path.join(att_folder_path,fn)
- attachments[i].SaveAsFile(att_path)
- f=open(att_path,"rb")
- content = "".join(f.readlines()).encode('base64')
- f.close()
- res['name'] = ustr(attachments[i].DisplayName)
- res['datas_fname'] = ustr(fn)
- res['datas'] = content
- res['res_id'] = obj_id
- id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.attachment','create',res)
- attachment_ids.append(id)
- result[obj].update({obj_id: attachment_ids})
- return result
+ attachments = mail.Attachments
+ result = {}
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ att_folder_path = os.path.abspath(os.path.dirname("%temp%\\"))
+ if not os.path.exists(att_folder_path):
+ os.makedirs(att_folder_path)
+ for rec in recs: #[('res.partner', 3, 'Agrolait')]
+ obj = rec[0]
+ obj_id = rec[1]
+ res={}
+ res['res_model'] = obj
+ attachment_ids = []
+ if obj not in result:
+ result[obj] = {}
+ for i in xrange(1, attachments.Count+1):
+ fn = ustr(attachments[i].FileName)
+ if len(fn) > 64:
+ l = 64 - len(fn)
+ f = fn.split('.')
+ fn = f[0][0:l] + '.' + f[-1]
+ att_path = os.path.join(att_folder_path,fn)
+ attachments[i].SaveAsFile(att_path)
+ f=open(att_path,"rb")
+ content = "".join(f.readlines()).encode('base64')
+ f.close()
+ res['name'] = ustr(attachments[i].DisplayName)
+ res['datas_fname'] = ustr(fn)
+ res['datas'] = content
+ res['res_id'] = obj_id
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.attachment','create',res)
+ attachment_ids.append(id)
+ result[obj].update({obj_id: attachment_ids})
+ return result
def CreateContact(self, res=None):
- res=eval(str(res))
- partner = res['partner_id']
- state = res['state_id']
- country = res['country_id']
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- partner_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner', 'search', [('name','=',ustr(partner))])
- res.update({'partner_id' : partner_id[0]})
- if not state == "":
- country_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [('name','=',ustr(country))])
- res.update({'country_id' : country_id[0]})
- if not country == "":
- state_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [('name','=',ustr(state))])
- res.update({'state_id' : state_id[0]})
- id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner.address','create',res)
- return id
+ res=eval(str(res))
+ partner = res['partner_id']
+ state = res['state_id']
+ country = res['country_id']
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ if not partner.strip() == '':
+ partner_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner', 'search', [('name','=',ustr(partner))])
+ res.update({'partner_id' : partner_id[0]})
+ else:
+ res.pop('partner_id')
+ if not state == "":
+ country_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [('name','=',ustr(country))])
+ res.update({'country_id' : country_id[0]})
+ else:
+ res.pop('country_id')
+ if not country == "":
+ state_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [('name','=',ustr(state))])
+ res.update({'state_id' : state_id[0]})
+ else:
+ res.pop('state_id')
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner.address','create',res)
+ return id
def CreatePartner(self, res):
- res=eval(str(res))
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','search',[('name','=',res['name'])])
- if ids:
- return False
- id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','create',res)
- return id
+ res=eval(str(res))
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','search',[('name','=',res['name'])])
+ if ids:
+ return False
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.partner','create',res)
+ return id
def SearchPartnerDetail(self, search_email_id):
- import win32ui
- res_vals = []
- address = {}
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- address_id = execute(conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'search', [('email','ilike',ustr(search_email_id))])
- if not address_id :
- return
- address = execute(conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address','read',address_id[0],['id','partner_id','name','street','street2','city','state_id','country_id','phone','mobile','email','fax','zip'])
- for key, vals in address.items():
- res_vals.append([key,vals])
- return res_vals
+ res_vals = []
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ address_id = execute(conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'search', [('email','ilike',ustr(search_email_id))])
+ if not address_id :
+ return
+ address = execute(conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address','read',address_id[0],['id','partner_id','name','street','street2','city','state_id','country_id','phone','mobile','email','fax','zip'])
+ for key, vals in address.items():
+ res_vals.append([key,vals])
+ return res_vals
def WritePartnerValues(self, new_vals):
- import win32ui
- flag = -1
- new_dict = dict(new_vals)
- email=new_dict['email']
- partner = new_dict['partner']
- country_val = new_dict['country']
- state_val = new_dict['state']
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- partner_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner', 'search', [('name','=',ustr(partner))])
- country_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [('name','=',ustr(country_val))])
- state_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [('name','=',ustr(state_val))])
- address_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'search', [('email','=',ustr(email))])
- if not partner_id or not address_id or not country_id or not state_id:
- return flag
- address = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address','read',address_id[0],['id','partner_id','state_id','country_id'])
- vals_res_address={
- 'partner_id' : partner_id[0],
- 'name' : new_dict['name'],
- 'street':new_dict['street'],
- 'street2' : new_dict['street2'],
- 'city' : new_dict['city'],
- 'phone' : new_dict['phone'],
- 'mobile' : new_dict['mobile'],
- 'fax' : new_dict['fax'],
- 'zip' : new_dict['zip'],
- 'country_id' : country_id[0],
- 'state_id' : state_id[0]
- }
- temp = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'write', address_id, vals_res_address)
- if temp:
- flag=1
- else:
- flag=0
- return flag
+ flag = -1
+ new_dict = dict(new_vals)
+ email=new_dict['email']
+ partner = new_dict['partner']
+ country_val = new_dict['country']
+ state_val = new_dict['state']
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ partner_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner', 'search', [('name','=',ustr(partner))])
+ country_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [('name','=',ustr(country_val))])
+ state_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [('name','=',ustr(state_val))])
+ address_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'search', [('email','=',ustr(email))])
+ if not partner_id or not address_id or not country_id or not state_id:
+ return flag
+ vals_res_address={
+ 'partner_id' : partner_id[0],
+ 'name' : new_dict['name'],
+ 'street':new_dict['street'],
+ 'street2' : new_dict['street2'],
+ 'city' : new_dict['city'],
+ 'phone' : new_dict['phone'],
+ 'mobile' : new_dict['mobile'],
+ 'fax' : new_dict['fax'],
+ 'zip' : new_dict['zip'],
+ 'country_id' : country_id[0],
+ 'state_id' : state_id[0]
+ }
+ temp = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'write', address_id, vals_res_address)
+ if temp:
+ flag=1
+ else:
+ flag=0
+ return flag
def GetAllState(self):
- import win32ui
- state_list = []
- state_ids = []
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- state_ids = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [])
- for state_id in state_ids:
- obj = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'read', [state_id],['id','name'])[0]
- state_list.append((obj['id'], ustr(obj['name'])))
- return state_list
+ state_list = []
+ state_ids = []
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ state_ids = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'search', [])
+ for state_id in state_ids:
+ obj = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country.state', 'read', [state_id],['id','name'])[0]
+ state_list.append((obj['id'], ustr(obj['name'])))
+ return state_list
def GetAllCountry(self):
- import win32ui
- country_list = []
- country_ids = []
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- country_ids = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [])
- for country_id in country_ids:
- obj = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country','read', [country_id], ['id','name'])[0]
- country_list.append((obj['id'], ustr(obj['name'])))
- return country_list
-
- def SearchPartner(self, partner = ""):
- import win32ui
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- partner_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner', 'search', [('name','=',ustr(partner))])
- if not partner_id:
- return None
- return partner_id[0]
+ country_list = []
+ country_ids = []
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ country_ids = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country', 'search', [])
+ for country_id in country_ids:
+ obj = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.country','read', [country_id], ['id','name'])[0]
+ country_list.append((obj['id'], ustr(obj['name'])))
+ return country_list
+
+ def SearchPartner(self, mail_id = ""):
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ address = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'search', [('email','=',ustr(mail_id))])
+ if not address:
+ return None
+ else:
+ add_rec = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'res.partner.address', 'read', address[0])
+ partner = add_rec.get('partner_id',False)
+ if partner:
+ return partner[0]
+ return True
def SearchEmailResources(self, message_id):
- import win32ui
- import eml
-
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- sub = ""
- res_vals = []
- mail_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'mailgate.message', 'search', [('message_id','=',message_id)])
- if not mail_id:
- return None
- address = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'mailgate.message','read',mail_id[0],['model','res_id'])
- for key, vals in address.items():
- res_vals.append([key,vals])
- return res_vals
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ res_vals = []
+ mail_id = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'mailgate.message', 'search', [('message_id','=',message_id)])
+ if not mail_id:
+ return None
+ address = execute( conn, 'execute', self._dbname, int(self._uid), self._pwd, 'mailgate.message','read',mail_id[0],['model','res_id'])
+ for key, vals in address.items():
+ res_vals.append([key,vals])
+ return res_vals
def GetCountry(self, country_search=''):
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids=[]
- obj_list=[]
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','search',[('name','ilike',ustr(country_search))])
- if ids:
- ids.sort()
- for id in ids:
- object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','read',[id],['id','name'])[0]
- obj_list.append((object['id'], ustr(object['name'])))
- obj_list.sort(lambda x, y: cmp(x[1],y[1]))
- return obj_list
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids=[]
+ obj_list=[]
+ domain = []
+ if not country_search.strip() == '':
+ domain.append(('name','ilike',ustr(country_search)))
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','search',domain)
+ if ids:
+ ids.sort()
+ for id in ids:
+ object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','read',[id],['id','name'])[0]
+ obj_list.append((object['id'], ustr(object['name'])))
+ obj_list.sort(lambda x, y: cmp(x[1],y[1]))
+ return obj_list
def GetStates(self, state_search='', country=None):
- import win32ui
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids = []
- c_id = []
- obj_list = []
- if country == None:
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',[('name','ilike',ustr(state_search))])
- if not country == None:
- c_id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','search',[('name','=',ustr(country))])
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',[('name','ilike',ustr(state_search)),('country_id','=',c_id[0])])
- if ids:
- ids.sort()
- for id in ids:
- object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','read',[id],['id','name'])[0]
- obj_list.append((object['id'], ustr(object['name'])))
- obj_list.sort(lambda x, y: cmp(x[1],y[1]))
- return obj_list
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids = []
+ c_id = []
+ obj_list = []
+ domain = []
+ if not state_search.strip() == '':
+ domain.append(('name','ilike',ustr(state_search)))
+
+ if country == None:
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',domain)
+ if not country == None:
+ c_id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country','search',[('name','=',ustr(country))])
+ domain.append(('country_id','=',c_id[0]))
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',domain)
+ if ids:
+ ids.sort()
+ for id in ids:
+ object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','read',[id],['id','name'])[0]
+ obj_list.append((object['id'], ustr(object['name'])))
+ obj_list.sort(lambda x, y: cmp(x[1],y[1]))
+ return obj_list
+
def FindCountryForState(self, state_search=''):
- import win32ui
- res_vals = []
- conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
- ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',[('name','=',ustr(state_search))])
- if not ids:
- return None
- object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','read',ids)[0]
- country = object['country_id'][1]
- return country
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ ids = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','search',[('name','=',ustr(state_search))])
+ if not ids:
+ return None
+ object = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'res.country.state','read',ids)[0]
+ country = object['country_id'][1]
+ return country
+
+ def CreateEmailAttachment(self, rec, mail):
+ conn = xmlrpclib.ServerProxy(self._uri+ '/xmlrpc/object')
+ obj = rec[0]
+ obj_id = rec[1]
+ res = {}
+ res['res_model'] = obj
+ ls = ['*', '/', '\\', '<', '>', ':', '?', '"', '|', '\t', '\n',':','~']
+ fn = (mail.Subject).replace(' ','')
+ for c in ls:
+ fn = fn.replace(c,'')
+ if len(fn) > 64:
+ l = 64 - len(fn)
+ f = fn.split('-')
+ fn = '-'.join(f[1:])
+ if len(fn) > 64:
+ l = 64 - len(fn)
+ f = fn.split('.')
+ fn = f[0][0:l] + '.' + f[-1]
+ fn = fn[:-4]+'.txt'
+ f = open(fn,"w")
+ body = mail.Body.encode("utf-8")
+ f.writelines(body)
+ f.close()
+ f=open(fn,"rb")
+ content = "".join(f.readlines()).encode('base64')
+ f.close()
+ res['name'] = ustr((mail.Subject).replace(' ',''))
+ res['datas_fname'] = ustr(fn)
+ res['datas'] = content
+ res['res_id'] = obj_id
+ id = execute(conn,'execute',self._dbname,int(self._uid),self._pwd,'ir.attachment','create',res)
+ return id
diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py index 6b1c60ca516..9fd331e1792 100644 --- a/addons/product_visible_discount/product_visible_discount.py +++ b/addons/product_visible_discount/product_visible_discount.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/project/board_project_view.xml b/addons/project/board_project_view.xml index 2bc858a86d4..31b8e5085e2 100644 --- a/addons/project/board_project_view.xml +++ b/addons/project/board_project_view.xml @@ -25,7 +25,7 @@ <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/> <button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/> <button groups="base.group_extended" name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="gtk-sort-descending" help="For changing to delegate state"/> - <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="gtk-apply" help="For changing to done state"/> + <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/> </tree> </field> </record> diff --git a/addons/project/project.py b/addons/project/project.py index 6c9f66dd009..49e2579e92d 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -703,7 +703,7 @@ class project_work(osv.osv): _defaults = { 'user_id': lambda obj, cr, uid, context: uid, - 'date': time.strftime('%Y-%m-%d %H:%M:%S') + 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S') } _order = "date desc" diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 45862a252a6..d90ca07a96c 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -423,7 +423,7 @@ <field name="view_mode">tree,form,calendar,gantt,graph</field> <field eval="False" name="filter"/> <field name="view_id" ref="view_task_tree2"/> - <field name="context">{"search_default_project_id":project_id, "search_default_user_id":uid, "search_default_current": 1}</field> + <field name="context">{"search_default_user_id":uid, "search_default_current": 1}</field> <field name="search_view_id" ref="view_task_search_form"/> <field name="help">A task represents a work that has to be done. Each user works in his own list of tasks where he can record his task work in hours. He can work and close the task itself or delegate it to antoher user. If you delegate a task to another user, you get a new task in pending state, which will be re-opened when you have to review the work achieved. If you install the project_timesheet module, tasks works can be invoiced based on the project configuration. With the project_mrp module, sales orders can create tasks automatically when they are confirmed.</field> </record> diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index bf3b8c07998..8acdc210090 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -46,6 +46,10 @@ <field name="domain_force">[(1,'=',1)]</field> <field name="groups" eval="[(4,ref('project.group_project_manager'))]"/> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('group_project_user'))]"/> + </record> </data> </openerp> diff --git a/addons/project_caldav/project_caldav.py b/addons/project_caldav/project_caldav.py index fb2d62a9684..f1a4bc73e4b 100644 --- a/addons/project_caldav/project_caldav.py +++ b/addons/project_caldav/project_caldav.py @@ -22,7 +22,8 @@ from osv import fields, osv from caldav import calendar from datetime import datetime - +from tools.translate import _ +from base_calendar import base_calendar from project.project import task as base_project_task class project_task(osv.osv): @@ -45,6 +46,41 @@ class project_task(osv.osv): 'state': 'draft', } + + def open_task(self, cr, uid, ids, context=None): + """ + Open Task Form for Project Task. + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of project task’s IDs + @param context: A standard dictionary for contextual values + @return: Dictionary value which open Project Task form. + """ + + if not context: + context = {} + + data_pool = self.pool.get('ir.model.data') + value = {} + task_form_id = data_pool.get_object(cr, uid, 'project', 'view_task_form2') + task_tree_id = data_pool.get_object(cr, uid, 'project', 'view_task_tree2') + task_calendar_id = data_pool.get_object(cr, uid, 'project', 'view_task_calendar') + for id in ids: + value = { + 'name': _('Tasks'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'project.task', + 'view_id': False, + 'views': [(task_form_id, 'form'), (task_tree_id, 'tree'), (task_calendar_id, 'calendar')], + 'type': 'ir.actions.act_window', + 'res_id': base_calendar.base_calendar_id2real_id(id), + 'nodestroy': True + } + + return value + + def import_cal(self, cr, uid, data, data_id=None, context=None): todo_obj = self.pool.get('basic.calendar.todo') vals = todo_obj.import_cal(cr, uid, data, context=context) diff --git a/addons/project_caldav/project_caldav_view.xml b/addons/project_caldav/project_caldav_view.xml index 259d336c398..cfd27ce4240 100644 --- a/addons/project_caldav/project_caldav_view.xml +++ b/addons/project_caldav/project_caldav_view.xml @@ -13,7 +13,7 @@ <button string="Assign Task" name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d" icon="terp-partner" type="action" - context="{'model' : 'project.task'}" colspan="2"/> + context="{'model' : 'project.task', 'attendee_field':'attendee_ids'}" colspan="2"/> <field name="attendee_ids" colspan="4" nolabel="1" widget="one2many" mode="tree,form"> <tree string="Assignees details" editable="top"> @@ -70,7 +70,7 @@ <button string="Edit All" help="Edit all Ourrences of recurrent Task" attrs="{'invisible':[('rrule_type','in', ('none', False))]}" - name="open_meeting" icon="gtk-edit" + name="open_task" icon="gtk-edit" type="object" /> <button string="Exclude range" groups="base.group_extended" help="Add Exception Rule" diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py index 8a3aa3133f1..90bef42b452 100644 --- a/addons/project_gtd/project_gtd.py +++ b/addons/project_gtd/project_gtd.py @@ -109,7 +109,7 @@ class project_task(osv.osv): tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[])) search_extended ='''<newline/><group col="%d" expand="%d" string="%s">''' % (len(tt)+7,1,_('Getting Things Done')) search_extended += '''<filter domain="[('timebox_id','=', False)]" context="{'set_editable':True,'set_visible':True,'gtd_visible':True,'user_invisible':True}" icon="gtk-new" help="Undefined Timebox" string="%s"/>''' % (_('Inbox'),) - search_extended += '''<filter context="{'set_editable':True,'set_visible':True,'gtd_visible':True,'user_invisible':True}" icon="gtk-new" string="%s"/>''' % (_('GTD'),) + search_extended += '''<filter context="{'set_editable':True,'set_visible':True,'gtd_visible':True,'user_invisible':True}" icon="gtk-new" help="Getting things done" string="%s"/>''' % (_('GTD'),) search_extended += '''<separator orientation="vertical"/>''' for time in tt: if time.icon: diff --git a/addons/project_issue/__init__.py b/addons/project_issue/__init__.py index 5e8489ecafa..21efa34f6f4 100644 --- a/addons/project_issue/__init__.py +++ b/addons/project_issue/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/project_issue/__openerp__.py b/addons/project_issue/__openerp__.py index c776eeb1519..3ad0558cb71 100644 --- a/addons/project_issue/__openerp__.py +++ b/addons/project_issue/__openerp__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/project_issue/board_project_issue_view.xml b/addons/project_issue/board_project_issue_view.xml index 2351869e003..b236d0458ec 100644 --- a/addons/project_issue/board_project_issue_view.xml +++ b/addons/project_issue/board_project_issue_view.xml @@ -113,7 +113,7 @@ <field name="name">My Open Project issues</field> <field name="res_model">project.issue.report</field> <field name="view_type">form</field> - <field name="view_mode">tree,form</field> + <field name="view_mode">graph,tree,form,</field> <field name="domain">[('state','=','open'),'|',('assigned_to','=',uid),('user_id','=',uid)]</field> <field name="view_id" ref="view_my_open_project_issue_graph"/> </record> diff --git a/addons/project_issue_sheet/__init__.py b/addons/project_issue_sheet/__init__.py index 1b14bf46f8e..a5c0e48855e 100644 --- a/addons/project_issue_sheet/__init__.py +++ b/addons/project_issue_sheet/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/project_issue_sheet/__openerp__.py b/addons/project_issue_sheet/__openerp__.py index d867defc08f..51da95b52a1 100644 --- a/addons/project_issue_sheet/__openerp__.py +++ b/addons/project_issue_sheet/__openerp__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml index 79f11af4bbd..eaaafe5090a 100644 --- a/addons/project_long_term/project_long_term_view.xml +++ b/addons/project_long_term/project_long_term_view.xml @@ -257,8 +257,8 @@ <field name="arch" type="xml"> <search string="Project Phases"> <group colspan="4" col="20"> - <filter string="Draft" domain="[('state','=','draft')]" help="Draft Phases" icon="terp-document-new" default="1"/> - <filter string="In Progress" name="Progress" domain="[('state','=','open')]" help="Open Phases" icon="terp-camera_test"/> + <filter string="Current" domain="[('state','in',('open','draft'))]" name="current" help="Draft and In Progress Phases" icon="terp-check" default="1"/> + <filter string="In Progress" name="Progress" domain="[('state','=','open')]" help="In Progress Phases" icon="terp-camera_test"/> <filter string="Pending" domain="[('state','=','pending')]" help="Pending Phases" icon="terp-gtk-media-pause"/> <separator orientation="vertical"/> <field name="name"/> @@ -287,7 +287,7 @@ <field name="res_model">project.phase</field> <field name="view_type">form</field> <field name="view_mode">gantt,tree,form,calendar</field> - <field name="context">{'search_default_responsible_id':uid,'search_default_project':1}</field> + <field name="context">{"search_default_current": 1}</field> <field name="search_view_id" ref="view_project_phase_search"/> <field name="help">A project can be split into the different phases. For each phase, you can define your resources allocation, describe different tasks and link your phase to previous and next ones, add date constraints for the automated scheduling. Use the long term planning in order to planify your available human resources, convert your phases into a series of tasks when you start working on it.</field> </record> @@ -297,7 +297,7 @@ <field name="res_model">project.phase</field> <field name="view_type">form</field> <field name="view_mode">tree,form,calendar</field> - <field name="context">{'search_default_responsible_id':uid,'search_default_project':1}</field> + <field name="context">{"search_default_current": 1}</field> <field name="search_view_id" ref="view_project_phase_search"/> </record> diff --git a/addons/project_planning/project_planning.py b/addons/project_planning/project_planning.py index 759057fbaef..83c9cd6dff5 100644 --- a/addons/project_planning/project_planning.py +++ b/addons/project_planning/project_planning.py @@ -138,8 +138,8 @@ class report_account_analytic_planning(osv.osv): 'total_free': fields.function(_get_total_free, method=True, string='Total Free'), } _defaults = { - 'date_from': time.strftime('%Y-%m-01'), - 'date_to': (datetime.now()+relativedelta(months=1, day=1, days=-1)).strftime('%Y-%m-%d'), + 'date_from': lambda *a: time.strftime('%Y-%m-01'), + 'date_to': lambda *a: (datetime.now()+relativedelta(months=1, day=1, days=-1)).strftime('%Y-%m-%d'), 'user_id': lambda self, cr, uid, c: uid, 'state': 'draft', 'business_days': 20, @@ -434,7 +434,7 @@ class report_account_analytic_planning_account(osv.osv): SELECT id FROM report_account_analytic_planning_line WHERE planning_id = %s AND account_id=%s - )""", (line.planning_id.id,line.account_id.id )) + )""", (line.planning_id.id, line.account_id and line.account_id.id or None)) result[line.id] = cr.fetchall()[0][0] / div * div2 return result @@ -452,7 +452,7 @@ class report_account_analytic_planning_account(osv.osv): cr.execute(""" SELECT SUM(unit_amount/uom.factor) FROM account_analytic_line acc LEFT JOIN product_uom uom ON (uom.id = acc.product_uom_id) - WHERE acc.date>=%s and acc.date<=%s and acc.account_id=%s""", (line.planning_id.date_from, line.planning_id.date_to, line.account_id.id, )) + WHERE acc.date>=%s and acc.date<=%s and acc.account_id=%s""", (line.planning_id.date_from, line.planning_id.date_to, line.account_id and line.account_id.id or None)) res = cr.fetchall()[0][0] if res: result[line.id] = res * div2 @@ -526,9 +526,9 @@ class report_account_analytic_planning_stat(osv.osv): if line.user_id: cr.execute('''SELECT sum(acc.unit_amount/uom.factor) FROM account_analytic_line acc LEFT JOIN product_uom uom ON (uom.id = acc.product_uom_id) -WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.id, line.account_id.id, line.planning_id.date_from, line.planning_id.date_to)) +WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.id, line.account_id and line.account_id.id or None, line.planning_id.date_from, line.planning_id.date_to)) else: - cr.execute('SELECT sum(unit_amount) FROM account_analytic_line WHERE account_id=%s AND date>=%s AND date<=%s', (line.account_id.id, line.planning_id.date_from, line.planning_id.date_to)) + cr.execute('SELECT sum(unit_amount) FROM account_analytic_line WHERE account_id=%s AND date>=%s AND date<=%s', (line.account_id and line.account_id.id or None, line.planning_id.date_from, line.planning_id.date_to)) sum = cr.fetchone() if sum and sum[0]: @@ -563,7 +563,7 @@ WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.i project_id IN (select id from project_project where analytic_account_id=%s) AND date_end>=%s AND date_end<=%s''', ( - line.account_id.id, + line.account_id and line.account_id.id or None, line.planning_id.date_from, line.planning_id.date_to) ) diff --git a/addons/project_planning/project_planning_demo.xml b/addons/project_planning/project_planning_demo.xml index 1c12e5c53cf..34ecb58ab02 100644 --- a/addons/project_planning/project_planning_demo.xml +++ b/addons/project_planning/project_planning_demo.xml @@ -1,20 +1,58 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data noupdate="1"> - <record id="hr.dep_administration" model="hr.department"> - <field name="name">Administration</field> - <field name="parent_id" ref="hr.dep_management"/> - <field name="company_id" ref="base.main_company"/> - <field name="manager_id" ref="base.user_root"/> - <field name="member_ids" eval="[(6,0,[ref('base.user_demo')])]"/> - </record> + + <!-- Project Planning --> + <record id="project_plannning_1" model="report_account_analytic.planning"> - <field name="name">Project_Planning</field> + <field name="name">Project_Planning</field> <field name="business_days">20</field> - <field name="date_from">2010-01-01'</field> - <field name="date_to">2010-12-31</field> - <field name="state">draft</field> - <field name="member_ids" ref="base.user_demo"/> + <field name="date_from" eval="time.strftime('%Y-%m-01 10:00:00')"/> + <field name="date_to" eval="time.strftime('%Y-%m-30 15:23:00')"/> + <field name="state">open</field> + <field name="user_id" ref="project.res_users_project_manager"/> </record> + + + <record id="project_plannning_line1" model="report_account_analytic.planning.line"> + <field name="account_id" ref="account.analytic_trunk"/> + <field name="amount">16.0</field> + <field name="amount_unit" ref="product.uom_hour"/> + <field name="planning_id" ref="project_plannning_1"/> + <field name="user_id" ref="project.res_users_project_manager"/> + <field name="task_ids" eval="[(6,0,[ref('project.project_task_188')])]"/> + </record> + + + <record id="project_plannning_line2" model="report_account_analytic.planning.line"> + <field name="account_id" ref="account.analytic_trunk"/> + <field name="amount">24.0</field> + <field name="amount_unit" ref="product.uom_hour"/> + <field name="planning_id" ref="project_plannning_1"/> + <field name="user_id" ref="project.res_users_technical_leader"/> + <field name="task_ids" eval="[(6,0,[ref('project.project_task_192')])]"/> + </record> + + + <record id="project_plannning_line3" model="report_account_analytic.planning.line"> + <field name="account_id" ref="account.analytic_trunk"/> + <field name="amount">90.0</field> + <field name="amount_unit" ref="product.uom_hour"/> + <field name="planning_id" ref="project_plannning_1"/> + <field name="user_id" ref="project.res_users_developer"/> + <field name="task_ids" eval="[(6,0,[ref('project.project_task_11')])]"/> + </record> + + + <record id="project_plannning_line4" model="report_account_analytic.planning.line"> + <field name="account_id" ref="account.analytic_trunk"/> + <field name="amount">50.0</field> + <field name="amount_unit" ref="product.uom_hour"/> + <field name="planning_id" ref="project_plannning_1"/> + <field name="user_id" ref="project.res_users_tester"/> + <field name="task_ids" eval="[(6,0,[ref('project.project_task_13')])]"/> + </record> + + </data> </openerp> diff --git a/addons/project_planning/project_planning_view.xml b/addons/project_planning/project_planning_view.xml index 9abff817d17..3e67c8f5bb4 100644 --- a/addons/project_planning/project_planning_view.xml +++ b/addons/project_planning/project_planning_view.xml @@ -74,10 +74,9 @@ <field name="task_ids" /> <field name="note" /> <field name="amount_in_base_uom" invisible="1" sum="Total Planned (in Days)"/> - </tree> <form string="Planning Lines"> - <field name="user_id" domain="[('id','child_of',[parent.user_id])]"/> + <field name="user_id"/> <field name="account_id" groups="analytic.group_analytic_accounting"/> <field name="amount" /> <field name="amount_unit" /> diff --git a/addons/project_scrum/board_project_scrum_view.xml b/addons/project_scrum/board_project_scrum_view.xml index 2d146c94367..08acece9bbb 100644 --- a/addons/project_scrum/board_project_scrum_view.xml +++ b/addons/project_scrum/board_project_scrum_view.xml @@ -16,9 +16,9 @@ <field name="effective_hours" sum="Effective hours" widget="float_time"/> <field name="expected_hours" sum="Expected hours" widget="float_time"/> <field name="state"/> - <button type="object" string="Open" name="button_open" states="draft,pending" icon="gtk-jump-to"/> + <button type="object" string="Open" name="button_open" states="draft,pending" icon="gtk-ok"/> <button type="object" string="Pending" name="button_pending" states="open" icon="gtk-media-pause"/> - <button type="object" string="Close" name="button_close" states="open,pending" icon="gtk-jump-to"/> + <button type="object" string="Close" name="button_close" states="open,pending" icon="terp-dialog-close"/> <button type="object" string="Set to Draft" name="button_draft" states="cancel,done" icon="gtk-convert"/> <button name="%(project_scrum.report_scrum_sprint_burndown_chart)d" states="open,draft,close,cancel" string="Burndown Chart" type="action" icon="gtk-print"/> diff --git a/addons/project_scrum/project_scrum.py b/addons/project_scrum/project_scrum.py index 82395c3eb35..75f9cfd4a63 100644 --- a/addons/project_scrum/project_scrum.py +++ b/addons/project_scrum/project_scrum.py @@ -123,7 +123,7 @@ class project_scrum_sprint(osv.osv): } _defaults = { 'state': 'draft', - 'date_start' : time.strftime('%Y-%m-%d'), + 'date_start' : lambda *a: time.strftime('%Y-%m-%d'), } def copy(self, cr, uid, id, default=None, context=None): diff --git a/addons/project_scrum/project_scrum_demo.xml b/addons/project_scrum/project_scrum_demo.xml index 9dc97c351a3..76f2846c76f 100644 --- a/addons/project_scrum/project_scrum_demo.xml +++ b/addons/project_scrum/project_scrum_demo.xml @@ -154,7 +154,6 @@ <!-- Resource: project.product.backlog --> <record id="scrum_product_backlog_0" model="project.scrum.product.backlog"> - <field name="priority">3</field> <field name="name">Automatic migration system</field> <field name="expected_hours">6.0</field> <field name="note">This new system will enable you to migrate automatically from an old version of OpenERP to a new one. This system will migrate not only the OpenERP system but also the customers particularities. This happens without any kind of script or programming. It has been possible to carry out such a system thanks to the descriptive approach of OpenERP components. </field> @@ -163,7 +162,6 @@ <field name="project_id" ref="project.project_project_9"/> </record> <record id="scrum_product_backlog_1" model="project.scrum.product.backlog"> - <field name="priority">3</field> <field name="name">New accounting module</field> <field name="expected_hours">111.0</field> <field name="note">The accounting module of OpenERP (financial accounting and management accounting) is being reshaped. New functionalities will be added: intangible assets, a new way of presenting ledgers and bookings, new stock valuation calculation, and lots of predefined reports. </field> @@ -172,7 +170,6 @@ <field name="project_id" ref="project.project_project_9"/> </record> <record id="scrum_product_backlog_2" model="project.scrum.product.backlog"> - <field name="priority">3</field> <field name="name">Automated Plugin System to install/uninstall modules</field> <field name="expected_hours">4.0</field> <field name="note">We have to develop a plug-in system which will enable to install/remove modules. The basic version of OpenERP will include only the required minimum, and you will select the modules thanks to the plug-in manager. This allows you to limit your system to your real needs: quality management, localisations, project and service management, marketing campaigns, and so on... </field> @@ -271,7 +268,7 @@ <field name="project_id" ref="project.project_project_9"/> <field name="name">Review all English Terms</field> <field name="state">done</field> - <field eval="time.strftime('%Y-%m-%d')" name="date_close"/> + <field eval="time.strftime('%Y-%m-%d')" name="date_end"/> <field name="product_backlog_id" ref="scrum_product_backlog_3"/> </record> <record id="scrum_task_4" model="project.task"> @@ -280,7 +277,7 @@ <field name="project_id" ref="project.project_project_9"/> <field name="name">Review all french terms</field> <field name="state">done</field> - <field eval="time.strftime('%Y-%m-%d')" name="date_close"/> + <field eval="time.strftime('%Y-%m-%d')" name="date_end"/> <field name="product_backlog_id" ref="scrum_product_backlog_3"/> </record> <record id="scrum_task_5" model="project.task"> @@ -289,7 +286,7 @@ <field name="project_id" ref="project.project_project_9"/> <field name="name">Analytic Accounting features</field> <field name="state">done</field> - <field eval="time.strftime('%Y-%m-%d')" name="date_close"/> + <field eval="time.strftime('%Y-%m-%d')" name="date_end"/> <field name="product_backlog_id" ref="scrum_product_backlog_1"/> </record> <record id="scrum_task_6" model="project.task"> @@ -346,7 +343,7 @@ <field name="project_id" ref="project.project_project_9"/> <field name="name">Bugfix - memory leak</field> <field name="state">done</field> - <field eval="time.strftime('%Y-%m-%d')" name="date_close"/> + <field eval="time.strftime('%Y-%m-%d')" name="date_end"/> <field name="product_backlog_id" ref="scrum_product_backlog_4"/> </record> <record id="scrum_task_13" model="project.task"> diff --git a/addons/project_timesheet/report/task_report_view.xml b/addons/project_timesheet/report/task_report_view.xml index 379922f4838..87949d6812a 100644 --- a/addons/project_timesheet/report/task_report_view.xml +++ b/addons/project_timesheet/report/task_report_view.xml @@ -45,11 +45,25 @@ </search> </field> </record> + + <record id="view_task_hour_per_month_graph" model="ir.ui.view"> + <field name="name">report.timesheet.task.user.graph</field> + <field name="model">report.timesheet.task.user</field> + <field name="type">graph</field> + <field name="arch" type="xml"> + <graph string="Task Hours Per Month" type="bar"> + <field name="user_id"/> + <field name="task_hrs" operator="+"/> + <field name="timesheet_hrs" operator="+"/> + </graph> + </field> + </record> + <record id="action_report_timesheet_task_user" model="ir.actions.act_window"> <field name="name">Task Hours Per Month</field> <field name="res_model">report.timesheet.task.user</field> <field name="view_type">form</field> - <field name="view_mode">tree</field> + <field name="view_mode">tree,graph</field> <field name="context">{"search_default_user_id":uid}</field> <field name="search_view_id" ref="view_report_timesheet_task_user_search"/> </record> diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index c22ced3e159..206a14beab2 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/resource/resource_view.xml b/addons/resource/resource_view.xml index b8f3d14df56..2a20f101b0f 100644 --- a/addons/resource/resource_view.xml +++ b/addons/resource/resource_view.xml @@ -256,6 +256,7 @@ <field name="view_mode">tree,form,calendar</field> <field name="search_view_id" ref="view_resource_calendar_leaves_search"/> </record> - + <menuitem id="menu_resource_config" name="Resource" parent="base.menu_base_config" sequence="5" groups="base.group_extended"/> + <menuitem action="resource.action_resource_calendar_leave_tree" id="menu_view_resource_calendar_leaves_search" parent="menu_resource_config" sequence="1"/> </data> </openerp> diff --git a/addons/sale_layout/sale_layout.py b/addons/sale_layout/sale_layout.py index e5554aba07c..90192615f1a 100755 --- a/addons/sale_layout/sale_layout.py +++ b/addons/sale_layout/sale_layout.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/sale_mrp/sale_mrp.py b/addons/sale_mrp/sale_mrp.py index c11f62a1f03..2ae230ae4a8 100644 --- a/addons/sale_mrp/sale_mrp.py +++ b/addons/sale_mrp/sale_mrp.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/survey/report/__init__.py b/addons/survey/report/__init__.py index 710de5e7999..26fc1d46d63 100644 --- a/addons/survey/report/__init__.py +++ b/addons/survey/report/__init__.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/survey/report/survey_analysis_report.py b/addons/survey/report/survey_analysis_report.py index 0d866368bf2..6f6c30e1f1d 100644 --- a/addons/survey/report/survey_analysis_report.py +++ b/addons/survey/report/survey_analysis_report.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/survey/report/survey_browse_response.py b/addons/survey/report/survey_browse_response.py index 408a266d2cf..8e8c195aa59 100644 --- a/addons/survey/report/survey_browse_response.py +++ b/addons/survey/report/survey_browse_response.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/survey/report/survey_form.py b/addons/survey/report/survey_form.py index 1a623db4211..384a0b3ebab 100644 --- a/addons/survey/report/survey_form.py +++ b/addons/survey/report/survey_form.py @@ -6,16 +6,16 @@ # $Id$ # # This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# 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 General Public License for more details. +# GNU Affero General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## diff --git a/addons/survey/security/survey_security.xml b/addons/survey/security/survey_security.xml index 1506fdaec1b..598e3930f7f 100644 --- a/addons/survey/security/survey_security.xml +++ b/addons/survey/security/survey_security.xml @@ -14,6 +14,10 @@ <record model="res.groups" id="group_survey_user"> <field name="name">Survey / User</field> </record> + + <record id="base.user_demo" model="res.users"> + <field name="groups_id" eval="[(4,ref('group_survey_user'))]"/> + </record> </data> </openerp> diff --git a/addons/survey/wizard/survey_answer.py b/addons/survey/wizard/survey_answer.py index f803ab88803..978f66c9d75 100644 --- a/addons/survey/wizard/survey_answer.py +++ b/addons/survey/wizard/survey_answer.py @@ -457,7 +457,8 @@ class survey_question_wiz(osv.osv_memory): try: service = netsvc.LocalService(report_name); (result, format) = service.create(cr, uid, res_ids, {}, context) - fp = open(addons.get_module_resource('survey', 'report') + file_name + '.pdf', 'wb+'); + ret_file_name = addons.get_module_resource('survey', 'report') + file_name + '.pdf' + fp = open(ret_file_name, 'wb+'); fp.write(result); fp.close(); diff --git a/addons/thunderbird/partner/partner.py b/addons/thunderbird/partner/partner.py index 825c4f6fc8c..e6f5209917e 100644 --- a/addons/thunderbird/partner/partner.py +++ b/addons/thunderbird/partner/partner.py @@ -19,12 +19,8 @@ #
##############################################################################
-import time
-import ir
-from osv import osv,fields
+from osv import osv
import base64
-import netsvc
-from tools.translate import _
import email
import tools
import binascii
@@ -159,6 +155,7 @@ class thunderbird_partner(osv.osv_memory): msg_ids = []
res = {}
res_ids = []
+ obj_list= ['crm.lead','project.issue','hr.applicant','res.partner']
for ref_id in ref_ids:
msg_new = dictcreate.get('message')
ref = ref_id.split(',')
@@ -168,6 +165,31 @@ class thunderbird_partner(osv.osv_memory): msg_ids = msg_pool.search(cr, uid, [('message_id','=',message_id),('res_id','=',res_id),('model','=',model)])
if msg_ids and len(msg_ids):
continue
+ if model not in obj_list:
+ res={}
+ obj_attch = self.pool.get('ir.attachment')
+ ls = ['*', '/', '\\', '<', '>', ':', '?', '"', '|', '\t', '\n',':','~']
+ sub = msg.get('subject','NO-SUBJECT').replace(' ','')
+ if sub.strip() == '':
+ sub = 'NO SBUJECT'
+ fn = sub
+ for c in ls:
+ fn = fn.replace(c,'')
+ if len(fn) > 64:
+ l = 64 - len(fn)
+ f = fn.split('-')
+ fn = '-'.join(f[1:])
+ if len(fn) > 64:
+ l = 64 - len(fn)
+ f = fn.split('.')
+ fn = f[0][0:l] + '.' + f[-1]
+ fn = fn[:-4]+'.txt'
+ res['res_model'] = model
+ res['name'] = msg.get('subject','NO-SUBJECT')
+ res['datas_fname'] = fn
+ res['datas'] = base64.b64encode(msg.get('body'))
+ res['res_id'] = res_id
+ obj_attch.create(cr, uid, res)
server_tools_pool.history_message(cr, uid, model, res_id, msg_new)
res_ids.append(res_id)
return len(res_ids)
@@ -299,11 +321,8 @@ class thunderbird_partner(osv.osv_memory): name_get.append('error')
name_get.append(er_val)
return name_get
-
-
-
def list_alldocument(self,cr,user,vals):
- obj_list= [('crm.lead','Lead'),('project.issue','Project Issue'), ('hr.applicant','HR Recruitment')]
+ obj_list= [('crm.lead','CRM Lead'),('project.issue','Project Issue'), ('hr.applicant','HR Applicant')]
object=[]
model_obj = self.pool.get('ir.model')
for obj in obj_list:
diff --git a/addons/thunderbird/plugin/openerp_plugin.xpi b/addons/thunderbird/plugin/openerp_plugin.xpi Binary files differindex abcc254c869..943fba35329 100644 --- a/addons/thunderbird/plugin/openerp_plugin.xpi +++ b/addons/thunderbird/plugin/openerp_plugin.xpi diff --git a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar Binary files differindex 5666b96546e..92bb3602292 100644 --- a/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar +++ b/addons/thunderbird/plugin/openerp_plugin/chrome/openerp_plugin.jar |
