diff --git a/addons/account/__terp__.py b/addons/account/__terp__.py index d6465027059..c7f1dc9e149 100644 --- a/addons/account/__terp__.py +++ b/addons/account/__terp__.py @@ -21,7 +21,7 @@ { - "name" : "Accounting and financial management", + "name" : "Accounting and Financial Management", "version" : "1.1", "depends" : ["product", "base", "process"], "author" : "Tiny", diff --git a/addons/account/invoice.py b/addons/account/invoice.py index 87874c0a1b2..c2024c86eb3 100644 --- a/addons/account/invoice.py +++ b/addons/account/invoice.py @@ -29,17 +29,17 @@ from mx.DateTime import RelativeDateTime from tools import config from tools.translate import _ -class fiscalyear_seq(osv.osv): - _name = "fiscalyear.seq" - _description = "Maintains Invoice sequences with Fiscal Year" - _rec_name = 'fiscalyear_id' - _columns = { - 'journal_id': fields.many2one('account.journal', 'Journal'), - 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year',required=True), - 'sequence_id':fields.many2one('ir.sequence', 'Sequence',required=True), - } - -fiscalyear_seq() +#class fiscalyear_seq(osv.osv): +# _name = "fiscalyear.seq" +# _description = "Maintains Invoice sequences with Fiscal Year" +# _rec_name = 'fiscalyear_id' +# _columns = { +# 'journal_id': fields.many2one('account.journal', 'Journal'), +# 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscal Year',required=True), +# 'sequence_id':fields.many2one('ir.sequence', 'Sequence',required=True), +# } +# +#fiscalyear_seq() class account_invoice(osv.osv): def _amount_all(self, cr, uid, ids, name, args, context=None): diff --git a/addons/account/project/project.py b/addons/account/project/project.py index f6c58ee3ea2..e39e5b00d77 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -41,7 +41,7 @@ class account_analytic_account(osv.osv): where_date += " AND l.date >= '" + context['from_date'] + "'" if context.get('to_date',False): where_date += " AND l.date <= '" + context['to_date'] + "'" - + cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r = dict(cr.fetchall()) for i in ids: @@ -51,13 +51,13 @@ class account_analytic_account(osv.osv): def _debit_calc(self, cr, uid, ids, name, arg, context={}): acc_set = ",".join(map(str, ids)) - + where_date = '' if context.get('from_date',False): where_date += " AND l.date >= '" + context['from_date'] + "'" if context.get('to_date',False): where_date += " AND l.date <= '" + context['to_date'] + "'" - + cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r= dict(cr.fetchall()) for i in ids: @@ -68,21 +68,21 @@ class account_analytic_account(osv.osv): res = {} ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) acc_set = ",".join(map(str, ids2)) - + for i in ids: res.setdefault(i,0.0) - + if not acc_set: return res - + where_date = '' if context.get('from_date',False): where_date += " AND l.date >= '" + context['from_date'] + "'" if context.get('to_date',False): where_date += " AND l.date <= '" + context['to_date'] + "'" - + cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) - + for account_id, sum in cr.fetchall(): res[account_id] = sum @@ -115,19 +115,19 @@ class account_analytic_account(osv.osv): res = {} ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) acc_set = ",".join(map(str, ids2)) - + for i in ids: res.setdefault(i,0.0) - + if not acc_set: return res - + where_date = '' if context.get('from_date',False): where_date += " AND l.date >= '" + context['from_date'] + "'" if context.get('to_date',False): where_date += " AND l.date <= '" + context['to_date'] + "'" - + cr.execute('SELECT a.id, COALESCE(SUM(l.unit_amount), 0) \ FROM account_analytic_account a \ LEFT JOIN account_analytic_line l ON (a.id = l.account_id ' + where_date + ') \ @@ -168,10 +168,10 @@ class account_analytic_account(osv.osv): return result _columns = { - 'name' : fields.char('Account Name', size=64, required=True), + 'name' : fields.char('Account Name', size=128, required=True), 'complete_name': fields.function(_complete_name_calc, method=True, type='char', string='Full Account Name'), 'code' : fields.char('Account Code', size=24), - 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."), +# 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."), 'type': fields.selection([('view','View'), ('normal','Normal')], 'Account Type'), 'description' : fields.text('Description'), 'parent_id': fields.many2one('account.analytic.account', 'Parent Analytic Account', select=2), @@ -189,11 +189,13 @@ class account_analytic_account(osv.osv): 'date': fields.date('Date End'), 'company_id': fields.many2one('res.company', 'Company', required=True), 'company_currency_id': fields.function(_get_company_currency, method=True, type='many2one', relation='res.currency', string='Currency'), - 'state': fields.selection([('draft','Draft'), ('open','Open'), ('pending','Pending'), ('close','Close'),], 'State', required=True, + 'state': fields.selection([('draft','Draft'),('open','Open'), ('pending','Pending'),('cancelled', 'Cancelled'),('close','Close'),('template', 'Template')], 'State', required=True,readonly=True, help='* When an account is created its in \'Draft\' state.\ \n* If any associated partner is there, it can be in \'Open\' state.\ \n* If any pending balance is there it can be in \'Pending\'. \ - \n* And finally when all the transactions are over, it can be in \'Close\' state.'), + \n* And finally when all the transactions are over, it can be in \'Close\' state. \ + \n* The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\ + \n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'), } def _default_company(self, cr, uid, context={}): @@ -202,13 +204,14 @@ class account_analytic_account(osv.osv): return user.company_id.id return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0] _defaults = { - 'active' : lambda *a : True, +# 'active' : lambda *a : True, 'type' : lambda *a : 'normal', 'company_id': _default_company, - 'state' : lambda *a : 'draft', + 'state' : lambda *a : 'open', 'user_id' : lambda self,cr,uid,ctx : uid, 'partner_id': lambda self,cr, uid, ctx: ctx.get('partner_id', False), 'contact_id': lambda self,cr, uid, ctx: ctx.get('contact_id', False), + 'date_start': lambda *a: time.strftime('%Y-%m-%d') } def check_recursion(self, cr, uid, ids, parent=None): diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index 7ffb93fb73b..1123b122eaf 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -76,7 +76,7 @@ - + diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv index 3d135317b71..bb7ffbae946 100644 --- a/addons/account/security/ir.model.access.csv +++ b/addons/account/security/ir.model.access.csv @@ -82,7 +82,6 @@ "access_account_fiscal_position","account.fiscal.position all","model_account_fiscal_position","base.group_user",1,0,0,0 "access_account_fiscal_position_tax","account.fiscal.position.tax all","model_account_fiscal_position_tax","base.group_user",1,0,0,0 "access_account_fiscal_position_account","account.fiscal.position all","model_account_fiscal_position_account","base.group_user",1,0,0,0 -"access_fiscalyear_seq","fiscalyear.seq","model_fiscalyear_seq","account.group_account_invoice",1,1,1,1 "access_account_fiscal_position_template","account.fiscal.position.template","model_account_fiscal_position_template","account.group_account_manager",1,1,1,1 "access_account_fiscal_position_tax_template","account.fiscal.position.tax.template","model_account_fiscal_position_tax_template","account.group_account_manager",1,1,1,1 "access_account_fiscal_position_account_template","account.fiscal.position.account.template","model_account_fiscal_position_account_template","account.group_account_manager",1,1,1,1 diff --git a/addons/auction/i18n/bg.po b/addons/auction/i18n/bg.po index 439292d57b4..62643ecb9e2 100644 --- a/addons/auction/i18n/bg.po +++ b/addons/auction/i18n/bg.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2009-02-03 11:15+0000\n" -"Last-Translator: Fabien (Open ERP) \n" +"PO-Revision-Date: 2010-01-19 09:48+0000\n" +"Last-Translator: lem0na \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2009-12-16 05:18+0000\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: auction @@ -44,19 +44,19 @@ msgstr "продавач" #. module: auction #: constraint:ir.actions.act_window:0 msgid "Invalid model name in the action definition." -msgstr "" +msgstr "Невалидно име на модел при задаване на действие" #. module: auction #: selection:auction.lots.send.aie,date_ask,numerotation:0 #: selection:auction.lots.send.aie,init,numerotation:0 msgid "Provisoire" -msgstr "" +msgstr "Временен" #. module: auction #: selection:auction.lots.send.aie,date_ask,numerotation:0 #: selection:auction.lots.send.aie,init,numerotation:0 msgid "Definitive (ordre catalogue)" -msgstr "" +msgstr "Зададен (за каталог)" #. module: auction #: model:ir.ui.menu,name:auction.menu_report_auction_object_date_tree1_my @@ -71,7 +71,7 @@ msgstr "История на партида" #. module: auction #: field:report.seller.auction,avg_estimation:0 msgid "Avg estimation" -msgstr "" +msgstr "Усреднена оценка" #. module: auction #: field:report.auction.object.date,obj_num:0 diff --git a/addons/auction/i18n/pt_BR.po b/addons/auction/i18n/pt_BR.po index 67206636571..af1925e9ff4 100644 --- a/addons/auction/i18n/pt_BR.po +++ b/addons/auction/i18n/pt_BR.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2009-11-17 09:09+0000\n" -"Last-Translator: Fabien (Open ERP) \n" +"PO-Revision-Date: 2010-01-18 23:06+0000\n" +"Last-Translator: Holverat \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2009-12-16 05:19+0000\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: auction @@ -50,7 +50,7 @@ msgstr "" #: selection:auction.lots.send.aie,date_ask,numerotation:0 #: selection:auction.lots.send.aie,init,numerotation:0 msgid "Provisoire" -msgstr "" +msgstr "Provisório" #. module: auction #: selection:auction.lots.send.aie,date_ask,numerotation:0 diff --git a/addons/audittrail/i18n/pt_BR.po b/addons/audittrail/i18n/pt_BR.po index ffe8c1787c2..773cf8b9054 100644 --- a/addons/audittrail/i18n/pt_BR.po +++ b/addons/audittrail/i18n/pt_BR.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2009-09-08 13:21+0000\n" -"Last-Translator: Pedro_Maschio \n" +"PO-Revision-Date: 2010-01-20 01:10+0000\n" +"Last-Translator: pedrobom \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2009-12-16 05:24+0000\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: audittrail @@ -32,32 +32,32 @@ msgstr "" #. module: audittrail #: field:audittrail.log.line,log_id:0 msgid "Log" -msgstr "" +msgstr "Registro (log)" #. module: audittrail #: selection:audittrail.rule,state:0 msgid "Subscribed" -msgstr "" +msgstr "Inscrito" #. module: audittrail #: view:audittrail.log:0 msgid "Old Value : " -msgstr "" +msgstr "Valor Anterior : " #. module: audittrail #: selection:audittrail.log,method:0 msgid "Create" -msgstr "" +msgstr "Criar" #. module: audittrail #: wizard_view:audittrail.view.log,init:0 msgid "Audit Logs" -msgstr "" +msgstr "Logs de auditoria" #. module: audittrail #: field:audittrail.rule,state:0 msgid "State" -msgstr "" +msgstr "Status" #. module: audittrail #: selection:audittrail.rule,state:0 @@ -67,12 +67,12 @@ msgstr "" #. module: audittrail #: field:audittrail.log.line,old_value:0 msgid "Old Value" -msgstr "" +msgstr "Valor Anterior" #. module: audittrail #: constraint:ir.actions.act_window:0 msgid "Invalid model name in the action definition." -msgstr "" +msgstr "Nome de modelo inválido na definição da ação." #. module: audittrail #: model:ir.actions.wizard,name:audittrail.wizard_audittrail_log @@ -87,7 +87,7 @@ msgstr "" #. module: audittrail #: field:audittrail.log,method:0 msgid "Method" -msgstr "" +msgstr "Método" #. module: audittrail #: wizard_field:audittrail.view.log,init,from:0 @@ -97,17 +97,17 @@ msgstr "" #. module: audittrail #: field:audittrail.log.line,log:0 msgid "Log ID" -msgstr "" +msgstr "Log ID" #. module: audittrail #: field:audittrail.log,res_id:0 msgid "Resource Id" -msgstr "" +msgstr "ID Recurso" #. module: audittrail #: selection:audittrail.log,method:0 msgid "Write" -msgstr "" +msgstr "Escrever" #. module: audittrail #: model:ir.ui.menu,name:audittrail.menu_action_audittrail @@ -117,23 +117,23 @@ msgstr "" #. module: audittrail #: view:audittrail.log:0 msgid "Log Lines" -msgstr "" +msgstr "Linhas do Log" #. module: audittrail #: view:audittrail.rule:0 msgid "Subscribe" -msgstr "" +msgstr "Assinar" #. module: audittrail #: selection:audittrail.log,method:0 msgid "Read" -msgstr "" +msgstr "Ler" #. module: audittrail #: field:audittrail.log,object_id:0 #: field:audittrail.rule,object_id:0 msgid "Object" -msgstr "" +msgstr "Objeto" #. module: audittrail #: view:audittrail.rule:0 @@ -162,12 +162,12 @@ msgstr "" #. module: audittrail #: field:audittrail.log,timestamp:0 msgid "Date" -msgstr "" +msgstr "Data" #. module: audittrail #: field:audittrail.log,user_id:0 msgid "User" -msgstr "" +msgstr "Usuário" #. module: audittrail #: view:audittrail.log:0 @@ -182,92 +182,92 @@ msgstr "Invalido XML para Arquitetura da View" #. module: audittrail #: field:audittrail.log,name:0 msgid "Name" -msgstr "" +msgstr "Nome" #. module: audittrail #: field:audittrail.log,line_ids:0 msgid "Log lines" -msgstr "" +msgstr "Linhas de Log" #. module: audittrail #: model:ir.ui.menu,name:audittrail.menu_action_audittrail_rule_tree_sub msgid "Subscribed Rules" -msgstr "" +msgstr "Regras Inscritas" #. module: audittrail #: field:audittrail.log.line,field_id:0 msgid "Fields" -msgstr "" +msgstr "Campos" #. module: audittrail #: view:audittrail.rule:0 msgid "AuditTrail Rules" -msgstr "" +msgstr "Regras de Auditoria" #. module: audittrail #: model:ir.model,name:audittrail.model_audittrail_rule msgid "audittrail.rule" -msgstr "" +msgstr "audittrail.rule" #. module: audittrail #: view:audittrail.rule:0 msgid "UnSubscribe" -msgstr "" +msgstr "Remover Inscrição" #. module: audittrail #: field:audittrail.rule,log_write:0 msgid "Log writes" -msgstr "" +msgstr "Escritas de Log" #. module: audittrail #: model:ir.model,name:audittrail.model_audittrail_log msgid "audittrail.log" -msgstr "" +msgstr "audittrail.log" #. module: audittrail #: field:audittrail.log.line,field_description:0 msgid "Field Description" -msgstr "" +msgstr "Descrição do Campo" #. module: audittrail #: selection:audittrail.log,method:0 msgid "Delete" -msgstr "" +msgstr "Apagar" #. module: audittrail #: wizard_button:audittrail.view.log,init,open:0 msgid "Open Logs" -msgstr "" +msgstr "Abrir Logs" #. module: audittrail #: field:audittrail.log.line,new_value_text:0 msgid "New value Text" -msgstr "" +msgstr "Texto do novo valor" #. module: audittrail #: field:audittrail.rule,name:0 msgid "Rule Name" -msgstr "" +msgstr "Nome da Regra" #. module: audittrail #: field:audittrail.rule,log_read:0 msgid "Log reads" -msgstr "" +msgstr "Leituras de Log" #. module: audittrail #: model:ir.ui.menu,name:audittrail.menu_action_audittrail_log_tree msgid "Logs" -msgstr "" +msgstr "Logs" #. module: audittrail #: field:audittrail.log.line,new_value:0 msgid "New Value" -msgstr "" +msgstr "Novo Valor" #. module: audittrail #: model:ir.ui.menu,name:audittrail.menu_action_log_tree2 msgid "View Logs" -msgstr "" +msgstr "Ver Logs" #. module: audittrail #: field:audittrail.rule,log_create:0 @@ -277,7 +277,7 @@ msgstr "" #. module: audittrail #: view:audittrail.log:0 msgid "AuditTrail Logs" -msgstr "" +msgstr "Logs de Auditoria" #. module: audittrail #: model:ir.ui.menu,name:audittrail.menu_action_audittrail_rule_tree @@ -287,22 +287,22 @@ msgstr "Regras" #. module: audittrail #: view:audittrail.log:0 msgid "New Value : " -msgstr "" +msgstr "Novo Valor: " #. module: audittrail #: field:audittrail.rule,user_id:0 msgid "Users" -msgstr "" +msgstr "Usuários" #. module: audittrail #: field:audittrail.log.line,old_value_text:0 msgid "Old value Text" -msgstr "" +msgstr "Texto do Valor Antigo" #. module: audittrail #: wizard_button:audittrail.view.log,init,end:0 msgid "Cancel" -msgstr "" +msgstr "Cancelar" #. module: audittrail #: field:audittrail.rule,log_unlink:0 diff --git a/addons/base_contact/base_contact_view.xml b/addons/base_contact/base_contact_view.xml index f8b50233877..db7ea54314e 100644 --- a/addons/base_contact/base_contact_view.xml +++ b/addons/base_contact/base_contact_view.xml @@ -312,6 +312,7 @@ + - - res.partner.address.select - res.partner.address - search - - - - - - + + res.partner.address.select + res.partner.address + search + + + + + + diff --git a/addons/base_module_quality/wizard/quality_save_report.py b/addons/base_module_quality/wizard/quality_save_report.py index 1debe21289d..853698dee1f 100644 --- a/addons/base_module_quality/wizard/quality_save_report.py +++ b/addons/base_module_quality/wizard/quality_save_report.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -25,6 +25,7 @@ import cStringIO import wizard from osv import osv import pooler +from tools.translate import _ form_rep = '''
@@ -35,7 +36,7 @@ form_rep = ''' fields_rep = { - 'name': {'string': 'File name', 'type': 'char', 'required': True, 'help': 'Save report as .html format'}, + 'name': {'string': 'File name', 'type': 'char', 'required': True, 'help': 'Save report as .html format', 'size':64}, 'module_file': {'string': 'Save report', 'type': 'binary', 'required': True}, } diff --git a/addons/board_crm_configuration/__terp__.py b/addons/board_crm_configuration/__terp__.py index 3c303ee2d1c..2d67fdc0174 100644 --- a/addons/board_crm_configuration/__terp__.py +++ b/addons/board_crm_configuration/__terp__.py @@ -37,7 +37,7 @@ This module implements a dashboard for CRM that includes: 'depends': ['board', 'crm', 'report_crm'], 'update_xml': ['board_crm_statistical_view.xml', 'board_crm_view.xml'], 'demo_xml': ['board_crm_demo.xml'], - 'installable': True, + 'installable': False, 'active': False, 'certificate': '0071599098909', } diff --git a/addons/caldav/__init__.py b/addons/caldav/__init__.py index e658ddcda72..2b6241a8f9d 100644 --- a/addons/caldav/__init__.py +++ b/addons/caldav/__init__.py @@ -21,5 +21,6 @@ import calendar import common +import wizard # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/caldav/__terp__.py b/addons/caldav/__terp__.py index a9f2b5befca..694b0f4365d 100644 --- a/addons/caldav/__terp__.py +++ b/addons/caldav/__terp__.py @@ -43,7 +43,8 @@ "demo_xml" : [], "update_xml" : [ 'security/ir.model.access.csv', - 'caldav_view.xml' + 'caldav_view.xml', + 'caldav_wizard.xml', ], "installable" : True, "active" : False, diff --git a/addons/caldav/caldav_data.xml b/addons/caldav/caldav_data.xml index 2b942d3b9ff..2043dd3e6e4 100644 --- a/addons/caldav/caldav_data.xml +++ b/addons/caldav/caldav_data.xml @@ -76,7 +76,7 @@ 3 hours before - + hours @@ -86,7 +86,7 @@ 4 hours before - + hours @@ -96,7 +96,7 @@ 5 hours before - + hours @@ -106,7 +106,7 @@ 18 hours before - + hours @@ -115,9 +115,9 @@ - - + + Run Event Reminder diff --git a/addons/caldav/caldav_wizard.xml b/addons/caldav/caldav_wizard.xml new file mode 100644 index 00000000000..62a035889e3 --- /dev/null +++ b/addons/caldav/caldav_wizard.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py index 4371badf1ac..c746967692c 100644 --- a/addons/caldav/calendar.py +++ b/addons/caldav/calendar.py @@ -42,7 +42,7 @@ def map_data(cr, uid, obj): if field_type == 'selection': if not map_val: continue - mapping =obj.__attribute__[map_dict].get('mapping', False) + mapping = obj.__attribute__[map_dict].get('mapping', False) if mapping: map_val = mapping[map_val.lower()] else: @@ -97,12 +97,12 @@ class CalDAV(object): val = self.__attribute__.get(name).get(type, None) valtype = self.__attribute__.get(name).get('type', None) if type == 'value': - if valtype and valtype=='datetime' and val: + if valtype and valtype == 'datetime' and val: if isinstance(val, list): val = ','.join(map(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'), val)) else: val = val.strftime('%Y-%m-%d %H:%M:%S') - if valtype and valtype=='integer' and val: + if valtype and valtype == 'integer' and val: val = int(val) return val else: @@ -122,11 +122,21 @@ class CalDAV(object): map_field = self.ical_get(field, 'field') map_type = self.ical_get(field, 'type') if map_field in data.keys(): - if field == 'uid' : + if field == 'uid': model = context.get('model', None) if not model: continue uidval = common.openobjectid2uid(cr, data[map_field], model) + cr.execute('select id from %s where recurrent_uid=%s' + % (model.replace('.', '_'), data[map_field])) + r_ids = map(lambda x: x[0], cr.fetchall()) + if r_ids: + rdata = self.pool.get(model).read(cr, uid, r_ids) + rcal = self.export_ical(cr, uid, rdata, context=context) + for revents in rcal.contents['vevent']: + ical.contents['vevent'].append(revents) + if data.get('recurrent_uid', None): + uidval = common.openobjectid2uid(cr, data['recurrent_uid'], model) vevent.add('uid').value = uidval elif field == 'attendee' and data[map_field]: attendee_obj = self.pool.get('basic.calendar.attendee') @@ -145,7 +155,7 @@ class CalDAV(object): elif map_type == "timedelta": vevent.add(field).value = timedelta(hours=data[map_field]) elif map_type == "many2one": - vevent.add(field).value = [data.get(map_field)[1]] + vevent.add(field).value = [data.get(map_field)[1]] if self.__attribute__.get(field).has_key('mapping'): for key1, val1 in self.ical_get(field, 'mapping').items(): if val1 == data[map_field]: @@ -236,7 +246,7 @@ class Event(CalDAV, osv.osv_memory): 'duration': None, # Use: O-1, Type: DURATION, Specifies a positive duration of time. 'dtend': None, # Use: O-1, Type: DATE-TIME, Specifies the date and time that a calendar component ends. } - def export_ical(self, cr, uid, datas, context={}): + def export_ical(self, cr, uid, datas, vobj='vevent', context={}): return super(Event, self).export_ical(cr, uid, datas, 'vevent', context=context) Event() @@ -279,7 +289,7 @@ class ToDo(CalDAV, osv.osv_memory): 'rrule': None, } - def export_ical(self, cr, uid, datas, context={}): + def export_ical(self, cr, uid, datas, vobj='vevent', context={}): return super(ToDo, self).export_ical(cr, uid, datas, 'vtodo', context=context) ToDo() @@ -367,15 +377,15 @@ class Alarm(CalDAV, osv.osv_memory): related = 'before' if not seconds: duration = abs(days) - related = days>0 and 'after' or 'before' + related = days > 0 and 'after' or 'before' elif (abs(diff) / 3600) == 0: duration = abs(diff / 60) interval = 'minutes' - related = days>=0 and 'after' or 'before' + related = days >= 0 and 'after' or 'before' else: duration = abs(diff / 3600) interval = 'hours' - related = days>=0 and 'after' or 'before' + related = days >= 0 and 'after' or 'before' self.ical_set('trigger_interval', interval, 'value') self.ical_set('trigger_duration', duration, 'value') self.ical_set('trigger_occurs', related.lower(), 'value') @@ -429,7 +439,7 @@ class Attendee(CalDAV, osv.osv_memory): attendee_add.params[a_key] = [str(attendee[a_val['field']])] if a_val['field'] == 'cn': cn_val = [str(attendee[a_val['field']])] - attendee_add.params['CN']= cn_val + attendee_add.params['CN'] = cn_val return vevent Attendee() diff --git a/addons/caldav/common.py b/addons/caldav/common.py index 77187c91419..d82cc369f91 100644 --- a/addons/caldav/common.py +++ b/addons/caldav/common.py @@ -21,9 +21,12 @@ from datetime import datetime, timedelta +from datetime import datetime, timedelta +from dateutil import parser from osv import fields, osv from service import web_services from tools.translate import _ +import base64 import re import time @@ -40,7 +43,9 @@ def caldav_id2real_id(caldav_id=None, with_date=False): if with_date: real_date = time.strftime("%Y-%m-%d %H:%M:%S", \ time.strptime(res[1], "%Y%m%d%H%M%S")) - return (int(real_id), real_date) + start = datetime.strptime(real_date, "%Y-%m-%d %H:%M:%S") + end = start + timedelta(hours=with_date) + return (int(real_id), real_date, end.strftime("%Y-%m-%d %H:%M:%S")) return int(real_id) return caldav_id and int(caldav_id) or caldav_id @@ -48,22 +53,29 @@ def real_id2caldav_id(real_id, recurrent_date): if real_id and recurrent_date: recurrent_date = time.strftime("%Y%m%d%H%M%S", \ time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S")) - return '%d-%s'%(real_id, recurrent_date) + return '%d-%s' % (real_id, recurrent_date) return real_id -def uid2openobjectid(cr, uidval, oomodel): +def uid2openobjectid(cr, uidval, oomodel, rdate): __rege = re.compile(r'OpenObject-([\w|\.]+)_([0-9]+)@(\w+)$') wematch = __rege.match(uidval.encode('utf8')) if not wematch: - return False + return (False, None) else: model, id, dbname = wematch.groups() if (not model == oomodel) or (not dbname == cr.dbname): - return False - cr.execute('select distinct(id) from %s' % model.replace('.', '_')) + return (False, None) + qry = 'select distinct(id) from %s' % model.replace('.', '_') + if rdate: + qry += " where recurrent_id='%s'" % (rdate) + cr.execute(qry) + r_id = cr.fetchone() + if r_id: + return (id, r_id[0]) + cr.execute(qry) ids = map(lambda x: str(x[0]), cr.fetchall()) if id in ids: - return id + return (id, None) return False def openobjectid2uid(cr, uidval, oomodel): @@ -214,8 +226,8 @@ request was delegated to"), 'partner_address_id': fields.many2one('res.partner.address', 'Contact'), 'partner_id':fields.related('partner_address_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'), 'email': fields.char('Email', size=124), - 'event_date' : fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'), - 'event_end_date' : fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'), + 'event_date': fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'), + 'event_end_date': fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'), 'ref': fields.reference('Document Ref', selection=_links_get, size=128), 'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"), } @@ -311,8 +323,8 @@ are both optional, but if one occurs, so MUST the other"""), alarm_ids = alarm_obj.search(cr, uid, [('model_id', '=', model_id), ('res_id', '=', datas.id)]) if alarm_ids and len(alarm_ids): alarm_obj.unlink(cr, uid, alarm_ids) - cr.execute('Update crm_meeting set caldav_alarm_id=NULL, \ - alarm_id=NULL where id=%s' % (datas.id)) + cr.execute('Update %s set caldav_alarm_id=NULL, \ + alarm_id=NULL where id=%s' % (self._table, datas.id)) cr.commit() return True @@ -349,12 +361,12 @@ or contains the text to be used for display"""), 'attach': fields.binary('Attachment', help="""* Points to a sound resource, which is rendered when the alarm is triggered for audio, * File which is intended to be sent as message attachments for email, * Points to a procedure resource, which is invoked when the alarm is triggered for procedure."""), - 'res_id' : fields.integer('Resource ID'), + 'res_id': fields.integer('Resource ID'), 'model_id': fields.many2one('ir.model', 'Model'), 'user_id': fields.many2one('res.users', 'Owner'), - 'event_date' : fields.datetime('Event Date'), - 'event_end_date' : fields.datetime('Event End Date'), - 'trigger_date' : fields.datetime('Trigger Date', readonly="True"), + 'event_date': fields.datetime('Event Date'), + 'event_end_date': fields.datetime('Event End Date'), + 'trigger_date': fields.datetime('Trigger Date', readonly="True"), 'state':fields.selection([ ('draft', 'Draft'), ('run', 'Run'), @@ -365,7 +377,7 @@ or contains the text to be used for display"""), _defaults = { 'action': lambda *x: 'email', - 'state' : lambda *x: 'run', + 'state': lambda *x: 'run', } def create(self, cr, uid, vals, context={}): @@ -404,7 +416,7 @@ or contains the text to be used for display"""), 'act_to': alarm.user_id.id, 'body': alarm.description, 'trigger_date': alarm.trigger_date, - 'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id) + 'ref_doc1': '%s,%s' % (alarm.model_id.model, alarm.res_id) } request_id = request_obj.create(cr, uid, value) request_ids = [request_id] @@ -415,17 +427,17 @@ or contains the text to be used for display"""), request_obj.request_send(cr, uid, request_ids) if alarm.action == 'email': - sub = '[Openobject Remainder] %s' %(alarm.name) + sub = '[Openobject Remainder] %s' % (alarm.name) body = """ - Name : %s - Date : %s - Description : %s + Name: %s + Date: %s + Description: %s - From : + From: %s %s - """ %(alarm.name, alarm.trigger_date, alarm.description, \ + """ % (alarm.name, alarm.trigger_date, alarm.description, \ alarm.user_id.name, alarm.user_id.sign) mail_to = [alarm.user_id.address_id.email] for att in alarm.attendee_ids: @@ -442,6 +454,471 @@ or contains the text to be used for display"""), calendar_alarm() + +class calendar_event(osv.osv): + _name = "calendar.event" + _description = "Calendar Event" + + #kept it until fields mapping implemented + __attribute__ = { + 'class': {'field': 'class', 'type': 'selection'}, + 'created': {'field': 'create_date', 'type': 'datetime'}, + 'description': {'field': 'description', 'type': 'text'}, + 'dtstart': {'field': 'date', 'type': 'datetime'}, + 'location': {'field': 'location', 'type': 'text'}, + #'organizer': {'field': 'partner_id', 'sub-field': 'name', 'type': 'many2one'}, + 'priority': {'field': 'priority', 'type': 'int'}, + 'dtstamp': {'field': 'date', 'type': 'datetime'}, + 'seq': None, + 'status': {'field': 'state', 'type': 'selection', 'mapping': \ + {'tentative': 'draft', 'confirmed': 'open', \ + 'cancelled': 'cancel'}}, + 'summary': {'field': 'name', 'type': 'text'}, + 'transp': {'field': 'transparent', 'type': 'text'}, + 'uid': {'field': 'id', 'type': 'text'}, + 'url': {'field': 'caldav_url', 'type': 'text'}, + 'recurrence-id': {'field': 'recurrent_id', 'type': 'datetime'}, + 'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'}, + 'categories': {'field': 'categ_id', 'type': 'many2one', 'object': 'crm.meeting.categ'}, + 'comment': None, + 'contact': None, + 'exdate': {'field': 'exdate', 'type': 'datetime'}, + 'exrule': {'field': 'exrule', 'type': 'text'}, + 'rstatus': None, + 'related': None, + 'resources': None, + 'rdate': None, + 'rrule': {'field': 'rrule', 'type': 'text'}, + 'x-openobject-model': {'value': _name, 'type': 'text'}, + 'dtend': {'field': 'date_deadline', 'type': 'datetime'}, + 'valarm': {'field': 'caldav_alarm_id', 'type': 'many2one', 'object': 'calendar.alarm'}, + } + + def onchange_rrule_type(self, cr, uid, ids, rtype, *args, **argv): + if rtype == 'none' or not rtype: + return {'value': {'rrule': ''}} + if rtype == 'custom': + return {} + rrule = self.pool.get('calendar.custom.rrule') + rrulestr = rrule.compute_rule_string(cr, uid, {'freq': rtype.upper(), \ + 'interval': 1}) + return {'value': {'rrule': rrulestr}} + + def _get_duration(self, cr, uid, ids, name, arg, context): + res = {} + for event in self.browse(cr, uid, ids, context=context): + start = datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S") + res[event.id] = 0 + if event.date_deadline: + end = datetime.strptime(event.date_deadline[:19], "%Y-%m-%d %H:%M:%S") + diff = end - start + duration = float(diff.days)* 24 + (float(diff.seconds) / 3600) + res[event.id] = round(duration, 2) + return res + + def _set_duration(self, cr, uid, id, name, value, arg, context): + event = self.browse(cr, uid, id, context=context) + start = datetime.strptime(event.date, "%Y-%m-%d %H:%M:%S") + end = start + timedelta(hours=value) + cr.execute("UPDATE %s set date_deadline='%s' \ + where id=%s"% (self._table, end.strftime("%Y-%m-%d %H:%M:%S"), id)) + return True + + _columns = { + 'name': fields.char('Description', size=64, required=True), + 'date': fields.datetime('Date'), + 'date_deadline': fields.datetime('Deadline'), + 'duration': fields.function(_get_duration, method=True, \ + fnct_inv=_set_duration, string='Duration'), + 'description': fields.text('Your action'), + 'class': fields.selection([('public', 'Public'), ('private', 'Private'), \ + ('confidential', 'Confidential')], 'Mark as'), + 'location': fields.char('Location', size=264, help="Location of Event"), + 'show_as': fields.selection([('free', 'Free'), \ + ('busy', 'Busy')], + 'Show as'), + 'caldav_url': fields.char('Caldav URL', size=264), + 'exdate': fields.text('Exception Date/Times', help="This property \ +defines the list of date/time exceptions for arecurring calendar component."), + 'exrule': fields.char('Exception Rule', size=352, help="defines a \ +rule or repeating pattern for anexception to a recurrence set"), + 'rrule': fields.char('Recurrent Rule', size=124), + 'rrule_type': fields.selection([('none', 'None'), ('daily', 'Daily'), \ + ('weekly', 'Weekly'), ('monthly', 'Monthly'), \ + ('yearly', 'Yearly'), ('custom', 'Custom')], 'Recurrency'), + 'alarm_id': fields.many2one('res.alarm', 'Alarm'), + 'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'), + 'recurrent_uid': fields.integer('Recurrent ID'), + 'recurrent_id': fields.datetime('Recurrent ID date'), + } + + _defaults = { + 'class': lambda *a: 'public', + 'show_as': lambda *a: 'busy', + } + + def export_cal(self, cr, uid, ids, context={}): + ids = map(lambda x: caldav_id2real_id(x), ids) + event_data = self.read(cr, uid, ids) + event_obj = self.pool.get('basic.calendar.event') + event = self.pool.get('calendar.event') + event_obj.__attribute__.update(event.__attribute__) + ical = event_obj.export_ical(cr, uid, event_data, context={'model': self._name}) + cal_val = ical.serialize() + cal_val = cal_val.replace('"', '').strip() + return cal_val + + def import_cal(self, cr, uid, data, context={}): + file_content = base64.decodestring(data) + event_obj = self.pool.get('basic.calendar.event') + event = self.pool.get('calendar.event') + event_obj.__attribute__.update(event.__attribute__) + + attendee_obj = self.pool.get('basic.calendar.attendee') + attendee = self.pool.get('calendar.attendee') + attendee_obj.__attribute__.update(attendee.__attribute__) + + alarm_obj = self.pool.get('basic.calendar.alarm') + alarm = self.pool.get('calendar.alarm') + alarm_obj.__attribute__.update(alarm.__attribute__) + + vals = event_obj.import_ical(cr, uid, file_content) + ids = [] + for val in vals: + exists, r_id = uid2openobjectid(cr, val['id'], self._name, \ + val.get('recurrent_id')) + if val.has_key('create_date'): val.pop('create_date') + val['caldav_url'] = context.get('url') or '' + val.pop('id') + if exists and r_id: + val.update({'recurrent_uid': exists}) + self.write(cr, uid, [r_id], val) + ids.append(r_id) + elif exists: + self.write(cr, uid, [exists], val) + ids.append(exists) + else: + event_id = self.create(cr, uid, val) + ids.append(event_id) + return ids + + def modify_this(self, cr, uid, ids, defaults, context=None, *args): + datas = self.read(cr, uid, ids[0], context=context) + date = datas.get('date') + defaults.update({ + 'recurrent_uid': caldav_id2real_id(datas['id']), + 'recurrent_id': defaults.get('date'), + 'rrule_type': 'none', + 'rrule': '' + }) + new_id = self.copy(cr, uid, ids[0], default=defaults, context=context) + return new_id + + def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100): + if not limit: + limit = 100 + if isinstance(select, (str, int, long)): + ids = [select] + else: + ids = select + result = [] + if ids and (base_start_date or base_until_date): + cr.execute("select m.id, m.rrule, m.date, m.date_deadline, \ + m.exdate from " + self._table + \ + " m where m.id in ("\ + + ','.join(map(lambda x: str(x), ids))+")") + + count = 0 + for data in cr.dictfetchall(): + start_date = base_start_date and datetime.strptime(base_start_date, "%Y-%m-%d") or False + until_date = base_until_date and datetime.strptime(base_until_date, "%Y-%m-%d") or False + if count > limit: + break + event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S") + if start_date and start_date <= event_date: + start_date = event_date + if not data['rrule']: + if start_date and (event_date < start_date): + continue + if until_date and (event_date > until_date): + continue + idval = real_id2caldav_id(data['id'], data['date']) + result.append(idval) + count += 1 + else: + exdate = data['exdate'] and data['exdate'].split(',') or [] + event_obj = self.pool.get('basic.calendar.event') + rrule_str = data['rrule'] + new_rrule_str = [] + rrule_until_date = False + is_until = False + for rule in rrule_str.split(';'): + name, value = rule.split('=') + if name == "UNTIL": + is_until = True + value = parser.parse(value) + rrule_until_date = parser.parse(value.strftime("%Y-%m-%d")) + if until_date and until_date >= rrule_until_date: + until_date = rrule_until_date + if until_date: + value = until_date.strftime("%Y%m%d%H%M%S") + new_rule = '%s=%s' % (name, value) + new_rrule_str.append(new_rule) + if not is_until and until_date: + value = until_date.strftime("%Y%m%d%H%M%S") + name = "UNTIL" + new_rule = '%s=%s' % (name, value) + new_rrule_str.append(new_rule) + new_rrule_str = ';'.join(new_rrule_str) + start_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S") + rdates = event_obj.get_recurrent_dates(str(new_rrule_str), exdate, start_date) + for rdate in rdates: + r_date = datetime.strptime(rdate, "%Y-%m-%d %H:%M:%S") + if start_date and r_date < start_date: + continue + if until_date and r_date > until_date: + continue + idval = real_id2caldav_id(data['id'], rdate) + result.append(idval) + count += 1 + if result: + ids = result + if isinstance(select, (str, int, long)): + return ids and ids[0] or False + return ids + + def search(self, cr, uid, args, offset=0, limit=100, order=None, + context=None, count=False): + args_without_date = [] + start_date = False + until_date = False + for arg in args: + if arg[0] not in ('date', unicode('date')): + args_without_date.append(arg) + else: + if arg[1] in ('>', '>='): + start_date = arg[2] + elif arg[1] in ('<', '<='): + until_date = arg[2] + res = super(calendar_event, self).search(cr, uid, args_without_date, offset, + limit, order, context, count) + return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit) + + + def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): + if isinstance(ids, (str, int, long)): + select = [ids] + else: + select = ids + new_ids = [] + for id in select: + id = caldav_id2real_id(id) + if not id in new_ids: + new_ids.append(id) + res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context) + if vals.get('alarm_id'): + alarm_obj = self.pool.get('res.alarm') + alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date') + return res + + def browse(self, cr, uid, ids, context=None, list_class=None, fields_process={}): + if isinstance(ids, (str, int, long)): + select = [ids] + else: + select = ids + select = map(lambda x: caldav_id2real_id(x), select) + res = super(calendar_event, self).browse(cr, uid, select, context, list_class, fields_process) + if isinstance(ids, (str, int, long)): + return res and res[0] or False + return res + + def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'): + if isinstance(ids, (str, int, long)): + select = [ids] + else: + select = ids + select = map(lambda x: (x, caldav_id2real_id(x)), select) + result = [] + if fields and 'date' not in fields: + fields.append('date') + for caldav_id, real_id in select: + res = super(calendar_event, self).read(cr, uid, real_id, fields=fields, context=context, \ + load=load) + ls = caldav_id2real_id(caldav_id, with_date=res.get('duration', 0)) + if not isinstance(ls, (str, int, long)) and len(ls) >= 2: + res['date'] = ls[1] + res['date_deadline'] = ls[2] + res['id'] = caldav_id + + result.append(res) + if isinstance(ids, (str, int, long)): + return result and result[0] or False + return result + + def copy(self, cr, uid, id, default=None, context={}): + res = super(calendar_event, self).copy(cr, uid, caldav_id2real_id(id), default, context) + alarm_obj = self.pool.get('res.alarm') + alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date') + return res + + def unlink(self, cr, uid, ids, context=None): + res = False + for id in ids: + ls = caldav_id2real_id(id) + if not isinstance(ls, (str, int, long)) and len(ls) >= 2: + date_new = ls[1] + for record in self.read(cr, uid, [caldav_id2real_id(id)], \ + ['date', 'rrule', 'exdate']): + if record['rrule']: + exdate = (record['exdate'] and (record['exdate'] + ',') or '') + \ + ''.join((re.compile('\d')).findall(date_new)) + 'Z' + if record['date'] == date_new: + res = self.write(cr, uid, [caldav_id2real_id(id)], {'exdate': exdate}) + else: + ids = map(lambda x: caldav_id2real_id(x), ids) + res = super(calendar_event, self).unlink(cr, uid, caldav_id2real_id(ids)) + alarm_obj = self.pool.get('res.alarm') + alarm_obj.do_alarm_unlink(cr, uid, ids, self._name) + else: + ids = map(lambda x: caldav_id2real_id(x), ids) + res = super(calendar_event, self).unlink(cr, uid, ids) + alarm_obj = self.pool.get('res.alarm') + alarm_obj.do_alarm_unlink(cr, uid, ids, self._name) + return res + + def create(self, cr, uid, vals, context={}): + res = super(calendar_event, self).create(cr, uid, vals, context) + alarm_obj = self.pool.get('res.alarm') + alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date') + return res + +calendar_event() + +class calendar_todo(osv.osv): + _name = "calendar.todo" + _inherit = "calendar.event" + _description = "Calendar Task" + + def _get_date(self, cr, uid, ids, name, arg, context): + res = {} + for event in self.browse(cr, uid, ids, context=context): + res[event.id] = event.date_start + return res + + def _set_date(self, cr, uid, id, name, value, arg, context): + event = self.browse(cr, uid, id, context=context) + cr.execute("UPDATE %s set date_start='%s' where id=%s" \ + % (self._table, value, id)) + return True + + _columns = { + 'date': fields.function(_get_date, method=True, fnct_inv=_set_date, \ + string='Duration', store=True, type='datetime'), + 'duration': fields.integer('Duration'), + } + + #kept it until fields mapping implemented + __attribute__ = { + 'class': {'field': 'class', 'type': 'text'}, + 'completed': {'field': 'date_close', 'type': 'datetime'}, +# 'created': {'field': 'field', 'type': 'text'}, + 'description': {'field': 'description', 'type': 'text'}, +# 'dtstamp': {'field': 'field', 'type': 'text'}, + 'dtstart': {'field': 'date_start', 'type': 'datetime'}, + 'duration': {'field': 'planned_hours', 'type': 'timedelta'}, + 'due': {'field': 'date_deadline', 'type': 'datetime'}, +# 'geo': {'field': 'field', 'type': 'text'}, +# 'last-mod ': {'field': 'field', 'type': 'text'}, + 'location': {'field': 'location', 'type': 'text'}, + 'organizer': {'field': 'partner_id', 'type': 'many2one', 'object': 'res.partner'}, + 'percent': {'field': 'progress_rate', 'type': 'int'}, + 'priority': {'field': 'priority', 'type': 'text'}, +# 'recurid': {'field': 'field', 'type': 'text'}, + 'seq': {'field': 'sequence', 'type': 'text'}, + 'status': {'field': 'state', 'type': 'selection', \ + 'mapping': {'needs-action': 'draft', \ + 'completed': 'done', 'in-process': 'open', \ + 'cancelled': 'cancelled'}}, + 'summary': {'field': 'name', 'type': 'text'}, + 'uid': {'field': 'id', 'type': 'int'}, + 'url': {'field': 'caldav_url', 'type': 'text'}, +# 'attach': {'field': 'field', 'type': 'text'}, + 'attendee': {'field': 'attendee_ids', 'type': 'many2many', 'object': 'calendar.attendee'}, + 'comment': {'field': 'notes', 'type': 'text'}, +# 'contact': {'field': 'field', 'type': 'text'}, + 'exdate': {'field':'exdate', 'type':'datetime'}, + 'exrule': {'field':'exrule', 'type':'text'}, +# 'rstatus': {'field': 'field', 'type': 'text'}, +# 'related': {'field': 'field', 'type': 'text'}, +# 'resources': {'field': 'field', 'type': 'text'}, +# 'rdate': {'field': 'field', 'type': 'text'}, + 'rrule': {'field': 'rrule', 'type': 'text'}, + 'valarm': {'field':'caldav_alarm_id', 'type':'many2one', 'object': 'calendar.alarm'}, + } + + def import_cal(self, cr, uid, data, context={}): + file_content = base64.decodestring(data) + todo_obj = self.pool.get('basic.calendar.todo') + todo = self.pool.get('calendar.todo') + todo_obj.__attribute__.update(todo.__attribute__) + + attendee_obj = self.pool.get('basic.calendar.attendee') + crm_attendee = self.pool.get('calendar.attendee') + attendee_obj.__attribute__.update(crm_attendee.__attribute__) + + alarm_obj = self.pool.get('basic.calendar.alarm') + crm_alarm = self.pool.get('calendar.alarm') + alarm_obj.__attribute__.update(crm_alarm.__attribute__) + + vals = todo_obj.import_ical(cr, uid, file_content) + for val in vals: + obj_tm = self.pool.get('res.users').browse(cr, uid, uid, context).company_id.project_time_mode_id + if not val.has_key('planned_hours'): + # 'Computes duration' in days + start = datetime.strptime(val['date_start'], '%Y-%m-%d %H:%M:%S') + end = datetime.strptime(val['date_deadline'], '%Y-%m-%d %H:%M:%S') + diff = end - start + plan = (diff.seconds/float(86400) + diff.days) * obj_tm.factor + val['planned_hours'] = plan + else: + # Converts timedelta into hours + hours = (val['planned_hours'].seconds / float(3600)) + \ + (val['planned_hours'].days * 24) + val['planned_hours'] = hours + exists, r_id = uid2openobjectid(cr, val['id'], self._name, val.get('recurrent_id')) + val.pop('id') + if exists: + self.write(cr, uid, [exists], val) + else: + task_id = self.create(cr, uid, val) + return {'count': len(vals)} + + def export_cal(self, cr, uid, ids, context={}): + task_datas = self.read(cr, uid, ids, [], context ={'read': True}) + tasks = [] + for task in task_datas: + if task.get('planned_hours', None) and task.get('date_deadline', None): + task.pop('planned_hours') + tasks.append(task) + todo_obj = self.pool.get('basic.calendar.todo') + todo = self.pool.get('calendar.todo') + todo_obj.__attribute__.update(todo.__attribute__) + + attendee_obj = self.pool.get('basic.calendar.attendee') + attendee = self.pool.get('calendar.attendee') + attendee_obj.__attribute__.update(attendee.__attribute__) + + alarm_obj = self.pool.get('basic.calendar.alarm') + alarm = self.pool.get('calendar.alarm') + alarm_obj.__attribute__.update(alarm.__attribute__) + + ical = todo_obj.export_ical(cr, uid, tasks, {'model': 'project.task'}) + calendar_val = ical.serialize() + calendar_val = calendar_val.replace('"', '').strip() + return calendar_val + +calendar_todo() + class ir_attachment(osv.osv): _name = 'ir.attachment' _inherit = 'ir.attachment' @@ -474,10 +951,10 @@ class ir_values(osv.osv): new_model.append((data[0], caldav_id2real_id(data[1]))) else: new_model.append(data) - return super(ir_values, self).set(cr, uid, key, key2, name, new_model,\ + return super(ir_values, self).set(cr, uid, key, key2, name, new_model, \ value, replace, isobject, meta, preserve_user, company) - def get(self, cr, uid, key, key2, models, meta=False, context={},\ + def get(self, cr, uid, key, key2, models, meta=False, context={}, \ res_id_req=False, without_user=True, key2_req=True): new_model = [] for data in models: @@ -572,7 +1049,7 @@ class calendar_custom_rrule(osv.osv): freq = datas.get('freq') if freq == 'None': - obj.write(cr, uid, [res_obj.id], {'rrule' : ''}) + obj.write(cr, uid, [res_obj.id], {'rrule': ''}) return {} if freq == 'weekly': @@ -623,7 +1100,7 @@ class calendar_custom_rrule(osv.osv): res_obj = obj.browse(cr, uid, context['active_id']) rrule_string = self.compute_rule_string(cr, uid, datas) - obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string}) + obj.write(cr, uid, [res_obj.id], {'rrule': rrule_string}) return {} calendar_custom_rrule() @@ -646,7 +1123,7 @@ class res_users(osv.osv): status = 'busy' res.update({user_id:status}) - #TOCHECK : Delegrated Event + #TOCHECK: Delegrated Event #cr.execute("SELECT user_id,'busy' FROM att_del_to_user_rel where user_id = ANY(%s)", (ids,)) #res.update(cr.dictfetchall()) for user_id in ids: @@ -691,7 +1168,7 @@ class invite_attendee_wizard(osv.osv_memory): res_obj = obj.browse(cr, uid, context['active_id']) type = datas.get('type') att_obj = self.pool.get('calendar.attendee') - vals = {'ref': '%s,%s'%(model, caldav_id2real_id(context['active_id']))} + vals = {'ref': '%s,%s' % (model, caldav_id2real_id(context['active_id']))} if type == 'internal': user_obj = self.pool.get('res.users') for user_id in datas.get('user_ids', []): @@ -708,7 +1185,6 @@ class invite_attendee_wizard(osv.osv_memory): vals.update({'email': datas['email']}) att_id = att_obj.create(cr, uid, vals) obj.write(cr, uid, res_obj.id, {'attendee_ids': [(4, att_id)]}) - elif type == 'partner': add_obj = self.pool.get('res.partner.address') for contact in add_obj.browse(cr, uid, datas['contact_ids']): diff --git a/addons/caldav/security/ir.model.access.csv b/addons/caldav/security/ir.model.access.csv index 00855f665e9..fabb3c42484 100644 --- a/addons/caldav/security/ir.model.access.csv +++ b/addons/caldav/security/ir.model.access.csv @@ -1,6 +1,10 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"basic_calendar_all","basic.calendar","model_basic_calendar",,1,1,1,1 -"basic_calendar_event_all","basic.calendar.event","model_basic_calendar_event",,1,1,1,1 -"basic_calendar_attendee_all","basic.calendar.attendee","model_basic_calendar_attendee",,1,1,1,1 -"access_basic_calendar_attendee","calendar.attendee","model_basic_calendar_attendee",,1,1,1,1 -"access_basic_calendar_alarm","calendar.alarm","model_basic_calendar_alarm",,1,1,1,1 +"access_basic_calendar_all","basic.calendar","model_basic_calendar",,1,1,1,1 +"access_basic_calendar_event_all","basic.calendar.event","model_basic_calendar_event",,1,1,1,1 +"access_basic_calendar_attendee_all","basic.calendar.attendee","model_basic_calendar_attendee",,1,1,1,1 +"access_calendar_todo_all","basic.calendar.todo","model_basic_calendar_todo",,1,1,1,1 +"access_calendar_todo_all","basic.calendar.todo","model_basic_calendar_todo",,1,1,1,1 +"access_calendar_attendee","calendar.attendee","model_calendar_attendee",,1,1,1,1 +"access_calendar_alarm","calendar.alarm","model_calendar_alarm",,1,1,1,1 +"access_res_alarm","res.alarm","model_res_alarm",,1,1,1,1 +"access_calendar_event_all","calendar.event","model_calendar_event",,1,1,1,1 diff --git a/addons/project_calendar/wizard/__init__.py b/addons/caldav/wizard/__init__.py old mode 100644 new mode 100755 similarity index 92% rename from addons/project_calendar/wizard/__init__.py rename to addons/caldav/wizard/__init__.py index add002b783e..e02dcdc0b06 --- a/addons/project_calendar/wizard/__init__.py +++ b/addons/caldav/wizard/__init__.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). +# Copyright (C) 2004-2009 Tiny SPRL (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -22,5 +22,7 @@ import wizard_cal_export import wizard_cal_import import wizard_cal_subscribe +import wizard_cal_edit_event + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/caldav/wizard/wizard_cal_edit_event.py b/addons/caldav/wizard/wizard_cal_edit_event.py new file mode 100644 index 00000000000..cfe98c65ea8 --- /dev/null +++ b/addons/caldav/wizard/wizard_cal_edit_event.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import wizard +import pooler + +class event_edit_this(wizard.interface): + event_form = """ + + + + + + + + + + + + """ + + event_fields = { + 'name': {'string': 'Title', 'type': 'char', 'size': 64}, + 'date': {'string': 'Start Date', 'type': 'datetime'}, + 'date_deadline': {'string': 'End Date', 'type': 'datetime'}, + 'location': {'string': 'Location', 'type': 'char', 'size': 124}, + 'alarm_id': {'string': 'Reminder', 'type': 'many2one', 'relation': 'res.alarm'}, + } + + def _default_values(self, cr, uid, data, context): + model = data.get('model') + model_obj = pooler.get_pool(cr.dbname).get(model) + event = model_obj.read(cr, uid, data['id'], ['name', 'location', 'date',\ + 'date_deadline', 'alarm_id']) + return event + + def _modify_this(self, cr, uid, datas, *args): + model = datas.get('model') + model_obj = pooler.get_pool(cr.dbname).get(model) + new_id = model_obj.modify_this(cr, uid, [datas['id']], datas['form']) + value = { + 'name': 'New event', + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': model, + 'res_id': new_id, + 'view_id': False, + 'type': 'ir.actions.act_window', + } + return value + + states = { + 'init': { + 'actions': [_default_values], + 'result': {'type': 'form', 'arch': event_form, 'fields': event_fields, + 'state': [('end', 'Cancel', 'gtk-cancel'), ('edit', '_Save', 'gtk-save')]} + }, + 'edit': { + 'actions': [], + 'result': {'type': 'action', 'action': _modify_this, 'state': 'end'} + } + } + +event_edit_this('calendar.event.edit.this') + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/wizard_cal_export.py b/addons/caldav/wizard/wizard_cal_export.py similarity index 86% rename from addons/crm/wizard/wizard_cal_export.py rename to addons/caldav/wizard/wizard_cal_export.py index d6064b926fd..4b32f02420f 100644 --- a/addons/crm/wizard/wizard_cal_export.py +++ b/addons/caldav/wizard/wizard_cal_export.py @@ -24,7 +24,7 @@ import base64 import pooler -class crm_cal_export_wizard(wizard.interface): +class cal_event_export_wizard(wizard.interface): form1 = '''
@@ -35,8 +35,8 @@ class crm_cal_export_wizard(wizard.interface): 'file_path': { 'string': 'Save ICS file', 'type': 'binary', - 'required' : True, - 'filters' : '*.ics' + 'required': True, + 'filters': '*.ics' }, 'name': { 'string': 'File name', @@ -47,8 +47,9 @@ class crm_cal_export_wizard(wizard.interface): } def _process_export_ics(self, cr, uid, data, context): - case_obj = pooler.get_pool(cr.dbname).get('crm.meeting') - calendar = case_obj.export_cal(cr, uid, data['ids'], context) + model = data.get('model') + model_obj = pooler.get_pool(cr.dbname).get(model) + calendar = model_obj.export_cal(cr, uid, data['ids'], context) return {'file_path': base64.encodestring(calendar), \ 'name': 'OpenERP Events.ics'} @@ -59,6 +60,6 @@ class crm_cal_export_wizard(wizard.interface): 'state': [('end', '_Cancel', 'gtk-cancel'), ('end', 'Ok', 'gtk-ok')]}}, } -crm_cal_export_wizard('caldav.crm.export') +cal_event_export_wizard('caldav.event.export') # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/wizard_cal_import.py b/addons/caldav/wizard/wizard_cal_import.py similarity index 90% rename from addons/crm/wizard/wizard_cal_import.py rename to addons/caldav/wizard/wizard_cal_import.py index 58f2c1f34bb..259b3b48b03 100644 --- a/addons/crm/wizard/wizard_cal_import.py +++ b/addons/caldav/wizard/wizard_cal_import.py @@ -23,7 +23,7 @@ import wizard import pooler -class crm_cal_import_wizard(wizard.interface): +class cal_event_import_wizard(wizard.interface): form1 = ''' @@ -52,8 +52,9 @@ class crm_cal_import_wizard(wizard.interface): } def _process_imp_ics(self, cr, uid, data, context=None): - case_obj = pooler.get_pool(cr.dbname).get('crm.meeting') - vals = case_obj.import_cal(cr, uid, data['form']['file_path'], context) + model = data.get('model') + model_obj = pooler.get_pool(cr.dbname).get(model) + vals = model_obj.import_cal(cr, uid, data['form']['file_path'], context) global cnt cnt = 0 if vals: @@ -72,7 +73,7 @@ class crm_cal_import_wizard(wizard.interface): 'open': { 'actions': [], 'result': {'type': 'action', 'action': _process_imp_ics, 'state': 'display'} - }, + }, 'display': { 'actions': [_result_set], 'result': {'type': 'form', 'arch': display, 'fields': display_fields, \ @@ -80,6 +81,6 @@ class crm_cal_import_wizard(wizard.interface): }, } -crm_cal_import_wizard('caldav.crm.import') +cal_event_import_wizard('caldav.event.import') # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/wizard/wizard_cal_subscribe.py b/addons/caldav/wizard/wizard_cal_subscribe.py similarity index 90% rename from addons/crm/wizard/wizard_cal_subscribe.py rename to addons/caldav/wizard/wizard_cal_subscribe.py index f51bbe29fb8..4fcdeffd89f 100644 --- a/addons/crm/wizard/wizard_cal_subscribe.py +++ b/addons/caldav/wizard/wizard_cal_subscribe.py @@ -25,7 +25,7 @@ import pooler import urllib import wizard -class crm_cal_subscribe_wizard(wizard.interface): +class cal_event_subscribe_wizard(wizard.interface): form1 = ''' @@ -58,13 +58,14 @@ class crm_cal_subscribe_wizard(wizard.interface): cnt = 0 try: f = urllib.urlopen(data['form']['url_path']) - caldata= f.fp.read() + caldata = f.fp.read() f.close() except Exception,e: raise wizard.except_wizard(_('Error!'), _('Please provide Proper URL !')) - case_obj = pooler.get_pool(cr.dbname).get('crm.meeting') + model = data.get('model') + model_obj = pooler.get_pool(cr.dbname).get(model) context.update({'url': data['form']['url_path']}) - vals = case_obj.import_cal(cr, uid, base64.encodestring(caldata), context) + vals = model_obj.import_cal(cr, uid, base64.encodestring(caldata), context) if vals: cnt = vals['count'] return {} @@ -89,6 +90,6 @@ class crm_cal_subscribe_wizard(wizard.interface): }, } -crm_cal_subscribe_wizard('caldav.crm.subscribe') +cal_event_subscribe_wizard('caldav.event.subscribe') # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/__terp__.py b/addons/crm/__terp__.py index ee02b30bd66..d01f083c2d9 100644 --- a/addons/crm/__terp__.py +++ b/addons/crm/__terp__.py @@ -81,8 +81,8 @@ between mails and Open ERP.""", 'crm_claims_menu.xml', # 'crm_report_view.xml', - # 'crm_helpdesk_view.xml', - # 'crm_helpdesk_menu.xml', + 'crm_helpdesk_view.xml', + 'crm_helpdesk_menu.xml', #'crm_report.xml', 'security/crm_security.xml', #'security/ir.model.access.csv', diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 53173754b8e..f1b4eab309b 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -101,6 +101,67 @@ class crm_case_section(osv.osv): return res crm_case_section() +class crm_case_categ(osv.osv): + _name = "crm.case.categ" + _description = "Category of case" + + _columns = { + 'name': fields.char('Case Category Name', size=64, required=True, translate=True), + 'probability': fields.float('Probability (%)', required=True), + 'section_id': fields.many2one('crm.case.section', 'Case Section'), + 'object_id': fields.many2one('ir.model','Object Name'), + } + def _find_object_id(self, cr, uid, context=None): + object_id = context and context.get('object_id', False) or False + ids =self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)]) + return ids and ids[0] + _defaults = { + 'probability': lambda *args: 0.0, + 'object_id' : _find_object_id + } +# +crm_case_categ() + +class crm_case_resource_type(osv.osv): + _name = "crm.case.resource.type" + _description = "Resource Type of case" + _rec_name = "name" + _columns = { + 'name': fields.char('Case Resource Type', size=64, required=True, translate=True), + 'section_id': fields.many2one('crm.case.section', 'Case Section'), + 'object_id': fields.many2one('ir.model','Object Name'), + } + def _find_object_id(self, cr, uid, context=None): + object_id = context and context.get('object_id', False) or False + ids =self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)]) + return ids and ids[0] + _defaults = { + 'object_id' : _find_object_id + } +crm_case_resource_type() + + +class crm_case_stage(osv.osv): + _name = "crm.case.stage" + _description = "Stage of case" + _rec_name = 'name' + _order = "sequence" + _columns = { + 'name': fields.char('Stage Name', size=64, required=True, translate=True), + 'section_id': fields.many2one('crm.case.section', 'Case Section'), + 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."), + 'object_id': fields.many2one('ir.model','Object Name'), + } + def _find_object_id(self, cr, uid, context=None): + object_id = context and context.get('object_id', False) or False + ids =self.pool.get('ir.model').search(cr, uid, [('model', '=', object_id)]) + return ids and ids[0] + _defaults = { + 'sequence': lambda *args: 1, + 'object_id' : _find_object_id + } + +crm_case_stage() class crm_case_rule(osv.osv): @@ -327,7 +388,7 @@ class crm_case(osv.osv): def stage_next(self, cr, uid, ids, context={}): ok = False - sid = self.pool.get('crm.case.stage').search(cr, uid, [], context=context) + sid = self.pool.get('crm.case.stage').search(cr, uid, [('object_id.model', '=', self._name)], context=context) s = {} previous = {} for stage in self.pool.get('crm.case.stage').browse(cr, uid, sid, context=context): diff --git a/addons/crm/crm_claim.py b/addons/crm/crm_claim.py index 693e5aa1a22..781ce45bacb 100644 --- a/addons/crm/crm_claim.py +++ b/addons/crm/crm_claim.py @@ -27,44 +27,7 @@ import netsvc from tools.translate import _ import crm -class crm_claim_categ(osv.osv): - _name = "crm.claim.categ" - _description = "Claim Categories" - _columns = { - 'name': fields.char('Category Name', size=64, required=True), - 'probability': fields.float('Probability (%)', required=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - _defaults = { - 'probability': lambda *args: 0.0 - } -crm_claim_categ() -class crm_claim_type(osv.osv): - _name = "crm.claim.type" - _description = "Claim Type" - _rec_name = "name" - _columns = { - 'name': fields.char('Claim Type Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - -crm_claim_type() - -class crm_claim_stage(osv.osv): - _name = "crm.claim.stage" - _description = "Stage of claim case" - _rec_name = 'name' - _order = "sequence" - _columns = { - 'name': fields.char('Stage Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."), - } - _defaults = { - 'sequence': lambda *args: 1 - } -crm_claim_stage() class crm_claim(osv.osv): _name = "crm.claim" @@ -82,23 +45,23 @@ class crm_claim(osv.osv): 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \ "the partner mentality in relation to our services.The scale has" \ "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."), - 'categ_id': fields.many2one('crm.claim.categ','Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'type_id': fields.many2one('crm.claim.type', 'Claim Type', domain="[('section_id','=',section_id)]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Claim Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), 'partner_name': fields.char("Employee's Name", size=64), 'partner_mobile': fields.char('Mobile', size=32), 'partner_phone': fields.char('Phone', size=32), - 'stage_id': fields.many2one ('crm.claim.stage', 'Stage', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.claim')]"), } _defaults = { - 'priority': lambda *a: AVAILABLE_PRIORITIES[2][0], + 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], } def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.claim.categ').browse(cr, uid, categ, context).probability + cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability return {'value':{'probability':cat}} crm_claim() diff --git a/addons/crm/crm_claims_data.xml b/addons/crm/crm_claims_data.xml index 9566e28f52a..f9388e06daf 100644 --- a/addons/crm/crm_claims_data.xml +++ b/addons/crm/crm_claims_data.xml @@ -5,53 +5,63 @@ - + Factual Claims + - + Value Claims + - + Policy Claims + - + Corrective + - + Preventive + - + Accepted as Claim + - + Fixed + - + Won't fix + - + Invalid + - + Awaiting Response + \ No newline at end of file diff --git a/addons/crm/crm_claims_menu.xml b/addons/crm/crm_claims_menu.xml index 50cdd72c982..211c632a804 100644 --- a/addons/crm/crm_claims_menu.xml +++ b/addons/crm/crm_claims_menu.xml @@ -1,11 +1,11 @@ - + ######################## CLAIMS (menu) ########################### - All Claims + Claims crm.claim form tree,calendar,form,graph @@ -38,7 +38,7 @@ - + diff --git a/addons/crm/crm_claims_view.xml b/addons/crm/crm_claims_view.xml index ec7568d1aa3..0e81f4f34e2 100644 --- a/addons/crm/crm_claims_view.xml +++ b/addons/crm/crm_claims_view.xml @@ -4,73 +4,25 @@ # ------------------------------------------------------ # Claims # ------------------------------------------------------ - - - - - crm.claim.categ.form - crm.claim.categ - form - - - - - - - - - - crm.claim.categ.tree - crm.claim.categ - tree - - - - - - - - - Claim Categories - crm.claim.categ + crm.case.categ form - + + [('object_id.model', '=', 'crm.claim')] + {'object_id':'crm.claim'} - # ------------------------------------------------------ - # Stage - # ------------------------------------------------------ - - crm.claim.stage.tree - crm.claim.stage - tree - - - - - - - - - - crm.claim.stage.form - crm.claim.stage - form - -
- - - - - -
+ # ------------------------------------------------------ + # Stages + # ------------------------------------------------------ Claim Stages - crm.claim.stage + crm.case.stage form - + + [('object_id.model', '=', 'crm.claim')] + {'object_id':'crm.claim'} diff --git a/addons/crm/crm_fund_data.xml b/addons/crm/crm_fund_data.xml index 08b8d71e5bb..1c566279b90 100644 --- a/addons/crm/crm_fund_data.xml +++ b/addons/crm/crm_fund_data.xml @@ -4,46 +4,54 @@ - + Social Rehabilitation And Rural Upliftment + - + Learning And Education + - + Healthcare + - + Arts And Culture + - + - + Cash + - + Cheque + - + Credit Card + - + Demand Draft + diff --git a/addons/crm/crm_fund_menu.xml b/addons/crm/crm_fund_menu.xml index df7cc431173..57353e2c6ac 100644 --- a/addons/crm/crm_fund_menu.xml +++ b/addons/crm/crm_fund_menu.xml @@ -2,8 +2,9 @@ + - All Funds + Funds crm.fundraising tree,form,graph @@ -28,8 +29,7 @@ - - + diff --git a/addons/crm/crm_fund_view.xml b/addons/crm/crm_fund_view.xml index 2ef4c98ea6f..4fec4afb976 100644 --- a/addons/crm/crm_fund_view.xml +++ b/addons/crm/crm_fund_view.xml @@ -5,70 +5,25 @@ # ------------------------------------------------------ # Fund Raising Categories # ------------------------------------------------------ - - crm.fundraising.categ.form - crm.fundraising.categ - form - -
- - - - - -
- - crm.fundraising.categ.tree - crm.fundraising.categ - tree - - - - - - - - - Fundraising Categories - crm.fundraising.categ + crm.case.categ form - + + [('object_id.model', '=', 'crm.fundraising')] + {'object_id':'crm.fundraising'} # ------------------------------------------------------ # Fund Stage # ------------------------------------------------------ - - crm.fundraising.stage.tree - crm.fundraising.stage - tree - - - - - - - - - - crm.fundraising.stage.form - crm.fundraising.stage - form - -
- - - - - -
Fundraising Stages - crm.claim.stage + crm.case.stage form - + + [('object_id.model', '=', 'crm.fundraising')] + {'object_id':'crm.fundraising'} diff --git a/addons/crm/crm_fundraising.py b/addons/crm/crm_fundraising.py index 30c01d5de2f..046065e61f2 100644 --- a/addons/crm/crm_fundraising.py +++ b/addons/crm/crm_fundraising.py @@ -34,44 +34,6 @@ from osv.orm import except_orm import crm -class crm_fundraising_categ(osv.osv): - _name = "crm.fundraising.categ" - _description = "Fundraising Categories" - _columns = { - 'name': fields.char('Category Name', size=64, required=True), - 'probability': fields.float('Probability (%)', required=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - _defaults = { - 'probability': lambda *args: 0.0 - } -crm_fundraising_categ() - -class crm_fundraising_type(osv.osv): - _name = "crm.fundraising.type" - _description = "Fundraising Type" - _rec_name = "name" - _columns = { - 'name': fields.char('Fundraising Type Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - -crm_fundraising_type() - -class crm_fundraising_stage(osv.osv): - _name = "crm.fundraising.stage" - _description = "Stage of fundraising case" - _rec_name = 'name' - _order = "sequence" - _columns = { - 'name': fields.char('Stage Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."), - } - _defaults = { - 'sequence': lambda *args: 1 - } -crm_fundraising_stage() class crm_fundraising(osv.osv): @@ -82,7 +44,7 @@ class crm_fundraising(osv.osv): _columns = { 'date_closed': fields.datetime('Closed', readonly=True), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'categ_id': fields.many2one('crm.fundraising.categ','Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.fundraising')]"), 'planned_revenue': fields.float('Planned Revenue'), 'planned_cost': fields.float('Planned Costs'), 'probability': fields.float('Probability (%)'), @@ -90,8 +52,8 @@ class crm_fundraising(osv.osv): 'partner_name2': fields.char('Employee Email', size=64), 'partner_phone': fields.char('Phone', size=32), 'partner_mobile': fields.char('Mobile', size=32), - 'stage_id': fields.many2one ('crm.fundraising.stage', 'Stage', domain="[('section_id','=',section_id)]"), - 'type_id': fields.many2one('crm.fundraising.type', 'Fundraising Type', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id)]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Fundraising Type', domain="[('section_id','=',section_id)]"), 'duration': fields.float('Duration'), 'ref' : fields.reference('Reference', selection=crm._links_get, size=128), 'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128), @@ -103,12 +65,12 @@ class crm_fundraising(osv.osv): } _defaults = { - 'priority': lambda *a: AVAILABLE_PRIORITIES[2][0], + 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], } def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.fundraising.categ').browse(cr, uid, categ, context).probability + cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability return {'value':{'probability':cat}} diff --git a/addons/crm/crm_helpdesk.py b/addons/crm/crm_helpdesk.py index cdf6d25f3bf..ca4bf47006b 100644 --- a/addons/crm/crm_helpdesk.py +++ b/addons/crm/crm_helpdesk.py @@ -34,18 +34,7 @@ from osv.orm import except_orm import crm -class crm_helpdesk_categ(osv.osv): - _name = "crm.helpdesk.categ" - _description = "Helpdesk Categories" - _columns = { - 'name': fields.char('Category Name', size=64, required=True), - 'probability': fields.float('Probability (%)', required=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - _defaults = { - 'probability': lambda *args: 0.0 - } -crm_helpdesk_categ() + class crm_helpdesk(osv.osv): _name = "crm.helpdesk" @@ -65,13 +54,13 @@ class crm_helpdesk(osv.osv): 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \ "the partner mentality in relation to our services.The scale has" \ "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."), - 'categ_id': fields.many2one('crm.helpdesk.categ', 'Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.helpdesk')]"), 'duration': fields.float('Duration'), } def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.helpdesk.categ').browse(cr, uid, categ, context).probability + cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability return {'value':{'probability':cat}} crm_helpdesk() diff --git a/addons/crm/crm_helpdesk_menu.xml b/addons/crm/crm_helpdesk_menu.xml index e546a10e2e2..270237aa698 100644 --- a/addons/crm/crm_helpdesk_menu.xml +++ b/addons/crm/crm_helpdesk_menu.xml @@ -1,15 +1,14 @@ - + ######################## Help Desk (menu) ########################### - All Helpdesk Requests + Helpdesk Requests crm.helpdesk tree,calendar,form - - + @@ -31,7 +30,7 @@
- +
diff --git a/addons/crm/crm_helpdesk_view.xml b/addons/crm/crm_helpdesk_view.xml index 25c2d68b787..112440cef68 100644 --- a/addons/crm/crm_helpdesk_view.xml +++ b/addons/crm/crm_helpdesk_view.xml @@ -5,36 +5,13 @@ # ------------------------------------------------------ # Helpdesk Support Categories # ------------------------------------------------------ - - crm.helpdesk.categ.form - crm.helpdesk.categ - form - -
- - - - - -
- - crm.helpdesk.categ.tree - crm.helpdesk.categ - tree - - - - - - - - - Helpdesk Categories - crm.helpdesk.categ + crm.case.categ form - + + [('object_id.model', '=', 'crm.helpdesk')] + {'object_id':'crm.helpdesk'} # ------------------------------------------------------ diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 9fe1b1c4236..8fd0f81f6a4 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -34,45 +34,10 @@ from osv.orm import except_orm import crm -class crm_lead_categ(osv.osv): - _name = "crm.lead.categ" - _description = "Lead Categories" - _columns = { - 'name': fields.char('Category Name', size=64, required=True), - 'probability': fields.float('Probability (%)', required=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - _defaults = { - 'probability': lambda *args: 0.0 - } -crm_lead_categ() -class crm_lead_type(osv.osv): - _name = "crm.lead.type" - _description = "Lead Type" - _rec_name = "name" - _columns = { - 'name': fields.char('lead Type Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } -crm_lead_type() - -class crm_lead_stage(osv.osv): - _name = "crm.lead.stage" - _description = "Stage of claim case" - _rec_name = 'name' - _order = "sequence" - _columns = { - 'name': fields.char('Stage Name', size=64, required=True, translate=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."), - } - _defaults = { - 'sequence': lambda *args: 1 - } -crm_lead_stage() class crm_opportunity(osv.osv): _name = "crm.opportunity" + _description = "Opportunity Cases" crm_opportunity() class crm_lead(osv.osv): @@ -81,8 +46,8 @@ class crm_lead(osv.osv): _order = "id desc" _inherit = 'crm.case' _columns = { - 'categ_id': fields.many2one('crm.lead.categ', 'Category', domain="[('section_id','=',section_id)]"), - 'type_id': fields.many2one('crm.lead.type', 'Lead Type Name', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Lead Type Name', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), 'partner_name': fields.char("Employee's Name", size=64), 'partner_name2': fields.char('Employee Email', size=64), 'partner_phone': fields.char('Phone', size=32), @@ -96,7 +61,7 @@ class crm_lead(osv.osv): " With each commercial opportunity, you can indicate the canall which is this opportunity source."), 'planned_revenue': fields.float('Planned Revenue'), 'planned_cost': fields.float('Planned Costs'), - 'stage_id': fields.many2one ('crm.lead.stage', 'Stage', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.lead')]"), 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \ "the partner mentality in relation to our services.The scale has" \ "to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."), @@ -106,7 +71,7 @@ class crm_lead(osv.osv): def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.lead.categ').browse(cr, uid, categ, context).probability + cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability return {'value':{'probability':cat}} crm_lead() diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index bb232abfa52..6f142391d28 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -2,93 +2,114 @@ - + Existing Customer + - + Self Generated + - + Employee + - + Partner + - + Website + - + Word of mouth + - + Other + - + New + - + Assigned + - + In Process + - + Converted + - + Recycled + - + Dead + - + Telesales + - + Mail + - + Email + - + Print + - + Web + - + Radio + - + Television + - + Newsletter + diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 98e8a365dc7..537fc25cea5 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -5,72 +5,27 @@ # ------------------------------------------------------ # Leads Categories # ------------------------------------------------------ - - - crm.lead.categ.form - crm.lead.categ - form - -
- - - - - -
- - crm.lead.categ.tree - crm.lead.categ - tree - - - - - - - - Lead Categories - crm.lead.categ + crm.case.categ form - + + [('object_id.model', '=', 'crm.lead')] + {'object_id':'crm.lead'} # ------------------------------------------------------ # Stage # ------------------------------------------------------ - - crm.lead.stage.tree - crm.lead.stage - tree - - - - - - - - - - crm.lead.stage.form - crm.lead.stage - form - -
- - - - - -
Lead Stages - crm.claim.stage + crm.case.stage form - + + [('object_id.model', '=', 'crm.lead')] + {'object_id':'crm.lead'} # ------------------------------------------------------ @@ -98,7 +53,7 @@ -