diff options
134 files changed, 4654 insertions, 2814 deletions
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 (<http://tiny.be>). # @@ -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 <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## @@ -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 @@ <newline/> <field name="date_start"/> <field name="date" select="2"/> - <field name="active" select="2"/> + <newline/> <field name="quantity_max"/> <field name="user_id"/> 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) <fp@tinyerp.com>\n" +"PO-Revision-Date: 2010-01-19 09:48+0000\n" +"Last-Translator: lem0na <nickyk@gmx.net>\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) <fp@tinyerp.com>\n" +"PO-Revision-Date: 2010-01-18 23:06+0000\n" +"Last-Translator: Holverat <holverat@gmail.com>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 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 <pedro.bicudo@tgtconsult.com.br>\n" +"PO-Revision-Date: 2010-01-20 01:10+0000\n" +"Last-Translator: pedrobom <pedrobomlimeira@gmail.com>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 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 @@ </record> + <!-- <record id='view_partner_address_form_inherited5' model='ir.ui.view'> <field name='name'>res.partner.address.form.inherited5</field> <field name='model'>res.partner.address</field> @@ -319,7 +320,7 @@ <field name='type'>form</field> <field name='arch' type='xml'> <group string="Communication" colspan="2" col="2" position="after"> - <newline/> + <newline/> <field name="job_ids" mode="tree,form" colspan="4"> <tree string="Contacts" editable="top"> <field name="contact_id"/> @@ -341,17 +342,18 @@ </group> </field> </record> + --> - <record id="view_res_partner_address_filter" model="ir.ui.view"> - <field name="name">res.partner.address.select</field> - <field name="model">res.partner.address</field> - <field name="type">search</field> - <field name="inherit_id" ref="base.view_res_partner_address_filter"/> - <field name="arch" type="xml"> - <search string="Search Contact"> - <field name="job_ids" select='1'/> - </search> - </field> + <record id="view_res_partner_address_filter" model="ir.ui.view"> + <field name="name">res.partner.address.select</field> + <field name="model">res.partner.address</field> + <field name="type">search</field> + <field name="inherit_id" ref="base.view_res_partner_address_filter"/> + <field name="arch" type="xml"> + <search string="Search Contact"> + <field name="job_ids" select='1'/> + </search> + </field> </record> <!-- Views for res.partner.job --> 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 (<http://tiny.be>). # @@ -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 <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## @@ -25,6 +25,7 @@ import cStringIO import wizard from osv import osv import pooler +from tools.translate import _ form_rep = '''<?xml version="1.0"?> <form string="Standard entries"> @@ -35,7 +36,7 @@ form_rep = '''<?xml version="1.0"?> 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 @@ <record model="res.alarm" id="alarm9"> <field name="name">3 hours before</field> - + <field name="active" eval="1" /> <field name="trigger_duration" eval="3" /> <field name="trigger_interval">hours</field> @@ -86,7 +86,7 @@ <record model="res.alarm" id="alarm10"> <field name="name">4 hours before</field> - + <field name="active" eval="1" /> <field name="trigger_duration" eval="4" /> <field name="trigger_interval">hours</field> @@ -96,7 +96,7 @@ <record model="res.alarm" id="alarm11"> <field name="name">5 hours before</field> - + <field name="active" eval="1" /> <field name="trigger_duration" eval="5" /> <field name="trigger_interval">hours</field> @@ -106,7 +106,7 @@ <record model="res.alarm" id="alarm12"> <field name="name">18 hours before</field> - + <field name="active" eval="1" /> <field name="trigger_duration" eval="18" /> <field name="trigger_interval">hours</field> @@ -115,9 +115,9 @@ </record> - <!-- Scheduler for Event Alarm--> - <record forcecreate="True" id="ir_cron_scheduler_alarm" - model="ir.cron"> + <!-- Scheduler for Event Alarm--> + <record forcecreate="True" id="ir_cron_scheduler_alarm" + model="ir.cron"> <field name="name">Run Event Reminder</field> <field eval="True" name="active" /> <field name="user_id" ref="base.user_root" /> 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <wizard string="Import .ics File" model="calendar.event" + name="caldav.event.import" id="wizard_cal_event_import" multi="True" /> + + <wizard string="Subscribe to a Remote calendar" + model="calendar.event" name="caldav.event.subscribe" + id="wizard_cal_event_subscribe" multi="True" /> + + <wizard string="Export .ics File" model="calendar.event" + name="caldav.event.export" id="wizard_cal_event_export" multi="True" /> + + <wizard string="Edit this event" model="calendar.event" + name="calendar.event.edit.this" id="wizard_edit_this_event" + menu="False" /> + + </data> +</openerp> 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 index add002b783e..e02dcdc0b06 100644..100755 --- 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 (<http://tiny.be>). +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). # # 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 (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + +import wizard +import pooler + +class event_edit_this(wizard.interface): + event_form = """<?xml version="1.0"?> + <form string="Edit Event"> + <separator string="" colspan="4" /> + <newline /> + <field name='name' colspan="4" /> + <newline /> + <field name='location' colspan="4" /> + <newline /> + <field name='date' /> + <field name='date_deadline' /> + <newline /> + <field name='alarm_id'/> + </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 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 = '''<?xml version="1.0"?> <form string="Export ICS"> <field name="name"/> @@ -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 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 = '''<?xml version="1.0"?> <form string="Import ICS"> <separator string="Select ICS file"/> @@ -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 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 = '''<?xml version="1.0"?> <form string="Subscribe to Remote ICS"> <separator string="Provide path for Remote Calendar"/> @@ -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 @@ <!-- Claims Categories --> - <record model="crm.claim.categ" id="categ_claim1"> + <record model="crm.case.categ" id="categ_claim1"> <field name="name">Factual Claims</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.categ" id="categ_claim2"> + <record model="crm.case.categ" id="categ_claim2"> <field name="name">Value Claims</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.categ" id="categ_claim3"> + <record model="crm.case.categ" id="categ_claim3"> <field name="name">Policy Claims</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> <!-- Case Category2 --> - <record model="crm.claim.type" id="type_claim1"> + <record model="crm.case.resource.type" id="type_claim1"> <field name="name">Corrective</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.type" id="type_claim2"> + <record model="crm.case.resource.type" id="type_claim2"> <field name="name">Preventive</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> <!-- Case Stage --> - <record model="crm.claim.stage" id="stage_claim1"> + <record model="crm.case.stage" id="stage_claim1"> <field name="name">Accepted as Claim</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.stage" id="stage_claim2"> + <record model="crm.case.stage" id="stage_claim2"> <field name="name">Fixed</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.stage" id="stage_claim3"> + <record model="crm.case.stage" id="stage_claim3"> <field name="name">Won't fix</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.stage" id="stage_claim4"> + <record model="crm.case.stage" id="stage_claim4"> <field name="name">Invalid</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.claim.stage" id="stage_claim5"> + <record model="crm.case.stage" id="stage_claim5"> <field name="name">Awaiting Response</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> </data> </openerp>
\ 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 @@ <?xml version="1.0"?> <openerp> <data noupdate="1"> -<!-- <menuitem id="menu_aftersale" name="After-Sale Services" parent="crm.menu_crm"/>--> + <menuitem id="base.menu_aftersale" name="After-Sale Services" parent="base.menu_base_partner" sequence="6"/> ######################## CLAIMS (menu) ########################### <record model="ir.actions.act_window" id="crm_case_categ_claim0"> - <field name="name">All Claims</field> + <field name="name">Claims</field> <field name="res_model">crm.claim</field> <field name="view_type">form</field> <field name="view_mode">tree,calendar,form,graph</field> @@ -38,7 +38,7 @@ <field name="act_window_id" ref="crm_case_categ_claim0"/> </record> -<!-- <menuitem name="Claims" id="menu_crm_case_claims" parent="menu_aftersale" action="crm_case_categ_claim0"/>--> + <menuitem name="Claims" id="menu_crm_case_claims" parent="base.menu_aftersale" action="crm_case_categ_claim0"/> </data> 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 # ------------------------------------------------------ - - - <!-- Claim Categories --> - <record id="crm_claim_categ_view_form" model="ir.ui.view"> - <field name="name">crm.claim.categ.form</field> - <field name="model">crm.claim.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Claim Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_claim_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.claim.categ.tree</field> - <field name="model">crm.claim.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Claim Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record id="crm_claim_categ_action" model="ir.actions.act_window"> <field name="name">Claim Categories</field> - <field name="res_model">crm.claim.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_claim_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.claim')]</field> + <field name="context">{'object_id':'crm.claim'}</field> </record> <menuitem action="crm_claim_categ_action" id="menu_crm_case_claim-act" parent="crm.menu_crm_case_categ"/> - # ------------------------------------------------------ - # Stage - # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_claim_stage_tree"> - <field name="name">crm.claim.stage.tree</field> - <field name="model">crm.claim.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_claim_stage_form"> - <field name="name">crm.claim.stage.form</field> - <field name="model">crm.claim.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> + # ------------------------------------------------------ + # Stages + # ------------------------------------------------------ <record id="crm_claim_stage_act" model="ir.actions.act_window"> <field name="name">Claim Stages</field> - <field name="res_model">crm.claim.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_claim_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.claim')]</field> + <field name="context">{'object_id':'crm.claim'}</field> </record> <menuitem action="crm_claim_stage_act" id="menu_crm_claim_stage_act" parent="crm.menu_crm_case_stage"/> 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 @@ <!-- FUNDRAISING CATEGORY(categ_id) --> - <record model="crm.fundraising.categ" id="categ_fund1"> + <record model="crm.case.categ" id="categ_fund1"> <field name="name">Social Rehabilitation And Rural Upliftment</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.categ" id="categ_fund2"> + <record model="crm.case.categ" id="categ_fund2"> <field name="name">Learning And Education</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.categ" id="categ_fund3"> + <record model="crm.case.categ" id="categ_fund3"> <field name="name">Healthcare</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.categ" id="categ_fund4"> + <record model="crm.case.categ" id="categ_fund4"> <field name="name">Arts And Culture</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <!-- CASE CATEGORY2(category2_id) --> + <!-- CASE Resource(type_id) --> - <record model="crm.fundraising.type" id="type_fund1"> + <record model="crm.case.resource.type" id="type_fund1"> <field name="name">Cash</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.type" id="type_fund2"> + <record model="crm.case.resource.type" id="type_fund2"> <field name="name">Cheque</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.type" id="type_fund3"> + <record model="crm.case.resource.type" id="type_fund3"> <field name="name">Credit Card</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.fundraising.type" id="type_fund4"> + <record model="crm.case.resource.type" id="type_fund4"> <field name="name">Demand Draft</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> </data> 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 @@ <openerp> <data noupdate="1"> <!-- MENU --> + <menuitem id="base.menu_fundrising" name="Fund Raising" parent="base.menu_base_partner" sequence="7"/> <record model="ir.actions.act_window" id="crm_case_category_act_fund_all1"> - <field name="name">All Funds</field> + <field name="name">Funds</field> <field name="res_model">crm.fundraising</field> <field name="view_mode">tree,form,graph</field> <field name="view_id" ref="crm.crm_case_tree_view_fund"/> @@ -28,8 +29,7 @@ <field name="view_id" ref="crm.crm_case_graph_view_fund"/> <field name="act_window_id" ref="crm_case_category_act_fund_all1"/> </record> - -<!-- <menuitem name="Fund Raising" id="menu_crm_case_fund_raise" parent="crm.menu_crm" action="crm_case_category_act_fund_all1"/>--> + <menuitem name="Fund Raising" id="menu_crm_case_fund_raise" parent="base.menu_fundrising" action="crm_case_category_act_fund_all1" sequence="1"/> </data> </openerp> 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 # ------------------------------------------------------ - <record id="crm_fund_categ_view_form" model="ir.ui.view"> - <field name="name">crm.fundraising.categ.form</field> - <field name="model">crm.fundraising.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Fundraising Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_fund_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.fundraising.categ.tree</field> - <field name="model">crm.fundraising.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Fundraising Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record id="crm_fund_categ_action" model="ir.actions.act_window"> <field name="name">Fundraising Categories</field> - <field name="res_model">crm.fundraising.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_fund_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.fundraising')]</field> + <field name="context">{'object_id':'crm.fundraising'}</field> </record> <menuitem action="crm_fund_categ_action" id="menu_crm_case_fundraising-act" parent="crm.menu_crm_case_categ"/> # ------------------------------------------------------ # Fund Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_fundraising_stage_tree"> - <field name="name">crm.fundraising.stage.tree</field> - <field name="model">crm.fundraising.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_fundraising_stage_form"> - <field name="name">crm.fundraising.stage.form</field> - <field name="model">crm.fundraising.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> <record id="crm_fundraising_stage_act" model="ir.actions.act_window"> <field name="name">Fundraising Stages</field> - <field name="res_model">crm.claim.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_fundraising_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.fundraising')]</field> + <field name="context">{'object_id':'crm.fundraising'}</field> </record> <menuitem action="crm_fundraising_stage_act" id="menu_crm_fundraising_stage_act" parent="crm.menu_crm_case_stage"/> 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 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data noupdate="1"> -<!-- <menuitem id="menu_aftersale" name="After-Sale Services" parent="crm.menu_crm"/>--> + <menuitem id="base.menu_aftersale" name="After-Sale Services" parent="base.menu_base_partner" sequence="6"/> ######################## Help Desk (menu) ########################### <record model="ir.actions.act_window" id="crm_case_helpdesk_act111"> - <field name="name">All Helpdesk Requests</field> + <field name="name">Helpdesk Requests</field> <field name="res_model">crm.helpdesk</field> <field name="view_mode">tree,calendar,form</field> - <field name="view_id" ref="crm_case_tree_view_helpdesk"/> - <field name="domain" eval="'[(\'section_id\',\'=\','+str(ref('section_support_help'))+')]'"/> + <field name="view_id" ref="crm_case_tree_view_helpdesk"/> <field name="context" eval="{'default_state':'open'}"/> <field name="search_view_id" ref="crm.view_crm_case_filter"/> </record> @@ -31,7 +30,7 @@ <field name="view_id" ref="crm_case_form_view_helpdesk"/> <field name="act_window_id" ref="crm_case_helpdesk_act111"/> </record> -<!-- <menuitem name="Helpdesk and Support" id="menu_help_support_main" parent="menu_aftersale" action="crm_case_helpdesk_act111"/> --> + <menuitem name="Helpdesk and Support" id="menu_help_support_main" parent="base.menu_aftersale" action="crm_case_helpdesk_act111"/> </data> </openerp> 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 # ------------------------------------------------------ - <record id="crm_helpdesk_categ_view_form" model="ir.ui.view"> - <field name="name">crm.helpdesk.categ.form</field> - <field name="model">crm.helpdesk.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Helpdesk Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_helpdesk_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.helpdesk.categ.tree</field> - <field name="model">crm.helpdesk.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Helpdesk Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record id="crm_helpdesk_categ_action" model="ir.actions.act_window"> <field name="name">Helpdesk Categories</field> - <field name="res_model">crm.helpdesk.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_helpdesk_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.helpdesk')]</field> + <field name="context">{'object_id':'crm.helpdesk'}</field> </record> <menuitem action="crm_helpdesk_categ_action" id="menu_crm_case_helpdesk-act" parent="crm.menu_crm_case_categ"/> # ------------------------------------------------------ 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 @@ <openerp> <data noupdate="1"> - <record model="crm.lead.categ" id="categ_lead1"> + <record model="crm.case.categ" id="categ_lead1"> <field name="name">Existing Customer</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead2"> + <record model="crm.case.categ" id="categ_lead2"> <field name="name">Self Generated</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead3"> + <record model="crm.case.categ" id="categ_lead3"> <field name="name">Employee</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead4"> + <record model="crm.case.categ" id="categ_lead4"> <field name="name">Partner</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead6"> + <record model="crm.case.categ" id="categ_lead6"> <field name="name">Website</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead7"> + <record model="crm.case.categ" id="categ_lead7"> <field name="name">Word of mouth</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.categ" id="categ_lead8"> + <record model="crm.case.categ" id="categ_lead8"> <field name="name">Other</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> <!-- CASE STATUS(stage_id) --> - <record model="crm.lead.stage" id="stage_lead1"> + <record model="crm.case.stage" id="stage_lead1"> <field name="name">New</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.stage" id="stage_lead2"> + <record model="crm.case.stage" id="stage_lead2"> <field name="name">Assigned</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.stage" id="stage_lead3"> + <record model="crm.case.stage" id="stage_lead3"> <field name="name">In Process</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.stage" id="stage_lead4"> + <record model="crm.case.stage" id="stage_lead4"> <field name="name">Converted</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.stage" id="stage_lead5"> + <record model="crm.case.stage" id="stage_lead5"> <field name="name">Recycled</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.stage" id="stage_lead6"> + <record model="crm.case.stage" id="stage_lead6"> <field name="name">Dead</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> <!-- CASE CATEGORY2(category2_id) --> - <record model="crm.lead.type" id="type_lead1"> + <record model="crm.case.resource.type" id="type_lead1"> <field name="name">Telesales</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead2"> + <record model="crm.case.resource.type" id="type_lead2"> <field name="name">Mail</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead3"> + <record model="crm.case.resource.type" id="type_lead3"> <field name="name">Email</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead4"> + <record model="crm.case.resource.type" id="type_lead4"> <field name="name">Print</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead5"> + <record model="crm.case.resource.type" id="type_lead5"> <field name="name">Web</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead6"> + <record model="crm.case.resource.type" id="type_lead6"> <field name="name">Radio</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead7"> + <record model="crm.case.resource.type" id="type_lead7"> <field name="name">Television</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> - <record model="crm.lead.type" id="type_lead8"> + <record model="crm.case.resource.type" id="type_lead8"> <field name="name">Newsletter</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.lead')]" model="ir.model"/> </record> </data> 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 # ------------------------------------------------------ - - <record id="crm_lead_categ_view_form" model="ir.ui.view"> - <field name="name">crm.lead.categ.form</field> - <field name="model">crm.lead.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Lead Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_lead_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.lead.categ.tree</field> - <field name="model">crm.lead.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Lead Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> <record id="crm_lead_categ_action" model="ir.actions.act_window"> <field name="name">Lead Categories</field> - <field name="res_model">crm.lead.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_lead_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.lead')]</field> + <field name="context">{'object_id':'crm.lead'}</field> </record> <menuitem action="crm_lead_categ_action" id="menu_crm_case_lead-act" parent="crm.menu_crm_case_categ"/> # ------------------------------------------------------ # Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_lead_stage_tree"> - <field name="name">crm.lead.stage.tree</field> - <field name="model">crm.lead.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_lead_stage_form"> - <field name="name">crm.lead.stage.form</field> - <field name="model">crm.lead.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> <record id="crm_lead_stage_act" model="ir.actions.act_window"> <field name="name">Lead Stages</field> - <field name="res_model">crm.claim.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_lead_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.lead')]</field> + <field name="context">{'object_id':'crm.lead'}</field> </record> <menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act" parent="crm.menu_crm_case_stage"/> # ------------------------------------------------------ @@ -98,7 +53,7 @@ </group> <group colspan="2" col="4"> <field name="opportunity_id" string="Opportunity Case"/> - <button string="Convert to Opportunity" name="%(wizard_crm_lead_opportunity_set)d" icon="gtk-index" type="action"/> + <button string="Convert to Opportunity" name="%(wizard_crm_lead_opportunity_set)d" icon="gtk-index" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}"/> </group> <notebook colspan="4"> <page string="Leads"> diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py index bd93721be59..f6cf6faf439 100644 --- a/addons/crm/crm_meeting.py +++ b/addons/crm/crm_meeting.py @@ -19,407 +19,30 @@ # ############################################################################## -from caldav import common -from datetime import datetime, timedelta -from dateutil import parser from osv import fields, osv -from tools.translate import _ -import base64 -import re -import time -import tools -class crm_meeting_categ(osv.osv): - _name = "crm.meeting.categ" - _description = "Category of Meetings" - _columns = { - 'name': fields.char('Meeting Category Name', size=64, required=True, \ - translate=True), - 'probability': fields.float('Probability (%)', required=True), - 'section_id': fields.many2one('crm.case.section', 'Case Section'), - } - _defaults = { - 'probability': lambda *args: 0.0 - } -crm_meeting_categ() class crm_meeting(osv.osv): _name = 'crm.meeting' _description = "Meeting Cases" _order = "id desc" - _inherit = "crm.case" - - __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'}, - 'recurid': None, -# 'attach': {'field': 'attachment_ids', 'sub-field': 'datas', 'type': 'list'}, - '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 _get_duration(self, cr, uid, ids, name, arg, context): - res = {} - for meeting in self.browse(cr, uid, ids, context=context): - start = datetime.strptime(meeting.date, "%Y-%m-%d %H:%M:%S") - end = datetime.strptime(meeting.date_deadline[:19], "%Y-%m-%d %H:%M:%S") - diff = end - start - duration = float(diff.days)* 24 + (float(diff.seconds) / 3600) - res[meeting.id] = round(duration, 2) - return res - - def _set_duration(self, cr, uid, id, name, value, arg, context): - meeting = self.browse(cr, uid, id, context=context) - start = datetime.strptime(meeting.date, "%Y-%m-%d %H:%M:%S") - end = start + timedelta(hours=value) - cr.execute("UPDATE crm_meeting set date_deadline='%s' \ - where id=%s"% (end.strftime("%Y-%m-%d %H:%M:%S"), id)) - return True - - def onchange_rrule_type(self, cr, uid, ids, type, *args, **argv): - if type == 'none': - return {'value': {'rrule': ''}} - if type == 'custom': - return {} - rrule = self.pool.get('calendar.custom.rrule') - rrulestr = rrule.compute_rule_string(cr, uid, {'freq': type.upper(), \ - 'interval': 1}) - return {'value': {'rrule': rrulestr}} + _inherit = ["crm.case", "calendar.event"] _columns = { - 'id': fields.integer('ID', readonly=True), - 'name': fields.char('Description', size=64, required=True), - 'section_id': fields.many2one('crm.case.section', 'Section', select=True, help='Section to which Case belongs to. Define Responsible user and Email \ -account for mail gateway.'), 'priority': fields.selection([('5','Lowest'), - ('4','Low'), - ('3','Normal'), - ('2','High'), - ('1','Highest') - ], 'Priority'), - 'date': fields.datetime('Date'), - 'date_deadline': fields.datetime('Deadline'), - 'duration': fields.function(_get_duration, method=True, \ - fnct_inv=_set_duration, string='Duration'), - 'categ_id': fields.many2one('crm.meeting.categ', 'Category', \ - domain="[('section_id','=',section_id)]", \ + ('4','Low'), + ('3','Normal'), + ('2','High'), + ('1','Highest') + ], 'Priority'), + 'categ_id': fields.many2one('crm.case.categ', 'Category', \ + domain="[('section_id','=',section_id),\ + ('object_id.model', '=', 'crm.meeting')]", \ help='Category related to the section.Subdivide the CRM cases \ independently or section-wise.'), - 'description': fields.text('Your action'), - 'user_id': fields.many2one('res.users', 'Responsible'), - 'class': fields.selection([('public', 'Public'), ('private', 'Private'), \ - ('confidential', 'Confidential')], 'Mark as'), - 'location': fields.char('Location', size=264, help="Location of Meeting"), - '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'), - 'attendee_ids': fields.many2many('calendar.attendee', 'crm_attendee_rel', 'case_id', 'attendee_id', 'Attendees'), - 'alarm_id': fields.many2one('res.alarm', 'Alarm'), - 'caldav_alarm_id': fields.many2one('calendar.alarm', 'Alarm'), - } - - _defaults = { - 'class': lambda *a: 'public', - 'show_as': lambda *a: 'busy', + 'attendee_ids': fields.many2many('calendar.attendee', 'event_attendee_rel', 'event_id', 'attendee_id', 'Attendees'), } - def on_change_duration(self, cr, uid, id, date, duration): - if not date: - return {} - start_date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S") - if duration >= 0: - end = start_date + datetime.timedelta(hours=duration) - if duration < 0: - raise osv.except_osv(_('Warning !'), - _('You can not set negative Duration.')) - res = {'value': {'date_deadline': end.strftime('%Y-%m-%d %H:%M:%S')}} - return res - - def export_cal(self, cr, uid, ids, context={}): - ids = map(lambda x: common.caldav_id2real_id(x), ids) - crm_data = self.read(cr, uid, ids) - event_obj = self.pool.get('basic.calendar.event') - event_obj.__attribute__.update(self.__attribute__) - ical = event_obj.export_ical(cr, uid, crm_data, {'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_obj.__attribute__.update(self.__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: - is_exists = common.uid2openobjectid(cr, val['id'], self._name) - if val.has_key('create_date'): val.pop('create_date') - val['caldav_url'] = context.get('url') or '' - val.pop('id') - if is_exists: - self.write(cr, uid, [is_exists], val) - ids.append(is_exists) - else: - case_id = self.create(cr, uid, val) - ids.append(case_id) - return ids - - 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.exdate \ - from crm_meeting 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 = common.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 = common.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(crm_meeting, 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 = common.caldav_id2real_id(id) - if not id in new_ids: - new_ids.append(id) - res = super(crm_meeting, 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: common.caldav_id2real_id(x), select) - res = super(crm_meeting, 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, common.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(crm_meeting, self).read(cr, uid, real_id, fields=fields, context=context, \ - load=load) - ls = common.caldav_id2real_id(caldav_id, with_date=True) - if not isinstance(ls, (str, int, long)) and len(ls) >= 2: - res['date'] = ls[1] - 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(crm_meeting, self).copy(cr, uid, common.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 = common.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, [common.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, [common.caldav_id2real_id(id)], {'exdate': exdate}) - else: - ids = map(lambda x: common.caldav_id2real_id(x), ids) - res = super(crm_meeting, self).unlink(cr, uid, common.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: common.caldav_id2real_id(x), ids) - res = super(crm_meeting, 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(crm_meeting, 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 - - - def msg_new(self, cr, uid, msg): - mailgate_obj = self.pool.get('mail.gateway') - msg_body = mailgate_obj.msg_body_get(msg) - data = { - 'name': msg['Subject'], - 'email_from': msg['From'], - 'email_cc': msg['Cc'], - 'user_id': False, - 'description': msg_body['body'], - 'history_line': [(0, 0, {'description': msg_body['body'], 'email': msg['From'] })], - } - res = mailgate_obj.partner_get(cr, uid, msg['From']) - if res: - data.update(res) - res = self.create(cr, uid, data) - return res - crm_meeting() -class res_users(osv.osv): - _inherit = 'res.users' - def _get_user_avail(self, cr, uid, ids, context=None): - current_datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - res = super(res_users, self)._get_user_avail(cr, uid, ids, context) - cr.execute("SELECT m.user_id, 'busy' as status \ - FROM crm_meeting m\ - where m.date <= %s and m.date_deadline >= %s \ - and m.user_id = ANY(%s) and m.show_as = %s", - (current_datetime, current_datetime, ids, 'busy')) - result = cr.dictfetchall() - for user_data in result: - user_id = user_data['user_id'] - status = user_data['status'] - res.update({user_id:status}) - return res -res_users() - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_meeting_data.xml b/addons/crm/crm_meeting_data.xml index 1d727a72223..22b6d9ed29c 100644 --- a/addons/crm/crm_meeting_data.xml +++ b/addons/crm/crm_meeting_data.xml @@ -4,22 +4,26 @@ <!-- CASE CATEGORY(categ_id) --> - <record model="crm.meeting.categ" id="categ_meet1"> + <record model="crm.case.categ" id="categ_meet1"> <field name="name">Customer Meeting</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.meeting.categ" id="categ_meet2"> + <record model="crm.case.categ" id="categ_meet2"> <field name="name">Internal Meeting</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.fundraising')]" model="ir.model"/> </record> - <record model="crm.meeting.categ" id="categ_meet3"> + <record model="crm.case.categ" id="categ_meet3"> <field name="name">Phone Call</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.meeting')]" model="ir.model"/> </record> <record model="res.request.link" id="request_link_meeting"> <field name="name">Case Meeting</field> <field name="object">crm.meeting</field> + </record> </data> diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml index 58b4051f38a..b1b3c4b61f5 100644 --- a/addons/crm/crm_meeting_view.xml +++ b/addons/crm/crm_meeting_view.xml @@ -23,7 +23,7 @@ <field name="date_deadline" string="End Date" required="1" /> <field name="location" /> <field name="categ_id" widget="selection" /> - <group colspan="2" col="3"> + <group colspan="2" col="3" attrs="{'readonly':[('recurrent_uid','!=',False)]}"> <field name="rrule_type" string="Recurrency" on_change="onchange_rrule_type(rrule_type)" colspan="1" /> @@ -46,8 +46,7 @@ context="{'model' : 'crm.meeting'}" colspan="2"/> <field name="attendee_ids" colspan="4" nolabel="1" widget="one2many" mode="tree,form"> - <tree string="Atendee details" - editable="top"> + <tree string="Atendee details" editable="top"> <field name="email" /> <field name="role" select="1" /> <field name="state" /> @@ -63,7 +62,7 @@ <field name="state" /> </page> <page string="Other"> - <field name="user_id" select="1" /> + <field name="user_id"/> <field name="partner_address_id" select="1" /> <newline /> </page> @@ -76,9 +75,17 @@ <field name="show_as"/> <field name="class"/> <field name="user_id"/> - <field name="rrule" invisible="1"/> + <field name="recurrent_id" invisible="1" /> + <field name="recurrent_uid" invisible="1" /> + <field name="rrule" invisible="1" /> </page> </notebook> + <group col="3" colspan="4" attrs="{'invisible':[('rrule_type','in', ('none', False))]}"> + <label string="" /> + <button string="Modify this Occurrence" + name="%(caldav.wizard_edit_this_event)d" icon="gtk-save" + type="action" context="{'model' : 'crm.meeting'}" /> + </group> </form> </field> </record> diff --git a/addons/crm/crm_meeting_wizard.xml b/addons/crm/crm_meeting_wizard.xml index 8fb19bd622a..f4fba30056e 100644 --- a/addons/crm/crm_meeting_wizard.xml +++ b/addons/crm/crm_meeting_wizard.xml @@ -1,17 +1,18 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - <wizard string="Import ICS File" model="crm.meeting" - name="caldav.crm.import" id="wizard_crm_cal_import" multi="True" - /> - - <wizard string="Subscribe to a Remote calendar" model="crm.meeting" - name="caldav.crm.subscribe" id="wizard_crm_cal_subscribe" multi="True" - /> - - <wizard string="Export ICS File" model="crm.meeting" name="caldav.crm.export" - id="wizard_crm_cal_export" multi="True" - /> + <wizard string="Import .ics File" model="crm.meeting" + name="caldav.event.import" id="caldav.wizard_cal_event_import" multi="True" /> + <wizard string="Subscribe to a Remote calendar" + model="crm.meeting" name="caldav.event.subscribe" + id="caldav.wizard_cal_event_subscribe" multi="True" /> + + <wizard string="Export .ics File" model="crm.meeting" + name="caldav.event.export" id="caldav.wizard_cal_event_export" multi="True" /> + + <wizard string="Edit this event" model="crm.meeting" + name="calendar.event.edit.this" id="caldav.wizard_edit_this_event" + menu="False" /> </data> </openerp> diff --git a/addons/crm/crm_opportunity.py b/addons/crm/crm_opportunity.py index d0db5e3d614..35a85cad6ee 100644 --- a/addons/crm/crm_opportunity.py +++ b/addons/crm/crm_opportunity.py @@ -34,43 +34,6 @@ from osv.orm import except_orm import crm -class crm_opportunity_categ(osv.osv): - _name = "crm.opportunity.categ" - _description = "Opportunity 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_opportunity_categ() - -class crm_opportunity_type(osv.osv): - _name = "crm.opportunity.type" - _description = "Opportunity 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_opportunity_type() - -class crm_opportunity_stage(osv.osv): - _name = "crm.opportunity.stage" - _description = "Stage of opportunity 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_opportunity_stage() class crm_opportunity(osv.osv): _name = "crm.opportunity" @@ -78,9 +41,9 @@ class crm_opportunity(osv.osv): _order = "id desc" _inherit = 'crm.case' _columns = { - 'stage_id': fields.many2one ('crm.opportunity.stage', 'Stage', domain="[('section_id','=',section_id)]"), - 'categ_id': fields.many2one('crm.opportunity.categ', 'Category', domain="[('section_id','=',section_id)]"), - 'type_id': fields.many2one('crm.opportunity.type', 'Opportunity Type', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Resource Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.opportunity')]"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), 'probability': fields.float('Probability (%)'), 'planned_revenue': fields.float('Planned Revenue'), @@ -98,7 +61,7 @@ class crm_opportunity(osv.osv): def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.opportunity.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_opportunity() diff --git a/addons/crm/crm_opportunity_data.xml b/addons/crm/crm_opportunity_data.xml index bc08064ab92..b3780990a13 100644 --- a/addons/crm/crm_opportunity_data.xml +++ b/addons/crm/crm_opportunity_data.xml @@ -1,77 +1,94 @@ <?xml version="1.0"?> <openerp> <data noupdate="1"> - <record model="crm.opportunity.categ" id="categ_oppor1"> + <record model="crm.case.categ" id="categ_oppor1"> <field name="name">Existing Customer</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor2"> + <record model="crm.case.categ" id="categ_oppor2"> <field name="name">Self Generated</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor3"> + <record model="crm.case.categ" id="categ_oppor3"> <field name="name">Employee</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor4"> + <record model="crm.case.categ" id="categ_oppor4"> <field name="name">Partner</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor5"> + <record model="crm.case.categ" id="categ_oppor5"> <field name="name">Campaign</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor6"> + <record model="crm.case.categ" id="categ_oppor6"> <field name="name">Website</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor7"> + <record model="crm.case.categ" id="categ_oppor7"> <field name="name">Word of mouth</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.categ" id="categ_oppor8"> + <record model="crm.case.categ" id="categ_oppor8"> <field name="name">Other</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> <!-- CASE STATUS(stage_id) --> - <record model="crm.opportunity.stage" id="stage_oppor1"> + <record model="crm.case.stage" id="stage_oppor1"> <field name="name">Prospecting</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor2"> + <record model="crm.case.stage" id="stage_oppor2"> <field name="name">Needs Analysis</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor3"> + <record model="crm.case.stage" id="stage_oppor3"> <field name="name">Value Proposition</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor4"> + <record model="crm.case.stage" id="stage_oppor4"> <field name="name">Proposal/Price Quote</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor5"> + <record model="crm.case.stage" id="stage_oppor5"> <field name="name">Negotiation/Review</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor6"> + <record model="crm.case.stage" id="stage_oppor6"> <field name="name">Closed Won</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.stage" id="stage_oppor7"> + <record model="crm.case.stage" id="stage_oppor7"> <field name="name">Closed Lost</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> -<!-- CASE CATEGORY2(category2_id) --> - <record model="crm.opportunity.type" id="type_oppor1"> +<!-- Case Resource(type_id) --> + <record model="crm.case.resource.type" id="type_oppor1"> <field name="name">Existing Business</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> - <record model="crm.opportunity.type" id="type_oppor2"> + <record model="crm.case.resource.type" id="type_oppor2"> <field name="name">New Business</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.opportunity')]" model="ir.model"/> </record> </data> diff --git a/addons/crm/crm_opportunity_view.xml b/addons/crm/crm_opportunity_view.xml index 4a0273c372a..d8fcf059254 100644 --- a/addons/crm/crm_opportunity_view.xml +++ b/addons/crm/crm_opportunity_view.xml @@ -5,73 +5,26 @@ # ------------------------------------------------------ # Opportunity Categories # ------------------------------------------------------ - - <record id="crm_opportunity_categ_view_form" model="ir.ui.view"> - <field name="name">crm.opportunity.categ.form</field> - <field name="model">crm.opportunity.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Opportunity Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_opportunity_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.opportunity.categ.tree</field> - <field name="model">crm.opportunity.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Opportunity Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> <record id="crm_opportunity_categ_action" model="ir.actions.act_window"> <field name="name">Opportunity Categories</field> - <field name="res_model">crm.opportunity.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_opportunity_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.opportunity')]</field> + <field name="context">{'object_id':'crm.opportunity'}</field> </record> <menuitem action="crm_opportunity_categ_action" id="menu_crm_case_opportunity-act" parent="crm.menu_crm_case_categ"/> # ------------------------------------------------------ # Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_opportunity_stage_tree"> - <field name="name">crm.opportunity.stage.tree</field> - <field name="model">crm.opportunity.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - - <record model="ir.ui.view" id="crm_opportunity_stage_form"> - <field name="name">crm.opportunity.stage.form</field> - <field name="model">crm.opportunity.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> - <record id="crm_opportunity_stage_act" model="ir.actions.act_window"> <field name="name">Opportunity Stages</field> - <field name="res_model">crm.claim.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_opportunity_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.opportunity')]</field> + <field name="context">{'object_id':'crm.opportunity'}</field> </record> <menuitem action="crm_opportunity_stage_act" id="menu_crm_opportunity_stage_act" parent="crm.menu_crm_case_stage"/> # ------------------------------------------------------ @@ -103,7 +56,7 @@ <field name="phonecall_id" select="1"/> </group> <button string="Schedule a Phone Call" - name="%(wizard_crm_opportunity_reschedule_phone_call)d" icon="gtk-redo" type="action" /> + name="%(wizard_crm_opportunity_reschedule_phone_call)d" icon="gtk-redo" type="action" attrs="{'invisible':[('phonecall_id','!=',False)]}" /> </group> <notebook colspan="4"> <page string="Description"> diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py index b9a2d198144..1a0c4c1b78d 100644 --- a/addons/crm/crm_phonecall.py +++ b/addons/crm/crm_phonecall.py @@ -32,33 +32,6 @@ from tools.translate import _ import crm -class crm_phonecall_categ(osv.osv): - _name = "crm.phonecall.categ" - _description = "Phonecall 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_phonecall_categ() - -class crm_phonecall_stage(osv.osv): - _name = "crm.phonecall.stage" - _description = "Stage of phonecal 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_phonecall_stage() class crm_phonecall(osv.osv): _name = "crm.phonecall" @@ -67,7 +40,7 @@ class crm_phonecall(osv.osv): _inherit = 'crm.case' _columns = { 'duration': fields.float('Duration'), - 'categ_id': fields.many2one('crm.phonecall.categ', 'Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.phonecall')]"), 'partner_phone': fields.char('Phone', size=32), 'partner_mobile': fields.char('Mobile', size=32), 'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \ @@ -84,7 +57,7 @@ class crm_phonecall(osv.osv): def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.phonecall.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_phonecall() diff --git a/addons/crm/crm_phonecall_data.xml b/addons/crm/crm_phonecall_data.xml index a7444ad0b1e..49d02f8848e 100644 --- a/addons/crm/crm_phonecall_data.xml +++ b/addons/crm/crm_phonecall_data.xml @@ -6,29 +6,35 @@ <!-- Phonecall Categories --> - <record model="crm.phonecall.categ" id="categ_phone1"> + <record model="crm.case.categ" id="categ_phone1"> <field name="name">Inbound</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.phonecall')]" model="ir.model"/> + </record> - <record model="crm.phonecall.categ" id="categ_phone2"> + <record model="crm.case.categ" id="categ_phone2"> <field name="name">Outbound</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.phonecall')]" model="ir.model"/> </record> <!-- Case Stage --> - <record model="crm.phonecall.stage" id="stage_phone1"> + <record model="crm.case.stage" id="stage_phone1"> <field name="name">Planned</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.phonecall')]" model="ir.model"/> </record> - <record model="crm.phonecall.stage" id="stage_phone2"> + <record model="crm.case.stage" id="stage_phone2"> <field name="name">Held</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.phonecall')]" model="ir.model"/> </record> - <record model="crm.phonecall.stage" id="stage_phone3"> + <record model="crm.case.stage" id="stage_phone3"> <field name="name">Not Held</field> <field name="section_id" ref="section_sales_department"/> + <field name="object_id" search="[('model','=','crm.phonecall')]" model="ir.model"/> </record> </data> </openerp>
\ No newline at end of file diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml index b10ff4fe7db..606b8d81b8e 100644 --- a/addons/crm/crm_phonecall_view.xml +++ b/addons/crm/crm_phonecall_view.xml @@ -5,72 +5,27 @@ # ------------------------------------------------------ # Phonecall Categories # ------------------------------------------------------ - - <record id="crm_phonecall_categ_view_form" model="ir.ui.view"> - <field name="name">crm.phonecall.categ.form</field> - <field name="model">crm.phonecall.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Phonecall Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_phonecall_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.phonecall.categ.tree</field> - <field name="model">crm.phonecall.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Phonecall Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> - + <record id="crm_phonecall_categ_action" model="ir.actions.act_window"> <field name="name">Phonecall Categories</field> - <field name="res_model">crm.phonecall.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_phonecall_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field> + <field name="context">{'object_id':'crm.phonecall'}</field> </record> <menuitem action="crm_phonecall_categ_action" id="menu_crm_case_phonecall-act" parent="crm.menu_crm_case_categ"/> # ------------------------------------------------------ # Fund Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_phonecall_stage_tree"> - <field name="name">crm.phonecall.stage.tree</field> - <field name="model">crm.phonecall.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_phonecall_stage_form"> - <field name="name">crm.phonecall.stage.form</field> - <field name="model">crm.phonecall.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> <record id="crm_phonecall_stage_act" model="ir.actions.act_window"> <field name="name">Phonecall Stages</field> - <field name="res_model">crm.phonecall.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_phonecall_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field> + <field name="context">{'object_id':'crm.phonecall'}</field> </record> <menuitem action="crm_phonecall_stage_act" id="menu_crm_phonecall_stage_act" parent="crm.menu_crm_case_stage"/> @@ -90,7 +45,7 @@ <field name="partner_id" string="Partner"/> <field name="partner_address_id" string="Contact"/> <field name="opportunity_id"/> - <button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action"/> + <button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" /> <button string="Meeting" name="%(wizard_crm_phonecall_meeting_set)d" type="action" /> </tree> @@ -109,7 +64,7 @@ <field name="partner_address_id" string="Contact"/> <group col="2"> <field name="opportunity_id"/> - <button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action"/> + <button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" /> <button string="Meeting" name="%(wizard_crm_phonecall_meeting_set)d" type="action" /> </group> @@ -127,7 +82,7 @@ <field name="name" string="Subject"/> <field name="section_id" colspan="1" widget="selection"/> <field name="user_id" string="Assigned to" select="2"/> - <button string="Convert to Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" icon="gtk-index" type="action"/> + <button string="Convert to Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" icon="gtk-index" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" /> <newline/> <field name="date" string="Planned Date"/> <field name="duration"/> @@ -147,7 +102,7 @@ <field name="active" string="Reminder"/> <group colspan="2" col="3"> <field name="partner_id" string="Partner"/> - <button string="Convert to Partner" icon="terp-crm" name="%(wizard_crm_phonecall_partner_create)d" type="action" attrs="{'invisible':[('partner_id','!=',False)]}"/> + <button string="Convert to Partner" icon="terp-crm" name="%(wizard_crm_phonecall_partner_create)d" type="action" attrs="{'invisible':[('partner_id','!=',False)]}" /> </group> <field name="partner_address_id" string="Contact"/> <field name="partner_phone"/> diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index b6d16c2fcbd..02a2984a0a2 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -47,8 +47,76 @@ <field name="view_type">form</field> <field name="view_id" ref="crm_case_section_view_tree"/> </record> -<menuitem id="menu_crm_case_stage" name="Stages" parent="crm.menu_crm_configuration"/> -<menuitem id="menu_crm_case_categ" name="Categories" parent="crm.menu_crm_configuration"/> + + # ------------------------------------------------------ + # Stage + # ------------------------------------------------------ + <record model="ir.ui.view" id="crm_case_stage_tree"> + <field name="name">crm.case.stage.tree</field> + <field name="model">crm.case.stage</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Stages"> + <field name="sequence"/> + <field name="name"/> + <field name="section_id"/> + </tree> + </field> + </record> + <record model="ir.ui.view" id="crm_case_stage_form"> + <field name="name">crm.case.stage.form</field> + <field name="model">crm.case.stage</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Stage"> + <field name="name" select="1"/> + <field name="section_id" select="1" widget="selection"/> + <field name="object_id" invisible="1" /> + <field name="sequence"/> + </form> + </field> + </record> + <record id="crm_case_stage_act" model="ir.actions.act_window"> + <field name="name">Stages</field> + <field name="res_model">crm.case.stage</field> + <field name="view_type">form</field> + <field name="view_id" ref="crm_case_stage_tree"/> + </record> + <menuitem id="menu_crm_case_stage" name="Stages" parent="crm.menu_crm_configuration"/> + <!-- Case Categories --> + <record id="crm_case_categ-view" model="ir.ui.view"> + <field name="name">crm.case.categ.form</field> + <field name="model">crm.case.categ</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Case Category"> + <field name="name" select="1"/> + <field name="section_id" select="1" widget="selection"/> + <field name="object_id" invisible="1" /> + <field name="probability"/> + </form> + </field> + </record> + <record id="crm_case_categ_tree-view" model="ir.ui.view"> + <field name="name">crm.case.categ.tree</field> + <field name="model">crm.case.categ</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Case Category"> + <field name="name"/> + <field name="section_id"/> + <field name="probability"/> + </tree> + </field> + </record> + + <record id="crm_case_categ-act" model="ir.actions.act_window"> + <field name="name">Categories</field> + <field name="res_model">crm.case.categ</field> + <field name="view_type">form</field> + <field name="view_id" ref="crm_case_categ_tree-view"/> + </record> + <menuitem id="menu_crm_case_categ" name="Categories" parent="crm.menu_crm_configuration"/> <menuitem action="crm_case_section_act" id="menu_crm_case_section_act" parent="crm.menu_crm_configuration"/> diff --git a/addons/crm/i18n/pt_BR.po b/addons/crm/i18n/pt_BR.po index f0b4b427d5e..239a052b437 100644 --- a/addons/crm/i18n/pt_BR.po +++ b/addons/crm/i18n/pt_BR.po @@ -1,31 +1,31 @@ # Translation of OpenERP Server. # This file contains the translation of the following modules: -# * crm +# * crm # msgid "" msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2010-01-05 05:59:11+0000\n" -"PO-Revision-Date: 2010-01-05 17:04+0000\n" -"Last-Translator: Pedro_Maschio <pedro.bicudo@tgtconsult.com.br>\n" +"POT-Creation-Date: 2010-01-05 05:59+0000\n" +"PO-Revision-Date: 2010-01-20 01:33+0000\n" +"Last-Translator: pedrobom <pedrobomlimeira@gmail.com>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2009-12-16 05:08+0000\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: crm #: field:crm.email.add.cc,name:0 msgid "Send to" -msgstr "" +msgstr "Enviar para" #. module: crm #: help:crm.meeting,exdate:0 msgid "" -"This property defines the list of date/time exceptions for arecurring " -"calendar component." +"This property defines the list of date/time exceptions for " +"arecurring calendar component." msgstr "" #. module: crm @@ -33,11 +33,13 @@ msgstr "" msgid "" "Check this if you want the rule to send an email to the responsible person." msgstr "" +"Marque isto se você quiser que a regra envie um email para a pessoa " +"responsável." #. module: crm #: view:crm.meeting:0 msgid "Title" -msgstr "" +msgstr "Título" #. module: crm #: model:ir.model,name:crm.model_report_crm_case_section_categ2 @@ -50,9 +52,12 @@ msgid "Close Lead" msgstr "" #. module: crm -#: view:crm.job:0 view:crm.lead:0 view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 msgid " 7 Days " -msgstr "" +msgstr " 7 Dias " #. module: crm #: help:crm.menu.config_wizard,helpdesk:0 @@ -62,12 +67,12 @@ msgstr "" #. module: crm #: view:crm.job:0 msgid "Pending Jobs" -msgstr "" +msgstr "Serviços Pendentes" #. module: crm #: field:crm.case.rule,trg_state_to:0 msgid "Button Pressed" -msgstr "Butão pressionado" +msgstr "Botão pressionado" #. module: crm #: view:crm.case:0 @@ -85,7 +90,8 @@ msgid "Stage Name" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.case.history:0 +#: view:crm.case:0 +#: view:crm.case.history:0 #: model:ir.actions.act_window,name:crm.crm_case_categ0-act #: model:ir.actions.act_window,name:crm.crm_case_section_open_act #: model:ir.ui.menu,name:crm.menu_crm_case_categ0-act @@ -122,7 +128,7 @@ msgstr "" #. module: crm #: view:crm.fundraising:0 msgid "Amount" -msgstr "" +msgstr "Quantia" #. module: crm #: model:process.transition,note:crm.process_transition_opportunitymeeting0 @@ -136,12 +142,13 @@ msgid "Fixed" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 code:addons/crm/wizard/crm_job_wizard.py:0 +#: code:addons/crm/crm.py:0 +#: code:addons/crm/wizard/crm_job_wizard.py:0 #: code:addons/crm/wizard/crm_lead_wizard.py:0 #: code:addons/crm/wizard/crm_phonecall_wizard.py:0 #, python-format msgid "Warning !" -msgstr "" +msgstr "Atenção !" #. module: crm #: code:addons/crm/wizard/wizard_crm_new_send_email.py:0 @@ -152,29 +159,29 @@ msgstr "" #. module: crm #: model:crm.case.categ,name:crm.categ_oppor5 msgid "Campaign" -msgstr "" +msgstr "Campanha" #. module: crm #: view:crm.opportunity:0 msgid "Search Opportunities" -msgstr "" +msgstr "Procura Oportunidades" #. module: crm #: model:ir.ui.menu,name:crm.menu_crm_case_section_stage_tree #: view:report.crm.case.section.stage:0 msgid "Cases by Section and Stage" -msgstr "" +msgstr "Casos por Seção e Estágio" #. module: crm #: wizard_field:crm.job.meeting_set,init,duration:0 #: wizard_field:crm.phonecall.meeting_set,init,duration:0 msgid "Duration (Hours)" -msgstr "" +msgstr "Duração (Horas)" #. module: crm #: selection:crm.meeting,transparent:0 msgid "TRANSPARENT" -msgstr "" +msgstr "TRANSPARENTE" #. module: crm #: help:crm.case.rule,server_action_id:0 @@ -191,15 +198,18 @@ msgid "" msgstr "" #. module: crm -#: view:crm.case:0 field:crm.case,partner_id:0 +#: view:crm.case:0 +#: field:crm.case,partner_id:0 #: model:crm.case.categ,name:crm.categ_lead4 #: model:crm.case.categ,name:crm.categ_oppor4 #: wizard_field:crm.case.opportunity.partner_opportunity,init,partner_id:0 -#: field:crm.case.rule,trg_partner_id:0 selection:crm.email.add.cc,name:0 +#: field:crm.case.rule,trg_partner_id:0 +#: selection:crm.email.add.cc,name:0 #: field:crm.email.add.cc,partner_id:0 #: wizard_field:crm.lead.opportunity_set,create_partner,partner_id:0 #: wizard_field:crm.lead.opportunity_set,opportunity,partner_id:0 -#: view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 #: wizard_field:crm.phonecall.opportunity_set,create_partner,partner_id:0 #: wizard_field:crm.phonecall.opportunity_set,opportunity,partner_id:0 #: model:process.node,name:crm.process_node_partner0 @@ -207,8 +217,10 @@ msgid "Partner" msgstr "Parceiro" #. module: crm -#: field:crm.case.categ,section_id:0 field:crm.case.category2,section_id:0 -#: view:crm.case.section:0 field:crm.case.section,name:0 +#: field:crm.case.categ,section_id:0 +#: field:crm.case.category2,section_id:0 +#: view:crm.case.section:0 +#: field:crm.case.section,name:0 #: field:crm.case.stage,section_id:0 #: model:ir.model,name:crm.model_crm_case_section msgid "Case Section" @@ -217,7 +229,7 @@ msgstr "Seção de caso" #. module: crm #: view:crm.job:0 msgid "Proposed Salary" -msgstr "" +msgstr "Salário proposto" #. module: crm #: help:crm.case.section,sequence:0 @@ -230,12 +242,12 @@ msgstr "" #: model:crm.case.categ,name:crm.categ_meet3 #, python-format msgid "Phone Call" -msgstr "" +msgstr "Ligação Telefônica" #. module: crm #: model:ir.model,name:crm.model_report_crm_case_section_stage msgid "Cases by section and stage" -msgstr "" +msgstr "Casos por seção e estágio" #. module: crm #: field:crm.case.rule,act_mail_to_email:0 @@ -253,10 +265,14 @@ msgid "Special Keywords to Be Used in The Body" msgstr "Palavras-chave especiais a serem utilizadas no corpo" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Send New Email" -msgstr "" +msgstr "Envia Novo Email" #. module: crm #: view:crm.case.history:0 @@ -317,8 +333,12 @@ msgid "Warning!" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Dates" msgstr "Datas" @@ -333,7 +353,8 @@ msgid "Prospect Partner" msgstr "" #. module: crm -#: view:crm.fundraising:0 view:crm.opportunity:0 +#: view:crm.fundraising:0 +#: view:crm.opportunity:0 msgid "Description Information" msgstr "" @@ -354,8 +375,12 @@ msgid "Delay type" msgstr "Tipo de atraso" #. module: crm -#: view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 view:crm.lead:0 -#: view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 msgid "Contact" msgstr "" @@ -444,7 +469,8 @@ msgid "Home" msgstr "" #. module: crm -#: field:crm.case,categ_id:0 field:crm.case.rule,trg_categ_id:0 +#: field:crm.case,categ_id:0 +#: field:crm.case.rule,trg_categ_id:0 #: wizard_field:crm.job.reschedule_phone_call,init,category_id:0 #: view:crm.opportunity:0 #: wizard_field:crm.opportunity.reschedule_phone_call,init,category_id:0 @@ -479,8 +505,12 @@ msgid "%(partner)s = Partner name" msgstr "%(parceiro)s = Nome do Parceiro" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Action Information" msgstr "Informação da ação" @@ -513,7 +543,9 @@ msgid "Open Cases" msgstr "Casos abertos" #. module: crm -#: field:crm.case.log,name:0 view:crm.claim:0 view:crm.job:0 +#: field:crm.case.log,name:0 +#: view:crm.claim:0 +#: view:crm.job:0 msgid "Status" msgstr "Situação" @@ -541,10 +573,13 @@ msgid "Meetings Tree" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 view:crm.case:0 +#: code:addons/crm/crm.py:0 +#: view:crm.case:0 #: selection:crm.case.rule,trg_state_from:0 -#: selection:crm.case.rule,trg_state_to:0 view:crm.fundraising:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: selection:crm.case.rule,trg_state_to:0 +#: view:crm.fundraising:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 #, python-format msgid "Escalate" msgstr "Escalada" @@ -627,7 +662,10 @@ msgid "Allows to show calendar" msgstr "" #. module: crm -#: view:crm.job:0 view:crm.lead:0 view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 msgid " Today " msgstr "" @@ -665,6 +703,8 @@ msgstr "" msgid "" "You must define a responsible user for this case in order to use this action!" msgstr "" +"Você deve definir um usuário responsável para este caso se quiser usar esta " +"ação!" #. module: crm #: view:crm.phonecall:0 @@ -687,7 +727,10 @@ msgid "Jobs - Hiring Process" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Related Cases" msgstr "" @@ -700,8 +743,12 @@ msgid "September" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Communication history" msgstr "Histórico" @@ -752,7 +799,8 @@ msgid "Leads Form" msgstr "" #. module: crm -#: view:crm.segmentation:0 model:ir.model,name:crm.model_crm_segmentation +#: view:crm.segmentation:0 +#: model:ir.model,name:crm.model_crm_segmentation msgid "Partner Segmentation" msgstr "Segmentação de parceiros" @@ -772,7 +820,8 @@ msgid "Existing Business" msgstr "" #. module: crm -#: field:crm.case,probability:0 field:crm.case.categ,probability:0 +#: field:crm.case,probability:0 +#: field:crm.case.categ,probability:0 msgid "Probability (%)" msgstr "Probabilidade (%)" @@ -791,7 +840,8 @@ msgstr "" "todos os e-mails enviados sobre casos desta seção" #. module: crm -#: view:crm.case.rule:0 model:ir.model,name:crm.model_crm_case_rule +#: view:crm.case.rule:0 +#: model:ir.model,name:crm.model_crm_case_rule msgid "Case Rule" msgstr "Regra do caso" @@ -799,7 +849,8 @@ msgstr "Regra do caso" #: code:addons/crm/crm_opportunity.py:0 #: code:addons/crm/wizard/crm_lead_wizard.py:0 #: code:addons/crm/wizard/crm_opportunity_wizard.py:0 -#: code:addons/crm/wizard/crm_phonecall_wizard.py:0 view:crm.opportunity:0 +#: code:addons/crm/wizard/crm_phonecall_wizard.py:0 +#: view:crm.opportunity:0 #: view:crm.phonecall:0 #: model:ir.ui.menu,name:crm.menu_action_report_crm_case_oppor #, python-format @@ -807,8 +858,12 @@ msgid "Opportunity" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Emails" msgstr "" @@ -924,7 +979,8 @@ msgid "Gives the sequence order when displaying a list of case stages." msgstr "" #. module: crm -#: model:crm.case.section,name:crm.section_support3 view:crm.opportunity:0 +#: model:crm.case.section,name:crm.section_support3 +#: view:crm.opportunity:0 #: model:ir.ui.menu,name:crm.menu_crm_case_opp #: model:process.node,name:crm.process_node_opportunities0 msgid "Opportunities" @@ -957,7 +1013,8 @@ msgid "Direction" msgstr "" #. module: crm -#: help:crm.case,email_cc:0 help:crm.case.rule,act_email_cc:0 +#: help:crm.case,email_cc:0 +#: help:crm.case.rule,act_email_cc:0 msgid "" "These people will receive a copy of the future communication between partner " "and users by email" @@ -1030,7 +1087,8 @@ msgid "Mobile" msgstr "" #. module: crm -#: field:crm.case.rule,name:0 field:crm.segmentation.line,name:0 +#: field:crm.case.rule,name:0 +#: field:crm.segmentation.line,name:0 msgid "Rule Name" msgstr "Nome da Regra" @@ -1075,8 +1133,10 @@ msgid "Export ICS" msgstr "" #. module: crm -#: code:addons/crm/crm_claim.py:0 code:addons/crm/crm_helpdesk.py:0 -#: code:addons/crm/crm_meeting.py:0 code:addons/crm/crm_opportunity.py:0 +#: code:addons/crm/crm_claim.py:0 +#: code:addons/crm/crm_helpdesk.py:0 +#: code:addons/crm/crm_meeting.py:0 +#: code:addons/crm/crm_opportunity.py:0 #: code:addons/crm/crm_phonecall.py:0 #, python-format msgid "You can not assign Closed Case." @@ -1091,9 +1151,11 @@ msgstr "" "parceiro." #. module: crm -#: code:addons/crm/crm_meeting.py:0 code:addons/crm/wizard/crm_job_wizard.py:0 +#: code:addons/crm/crm_meeting.py:0 +#: code:addons/crm/wizard/crm_job_wizard.py:0 #: code:addons/crm/wizard/crm_phonecall_wizard.py:0 -#: model:crm.case.section,name:crm.section_support1 view:crm.meeting:0 +#: model:crm.case.section,name:crm.section_support1 +#: view:crm.meeting:0 #, python-format msgid "Meetings" msgstr "" @@ -1109,8 +1171,10 @@ msgid "Next Action" msgstr "Próxima ação" #. module: crm -#: view:crm.case:0 field:crm.case,date_deadline:0 -#: selection:crm.case.rule,trg_date_type:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: field:crm.case,date_deadline:0 +#: selection:crm.case.rule,trg_date_type:0 +#: view:crm.opportunity:0 msgid "Deadline" msgstr "Prazo final" @@ -1142,8 +1206,10 @@ msgid "Category of case" msgstr "Categorias de casos" #. module: crm -#: field:crm.email.add.cc,subject:0 view:crm.meeting:0 -#: wizard_field:crm.new.send.mail,init,subject:0 view:crm.phonecall:0 +#: field:crm.email.add.cc,subject:0 +#: view:crm.meeting:0 +#: wizard_field:crm.new.send.mail,init,subject:0 +#: view:crm.phonecall:0 #: wizard_field:crm.send.mail,init,subject:0 msgid "Subject" msgstr "" @@ -1238,13 +1304,15 @@ msgid "Print" msgstr "" #. module: crm -#: field:crm.case,som:0 field:crm.case.log,som:0 +#: field:crm.case,som:0 +#: field:crm.case.log,som:0 #: selection:crm.segmentation.line,expr_name:0 msgid "State of Mind" msgstr "Estado emocional" #. module: crm -#: view:crm.claim:0 view:crm.meeting:0 +#: view:crm.claim:0 +#: view:crm.meeting:0 #: field:report.crm.case.section.categ.categ2,category2_id:0 #: field:report.crm.case.section.categ2,category2_id:0 msgid "Type" @@ -1279,7 +1347,8 @@ msgid "Creation Date" msgstr "Data de Criação" #. module: crm -#: view:crm.meeting:0 view:crm.phonecall:0 +#: view:crm.meeting:0 +#: view:crm.phonecall:0 #: model:process.node,name:crm.process_node_meeting0 msgid "Meeting" msgstr "" @@ -1290,8 +1359,13 @@ msgid "%(partner_email)s = Partner email" msgstr "%(partner_email)s = Email do Parceiro" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 msgid "Reset to Draft" msgstr "Restaurar para esboço" @@ -1315,7 +1389,8 @@ msgid "Open cases" msgstr "Casos abertos" #. module: crm -#: field:crm.case,stage_id:0 view:crm.case.stage:0 +#: field:crm.case,stage_id:0 +#: view:crm.case.stage:0 #: field:report.crm.case.section.categ.categ2,stage_id:0 #: field:report.crm.case.section.categ.stage,stage_id:0 #: field:report.crm.case.section.categ2,stage_id:0 @@ -1366,7 +1441,9 @@ msgid "Meeting Date" msgstr "" #. module: crm -#: view:crm.job:0 view:crm.lead:0 view:crm.phonecall:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.phonecall:0 msgid "Convert to Partner" msgstr "" @@ -1384,7 +1461,7 @@ msgstr "ID do maior parceiro processado" #: code:addons/crm/crm.py:0 #, python-format msgid "You can not delete this case. You should better cancel it." -msgstr "" +msgstr "Você não pode excluir este caso. O melhor é você cancelá-lo." #. module: crm #: wizard_button:caldav.crm.subscribe,init,open:0 @@ -1425,10 +1502,11 @@ msgstr "" #: code:addons/crm/crm.py:0 #, python-format msgid "done" -msgstr "" +msgstr "concluído" #. module: crm -#: view:crm.meeting:0 view:crm.phonecall:0 +#: view:crm.meeting:0 +#: view:crm.phonecall:0 msgid "Reminder" msgstr "" @@ -1445,7 +1523,7 @@ msgstr "" #: code:addons/crm/crm.py:0 #, python-format msgid "open" -msgstr "" +msgstr "Abrir" #. module: crm #: field:crm.case.rule,act_remind_attach:0 @@ -1484,7 +1562,7 @@ msgstr "" #: code:addons/crm/crm.py:0 #, python-format msgid "draft" -msgstr "" +msgstr "esboço" #. module: crm #: model:crm.case.stage,name:crm.stage_claim5 @@ -1493,8 +1571,10 @@ msgid "Awaiting Response" msgstr "" #. module: crm -#: field:crm.case,date:0 field:crm.case.log,date:0 -#: selection:crm.case.rule,trg_date_type:0 view:crm.claim:0 +#: field:crm.case,date:0 +#: field:crm.case.log,date:0 +#: selection:crm.case.rule,trg_date_type:0 +#: view:crm.claim:0 #: view:crm.phonecall:0 msgid "Date" msgstr "Data" @@ -1521,8 +1601,12 @@ msgid "Converted" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Reply to Last Email" msgstr "" @@ -1537,8 +1621,12 @@ msgid "Gives Location of Meeting" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "History" msgstr "Histórico" @@ -1558,7 +1646,8 @@ msgid "Regular Expression on Case Name" msgstr "" #. module: crm -#: field:crm.case,state:0 field:report.crm.case.section.categ.categ2,state:0 +#: field:crm.case,state:0 +#: field:report.crm.case.section.categ.categ2,state:0 #: field:report.crm.case.section.categ.stage,state:0 #: field:report.crm.case.section.categ2,state:0 #: field:report.crm.case.section.stage,state:0 @@ -1571,27 +1660,36 @@ msgid "Send Reminder" msgstr "Enviar lembrete" #. module: crm -#: view:crm.case:0 view:crm.fundraising:0 view:crm.job:0 view:crm.lead:0 +#: view:crm.case:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 #: view:crm.opportunity:0 msgid "References" msgstr "Referências" #. module: crm -#: code:addons/crm/crm.py:0 view:crm.case:0 +#: code:addons/crm/crm.py:0 +#: view:crm.case:0 #: wizard_button:crm.case.opportunity.partner_opportunity,init,end:0 -#: view:crm.claim:0 view:crm.claim.assign_wizard:0 view:crm.fundraising:0 +#: view:crm.claim:0 +#: view:crm.claim.assign_wizard:0 +#: view:crm.fundraising:0 #: view:crm.helpdesk.assign_wizard:0 #: wizard_button:crm.job.meeting_set,init,end:0 #: wizard_button:crm.job.partner_create,init,end:0 -#: wizard_button:crm.job.reschedule_phone_call,init,end:0 view:crm.lead:0 +#: wizard_button:crm.job.reschedule_phone_call,init,end:0 +#: view:crm.lead:0 #: wizard_button:crm.lead.opportunity_set,create_partner,end:0 #: wizard_button:crm.lead.opportunity_set,opportunity,end:0 #: wizard_button:crm.lead.partner_create,init,end:0 #: view:crm.meeting.generic_wizard:0 -#: wizard_button:crm.new.send.mail,init,end:0 view:crm.opportunity:0 +#: wizard_button:crm.new.send.mail,init,end:0 +#: view:crm.opportunity:0 #: view:crm.opportunity.assign_wizard:0 #: wizard_button:crm.opportunity.reschedule_phone_call,init,end:0 -#: view:crm.phonecall:0 view:crm.phonecall.assign_wizard:0 +#: view:crm.phonecall:0 +#: view:crm.phonecall.assign_wizard:0 #: wizard_button:crm.phonecall.meeting_set,init,end:0 #: wizard_button:crm.phonecall.opportunity_set,create_partner,end:0 #: wizard_button:crm.phonecall.opportunity_set,opportunity,end:0 @@ -1638,7 +1736,8 @@ msgid "Claim Cost" msgstr "" #. module: crm -#: view:crm.job:0 view:crm.opportunity:0 +#: view:crm.job:0 +#: view:crm.opportunity:0 msgid "Schedule a Phone Call" msgstr "" @@ -1693,8 +1792,12 @@ msgid "Sale Amount" msgstr "Montante de Vendas" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 msgid "Add a CC" msgstr "" @@ -1704,7 +1807,9 @@ msgid "=" msgstr "=" #. module: crm -#: view:crm.fundraising:0 view:crm.job:0 field:crm.menu.config_wizard,name:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: field:crm.menu.config_wizard,name:0 #: field:crm.segmentation,name:0 msgid "Name" msgstr "Nome" @@ -1725,7 +1830,8 @@ msgid "Mail to watchers (CC)" msgstr "" #. module: crm -#: view:crm.fundraising:0 view:crm.meeting:0 +#: view:crm.fundraising:0 +#: view:crm.meeting:0 msgid "Next Meeting" msgstr "" @@ -1753,14 +1859,19 @@ msgid "Bug Tracking" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.case.rule:0 view:crm.claim:0 -#: view:crm.fundraising:0 view:crm.job:0 view:crm.lead:0 +#: view:crm.case:0 +#: view:crm.case.rule:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 #: view:crm.opportunity:0 msgid "Actions" msgstr "Ações" #. module: crm -#: selection:crm.case,priority:0 selection:crm.case.rule,act_priority:0 +#: selection:crm.case,priority:0 +#: selection:crm.case.rule,act_priority:0 #: selection:crm.case.rule,trg_priority_from:0 #: selection:crm.case.rule,trg_priority_to:0 msgid "High" @@ -1858,7 +1969,8 @@ msgid "Email Fail!" msgstr "" #. module: crm -#: model:crm.case.categ,name:crm.categ_phone1 view:crm.phonecall:0 +#: model:crm.case.categ,name:crm.categ_phone1 +#: view:crm.phonecall:0 #: model:ir.actions.act_window,name:crm.crm_case_categ_phone_incoming0 #: model:ir.ui.menu,name:crm.menu_crm_case_phone_inbound msgid "Inbound" @@ -1884,7 +1996,8 @@ msgstr "" #. module: crm #: view:report.crm.case.section.categ.categ2:0 #: view:report.crm.case.section.categ.stage:0 -#: view:report.crm.case.section.categ2:0 view:report.crm.case.section.stage:0 +#: view:report.crm.case.section.categ2:0 +#: view:report.crm.case.section.stage:0 msgid "This Year" msgstr "" @@ -1894,7 +2007,8 @@ msgid "Remind Partner" msgstr "Relembre Parceiro" #. module: crm -#: selection:crm.case,priority:0 selection:crm.case.rule,act_priority:0 +#: selection:crm.case,priority:0 +#: selection:crm.case.rule,act_priority:0 #: selection:crm.case.rule,trg_priority_from:0 #: selection:crm.case.rule,trg_priority_to:0 msgid "Highest" @@ -1975,7 +2089,8 @@ msgid "Convert To Opportunity" msgstr "" #. module: crm -#: model:crm.case.stage,name:crm.stage_phone2 view:crm.phonecall:0 +#: model:crm.case.stage,name:crm.stage_phone2 +#: view:crm.phonecall:0 msgid "Held" msgstr "" @@ -2015,10 +2130,12 @@ msgstr "Estado do caso" #: code:addons/crm/wizard/wizard_crm_send_email.py:0 #, python-format msgid "Send" -msgstr "" +msgstr "Enviar" #. module: crm -#: field:crm.case,priority:0 view:crm.fundraising:0 view:crm.lead:0 +#: field:crm.case,priority:0 +#: view:crm.fundraising:0 +#: view:crm.lead:0 #: view:crm.opportunity:0 msgid "Priority" msgstr "Prioridade" @@ -2047,7 +2164,9 @@ msgid "" msgstr "" #. module: crm -#: view:crm.claim:0 view:crm.job:0 view:crm.lead:0 +#: view:crm.claim:0 +#: view:crm.job:0 +#: view:crm.lead:0 msgid "Stage: " msgstr "" @@ -2062,12 +2181,15 @@ msgid "Schedule a normal or phone meeting" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 code:addons/crm/crm_claim.py:0 -#: code:addons/crm/crm_helpdesk.py:0 code:addons/crm/crm_meeting.py:0 -#: code:addons/crm/crm_opportunity.py:0 code:addons/crm/crm_phonecall.py:0 +#: code:addons/crm/crm.py:0 +#: code:addons/crm/crm_claim.py:0 +#: code:addons/crm/crm_helpdesk.py:0 +#: code:addons/crm/crm_meeting.py:0 +#: code:addons/crm/crm_opportunity.py:0 +#: code:addons/crm/crm_phonecall.py:0 #, python-format msgid "Error !" -msgstr "" +msgstr "Erro !" #. module: crm #: view:crm.case.rule:0 @@ -2177,7 +2299,8 @@ msgid "%(case_date)s = Creation date" msgstr "" #. module: crm -#: model:crm.case.stage,name:crm.stage_phone3 view:crm.phonecall:0 +#: model:crm.case.stage,name:crm.stage_phone3 +#: view:crm.phonecall:0 msgid "Not Held" msgstr "" @@ -2220,7 +2343,8 @@ msgid "Month" msgstr "" #. module: crm -#: model:crm.case.section,name:crm.section_support2 view:crm.lead:0 +#: model:crm.case.section,name:crm.section_support2 +#: view:crm.lead:0 #: field:crm.menu.config_wizard,lead:0 #: model:ir.ui.menu,name:crm.menu_action_report_crm_case_lead #: model:ir.ui.menu,name:crm.menu_crm_case_categ0_act_leads @@ -2264,7 +2388,8 @@ msgstr "Log" #. module: crm #: help:crm.menu.config_wizard,fund:0 -msgid "This may help associations in their fund raising process and tracking." +msgid "" +"This may help associations in their fund raising process and tracking." msgstr "" #. module: crm @@ -2296,14 +2421,16 @@ msgid "Delay Close" msgstr "" #. module: crm -#: selection:crm.case,priority:0 selection:crm.case.rule,act_priority:0 +#: selection:crm.case,priority:0 +#: selection:crm.case.rule,act_priority:0 #: selection:crm.case.rule,trg_priority_from:0 #: selection:crm.case.rule,trg_priority_to:0 msgid "Low" msgstr "Baixo" #. module: crm -#: field:crm.case,date_closed:0 selection:crm.case,state:0 +#: field:crm.case,date_closed:0 +#: selection:crm.case,state:0 #: selection:crm.case.rule,act_state:0 #: selection:crm.case.rule,trg_state_from:0 #: selection:crm.case.rule,trg_state_to:0 @@ -2323,7 +2450,7 @@ msgstr "" #: code:addons/crm/crm.py:0 #, python-format msgid "cancel" -msgstr "" +msgstr "cancelar" #. module: crm #: model:crm.case.categ,name:crm.categ_meet2 @@ -2331,7 +2458,10 @@ msgid "Internal Meeting" msgstr "" #. module: crm -#: view:crm.case:0 field:crm.case,child_ids:0 view:crm.claim:0 view:crm.lead:0 +#: view:crm.case:0 +#: field:crm.case,child_ids:0 +#: view:crm.claim:0 +#: view:crm.lead:0 #: view:crm.opportunity:0 msgid "Events" msgstr "" @@ -2384,7 +2514,8 @@ msgstr "" #. module: crm #: code:addons/crm/crm_phonecall.py:0 #: model:crm.case.section,name:crm.section_support_phone -#: field:crm.menu.config_wizard,phonecall:0 view:crm.phonecall:0 +#: field:crm.menu.config_wizard,phonecall:0 +#: view:crm.phonecall:0 #: model:ir.actions.act_window,name:crm.crm_case_categ_phone0 #: model:ir.ui.menu,name:crm.menu_crm_case_phone #, python-format @@ -2419,7 +2550,8 @@ msgid "Cheque" msgstr "" #. module: crm -#: field:crm.case,active:0 field:crm.case.rule,active:0 +#: field:crm.case,active:0 +#: field:crm.case.rule,active:0 #: field:crm.case.section,active:0 msgid "Active" msgstr "Ativo" @@ -2459,8 +2591,10 @@ msgid "Months" msgstr "Meses" #. module: crm -#: view:crm.claim.assign_wizard:0 view:crm.helpdesk.assign_wizard:0 -#: view:crm.opportunity.assign_wizard:0 view:crm.phonecall.assign_wizard:0 +#: view:crm.claim.assign_wizard:0 +#: view:crm.helpdesk.assign_wizard:0 +#: view:crm.opportunity.assign_wizard:0 +#: view:crm.phonecall.assign_wizard:0 #: model:ir.actions.act_window,name:crm.action_crm_claim_assign_wizard #: model:ir.actions.act_window,name:crm.action_crm_helpdesk_assign_wizard #: model:ir.actions.act_window,name:crm.action_crm_opportunity_assign_wizard @@ -2492,8 +2626,10 @@ msgstr "Ação" #. module: crm #: code:addons/crm/crm_claim.py:0 -#: model:crm.case.section,name:crm.section_support_claims view:crm.claim:0 -#: field:crm.menu.config_wizard,claims:0 view:crm.phonecall:0 +#: model:crm.case.section,name:crm.section_support_claims +#: view:crm.claim:0 +#: field:crm.menu.config_wizard,claims:0 +#: view:crm.phonecall:0 #: model:ir.ui.menu,name:crm.menu_crm_case_claims #, python-format msgid "Claims" @@ -2531,7 +2667,8 @@ msgid "Sales" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.phonecall:0 +#: view:crm.case:0 +#: view:crm.phonecall:0 msgid "General" msgstr "Geral" @@ -2552,8 +2689,12 @@ msgid "Other" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.lead:0 -#: selection:crm.new.send.mail,init,state:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.lead:0 +#: selection:crm.new.send.mail,init,state:0 +#: view:crm.opportunity:0 msgid "Done" msgstr "" @@ -2568,12 +2709,18 @@ msgid "All Opportunities" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 view:crm.case:0 selection:crm.case,state:0 +#: code:addons/crm/crm.py:0 +#: view:crm.case:0 +#: selection:crm.case,state:0 #: selection:crm.case.rule,act_state:0 #: selection:crm.case.rule,trg_state_from:0 -#: selection:crm.case.rule,trg_state_to:0 view:crm.claim:0 -#: view:crm.fundraising:0 view:crm.job:0 view:crm.lead:0 -#: view:crm.opportunity:0 view:crm.phonecall:0 +#: selection:crm.case.rule,trg_state_to:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 #: selection:report.crm.case.section.categ.categ2,state:0 #: selection:report.crm.case.section.categ.stage,state:0 #: selection:report.crm.case.section.categ2,state:0 @@ -2611,11 +2758,17 @@ msgid "Helpdesk" msgstr "" #. module: crm -#: field:crm.case,user_id:0 field:crm.case.rule,trg_user_id:0 view:crm.claim:0 -#: field:crm.claim.assign_wizard,user_id:0 view:crm.fundraising:0 -#: field:crm.helpdesk.assign_wizard,user_id:0 view:crm.job:0 -#: view:crm.meeting:0 field:crm.meeting.generic_wizard,user_id:0 -#: view:crm.opportunity:0 field:crm.opportunity.assign_wizard,user_id:0 +#: field:crm.case,user_id:0 +#: field:crm.case.rule,trg_user_id:0 +#: view:crm.claim:0 +#: field:crm.claim.assign_wizard,user_id:0 +#: view:crm.fundraising:0 +#: field:crm.helpdesk.assign_wizard,user_id:0 +#: view:crm.job:0 +#: view:crm.meeting:0 +#: field:crm.meeting.generic_wizard,user_id:0 +#: view:crm.opportunity:0 +#: field:crm.opportunity.assign_wizard,user_id:0 #: field:crm.phonecall.assign_wizard,user_id:0 msgid "Responsible" msgstr "Responsável" @@ -2649,6 +2802,8 @@ msgid "" "You can not escalate this case.\n" "You are already at the top level." msgstr "" +"Você não pode escalar este case.\n" +"Você já está em nível superior." #. module: crm #: view:crm.lead:0 @@ -2694,7 +2849,8 @@ msgstr "" #. module: crm #: view:report.crm.case.section.categ.categ2:0 #: view:report.crm.case.section.categ.stage:0 -#: view:report.crm.case.section.categ2:0 view:report.crm.case.section.stage:0 +#: view:report.crm.case.section.categ2:0 +#: view:report.crm.case.section.stage:0 msgid "This Month" msgstr "" @@ -2711,12 +2867,12 @@ msgstr "" #. module: crm #: help:crm.case,state:0 msgid "" -"The state is set to 'Draft', when a case is " -"created. \n" -"If the case is in progress the state is set to " -"'Open'. \n" -"When the case is over, the state is set to " -"'Done'. \n" +"The state is set to 'Draft', when a case is created. " +" \n" +"If the case is in progress the state is set to 'Open'. " +" \n" +"When the case is over, the state is set to 'Done'. " +" \n" "If the case needs to be reviewed then the state is set to 'Pending'." msgstr "" @@ -2882,7 +3038,8 @@ msgid "Provide path for Remote Calendar" msgstr "" #. module: crm -#: view:crm.segmentation:0 field:crm.segmentation.line,segmentation_id:0 +#: view:crm.segmentation:0 +#: field:crm.segmentation.line,segmentation_id:0 msgid "Segmentation" msgstr "Segmentação" @@ -2942,7 +3099,8 @@ msgstr "" #. module: crm #: wizard_button:caldav.crm.export,init,end:0 #: wizard_button:caldav.crm.import,display,end:0 -#: wizard_button:caldav.crm.subscribe,display,end:0 view:crm.email.add.cc:0 +#: wizard_button:caldav.crm.subscribe,display,end:0 +#: view:crm.email.add.cc:0 msgid "Ok" msgstr "" @@ -2964,10 +3122,11 @@ msgid "" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 code:addons/crm/wizard/wizard_cal_subscribe.py:0 +#: code:addons/crm/crm.py:0 +#: code:addons/crm/wizard/wizard_cal_subscribe.py:0 #, python-format msgid "Error!" -msgstr "" +msgstr "Erro!" #. module: crm #: model:ir.model,name:crm.model_crm_claim_assign_wizard @@ -2981,7 +3140,8 @@ msgid "All Jobs Requests" msgstr "" #. module: crm -#: selection:crm.case,state:0 selection:crm.case.rule,act_state:0 +#: selection:crm.case,state:0 +#: selection:crm.case.rule,act_state:0 #: selection:crm.case.rule,trg_state_from:0 #: selection:crm.case.rule,trg_state_to:0 #: selection:report.crm.case.section.categ.categ2,state:0 @@ -3049,7 +3209,8 @@ msgid "%(case_subject)s = Case subject" msgstr "%(case_subject)s = Assunto do Caso" #. module: crm -#: field:crm.case,section_id:0 field:crm.case.log,section_id:0 +#: field:crm.case,section_id:0 +#: field:crm.case.log,section_id:0 #: field:crm.case.rule,trg_section_id:0 #: field:crm.claim.assign_wizard,section_id:0 #: field:crm.helpdesk.assign_wizard,section_id:0 @@ -3093,13 +3254,15 @@ msgstr "Sua ação" #. module: crm #: model:crm.case.category2,name:crm.category_lead3 -#: field:crm.case.history,email:0 field:crm.email.add.cc,email:0 +#: field:crm.case.history,email:0 +#: field:crm.email.add.cc,email:0 #: view:crm.job:0 msgid "Email" msgstr "E-mail" #. module: crm -#: field:crm.case,canal_id:0 field:crm.case.log,canal_id:0 +#: field:crm.case,canal_id:0 +#: field:crm.case.log,canal_id:0 msgid "Channel" msgstr "Canal" @@ -3144,12 +3307,18 @@ msgid "Reporting" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 view:crm.case:0 selection:crm.case,state:0 +#: code:addons/crm/crm.py:0 +#: view:crm.case:0 +#: selection:crm.case,state:0 #: selection:crm.case.rule,act_state:0 #: selection:crm.case.rule,trg_state_from:0 -#: selection:crm.case.rule,trg_state_to:0 view:crm.claim:0 -#: view:crm.fundraising:0 view:crm.job:0 view:crm.lead:0 -#: selection:crm.new.send.mail,init,state:0 view:crm.opportunity:0 +#: selection:crm.case.rule,trg_state_to:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: selection:crm.new.send.mail,init,state:0 +#: view:crm.opportunity:0 #: selection:report.crm.case.section.categ.categ2,state:0 #: selection:report.crm.case.section.categ.stage,state:0 #: selection:report.crm.case.section.categ2,state:0 @@ -3205,7 +3374,8 @@ msgid "Lead Subject" msgstr "" #. module: crm -#: view:crm.lead:0 view:crm.phonecall:0 +#: view:crm.lead:0 +#: view:crm.phonecall:0 msgid "Convert to Opportunity" msgstr "" @@ -3298,7 +3468,8 @@ msgid "All Funds" msgstr "" #. module: crm -#: field:crm.case.section,calendar:0 view:crm.meeting:0 +#: field:crm.case.section,calendar:0 +#: view:crm.meeting:0 #: model:ir.ui.menu,name:crm.menu_crm_case_category_act_meetings msgid "Calendar" msgstr "Calendário" @@ -3324,7 +3495,8 @@ msgid "Sales Purchase" msgstr "Propostas de vendas" #. module: crm -#: view:crm.job:0 model:ir.actions.wizard,name:crm.wizard_crm_job_meeting_set +#: view:crm.job:0 +#: model:ir.actions.wizard,name:crm.wizard_crm_job_meeting_set #: model:ir.actions.wizard,name:crm.wizard_crm_phonecall_meeting_set msgid "Schedule Meeting" msgstr "" @@ -3335,7 +3507,8 @@ msgid "Arts And Culture" msgstr "" #. module: crm -#: model:crm.case.categ,name:crm.categ_phone2 view:crm.phonecall:0 +#: model:crm.case.categ,name:crm.categ_phone2 +#: view:crm.phonecall:0 #: model:ir.actions.act_window,name:crm.crm_case_categ_phone_outgoing0 #: model:ir.ui.menu,name:crm.menu_crm_case_phone_outbound msgid "Outbound" @@ -3360,14 +3533,17 @@ msgstr "Parado" #. module: crm #: wizard_field:crm.case.opportunity.partner_opportunity,init,probability:0 #: wizard_field:crm.lead.opportunity_set,opportunity,probability:0 +#: wizard_field:crm.phonecall.opportunity_set,opportunity,probability:0 msgid "Success Probability" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 selection:crm.case,state:0 +#: code:addons/crm/crm.py:0 +#: selection:crm.case,state:0 #: selection:crm.case.rule,act_state:0 #: selection:crm.case.rule,trg_state_from:0 -#: selection:crm.case.rule,trg_state_to:0 view:crm.meeting:0 +#: selection:crm.case.rule,trg_state_to:0 +#: view:crm.meeting:0 #: selection:report.crm.case.section.categ.categ2,state:0 #: selection:report.crm.case.section.categ.stage,state:0 #: selection:report.crm.case.section.categ2,state:0 @@ -3392,7 +3568,8 @@ msgid "Set section to" msgstr "Definir seção para" #. module: crm -#: selection:crm.case,priority:0 selection:crm.case.rule,act_priority:0 +#: selection:crm.case,priority:0 +#: selection:crm.case.rule,act_priority:0 #: selection:crm.case.rule,trg_priority_from:0 #: selection:crm.case.rule,trg_priority_to:0 msgid "Normal" @@ -3404,7 +3581,7 @@ msgstr "Normal" #: code:addons/crm/wizard/wizard_crm_send_email.py:0 #, python-format msgid "You must put a Partner eMail to use this action!" -msgstr "" +msgstr "Você deve colocar um e-mail de parceiro para utilizar esta ação!" #. module: crm #: wizard_view:crm.job.partner_create,init:0 @@ -3426,7 +3603,8 @@ msgid "Change RRule" msgstr "" #. module: crm -#: selection:crm.email.add.cc,name:0 field:crm.email.add.cc,user_id:0 +#: selection:crm.email.add.cc,name:0 +#: field:crm.email.add.cc,user_id:0 #: field:report.crm.case.section.categ.categ2,user_id:0 #: field:report.crm.case.section.categ.stage,user_id:0 #: field:report.crm.case.section.categ2,user_id:0 @@ -3476,6 +3654,8 @@ msgstr "" msgid "" "Can not send mail with empty body,you should have description in the body" msgstr "" +"Não é possível enviar um e-mail com uma mensagem de corpo vazia, escreva a " +"mensagem" #. module: crm #: selection:report.crm.case.section.categ.categ2,month:0 @@ -3506,10 +3686,15 @@ msgid "Healthcare" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.claim.assign_wizard:0 -#: view:crm.helpdesk.assign_wizard:0 view:crm.meeting:0 -#: view:crm.meeting.generic_wizard:0 view:crm.opportunity:0 -#: view:crm.opportunity.assign_wizard:0 view:crm.phonecall:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.claim.assign_wizard:0 +#: view:crm.helpdesk.assign_wizard:0 +#: view:crm.meeting:0 +#: view:crm.meeting.generic_wizard:0 +#: view:crm.opportunity:0 +#: view:crm.opportunity.assign_wizard:0 +#: view:crm.phonecall:0 #: view:crm.phonecall.assign_wizard:0 msgid "Assign" msgstr "" @@ -3535,7 +3720,9 @@ msgid "Stage of case" msgstr "" #. module: crm -#: view:crm.case:0 view:crm.fundraising:0 view:crm.opportunity:0 +#: view:crm.case:0 +#: view:crm.fundraising:0 +#: view:crm.opportunity:0 msgid "Estimates" msgstr "Estimativas" @@ -3545,7 +3732,8 @@ msgid "Responsible User" msgstr "Usuário Responsável" #. module: crm -#: code:addons/crm/crm.py:0 view:crm.case:0 +#: code:addons/crm/crm.py:0 +#: view:crm.case:0 #, python-format msgid "Close" msgstr "Fechar" @@ -3603,9 +3791,14 @@ msgid "% = The '%' Character" msgstr "" #. module: crm -#: view:crm.case:0 field:crm.case,name:0 field:crm.case.history,description:0 -#: field:crm.case.history,note:0 view:crm.job:0 view:crm.meeting:0 -#: view:crm.opportunity:0 view:crm.phonecall:0 +#: view:crm.case:0 +#: field:crm.case,name:0 +#: field:crm.case.history,description:0 +#: field:crm.case.history,note:0 +#: view:crm.job:0 +#: view:crm.meeting:0 +#: view:crm.opportunity:0 +#: view:crm.phonecall:0 #: field:crm.segmentation,description:0 msgid "Description" msgstr "Descrição" @@ -3631,9 +3824,14 @@ msgstr "" "Marque isto se quiser a regra para enviar um aviso por e-mail para o usuário." #. module: crm -#: view:crm.case:0 view:crm.claim:0 view:crm.fundraising:0 view:crm.job:0 -#: view:crm.lead:0 wizard_field:crm.new.send.mail,init,cc:0 -#: view:crm.opportunity:0 wizard_field:crm.send.mail,init,cc:0 +#: view:crm.case:0 +#: view:crm.claim:0 +#: view:crm.fundraising:0 +#: view:crm.job:0 +#: view:crm.lead:0 +#: wizard_field:crm.new.send.mail,init,cc:0 +#: view:crm.opportunity:0 +#: wizard_field:crm.send.mail,init,cc:0 msgid "CC" msgstr "" @@ -3648,10 +3846,14 @@ msgid "_Import" msgstr "" #. module: crm -#: code:addons/crm/crm.py:0 field:crm.case.log,case_id:0 -#: field:crm.claim,inherit_case_id:0 field:crm.fundraising,inherit_case_id:0 -#: field:crm.helpdesk,inherit_case_id:0 field:crm.job,inherit_case_id:0 -#: field:crm.lead,inherit_case_id:0 field:crm.meeting,inherit_case_id:0 +#: code:addons/crm/crm.py:0 +#: field:crm.case.log,case_id:0 +#: field:crm.claim,inherit_case_id:0 +#: field:crm.fundraising,inherit_case_id:0 +#: field:crm.helpdesk,inherit_case_id:0 +#: field:crm.job,inherit_case_id:0 +#: field:crm.lead,inherit_case_id:0 +#: field:crm.meeting,inherit_case_id:0 #: field:crm.opportunity,inherit_case_id:0 #: field:crm.phonecall,inherit_case_id:0 #: model:ir.model,name:crm.model_crm_case @@ -3661,7 +3863,8 @@ msgid "Case" msgstr "Caso" #. module: crm -#: selection:crm.case,priority:0 selection:crm.case.rule,act_priority:0 +#: selection:crm.case,priority:0 +#: selection:crm.case.rule,act_priority:0 #: selection:crm.case.rule,trg_priority_from:0 #: selection:crm.case.rule,trg_priority_to:0 msgid "Lowest" @@ -3697,7 +3900,8 @@ msgstr "" "por este fator. Trata-se de uma multiplicação" #. module: crm -#: wizard_view:crm.new.send.mail,init:0 wizard_view:crm.send.mail,init:0 +#: wizard_view:crm.new.send.mail,init:0 +#: wizard_view:crm.send.mail,init:0 msgid "Mass Mailing" msgstr "" @@ -3722,7 +3926,7 @@ msgstr "" #. module: crm #: view:crm.fundraising:0 msgid "Funds by Categories" -msgstr "Categorias" +msgstr "" #. module: crm #: model:process.node,note:crm.process_node_leads0 @@ -3773,7 +3977,8 @@ msgid "Export ICS File" msgstr "" #. module: crm -#: field:crm.case.rule,sequence:0 field:crm.case.section,sequence:0 +#: field:crm.case.rule,sequence:0 +#: field:crm.case.section,sequence:0 #: field:crm.case.stage,sequence:0 msgid "Sequence" msgstr "Sequência" @@ -3821,8 +4026,11 @@ msgstr "" #~ msgid "Add Last Mail for Replying" #~ msgstr "Adicionar último e-mail para responder" -#~ msgid "this wizard will create all sub-menus, within the selected menu." -#~ msgstr "este wizard cria todos os sub-menus, dentro de um menu selecionado" +#~ msgid "Update The Proposed Menus To Be Created" +#~ msgstr "Atualizar os menus propostos para serem criados" + +#~ msgid "Base Information" +#~ msgstr "Informações básicas" #~ msgid "All Open " #~ msgstr "Tudo aberto " @@ -3830,12 +4038,18 @@ msgstr "" #~ msgid "Create menus for a case section" #~ msgstr "Criar menus para uma seção de caso" +#~ msgid "My " +#~ msgstr "Meu " + #~ msgid "Create menu Entries" #~ msgstr "Criar entradas de menus" #~ msgid "All Unclosed and Unassigned " #~ msgstr "Todos abertos e não assinados " +#~ msgid "Extra Info" +#~ msgstr "Informações Extra" + #~ msgid "My Open " #~ msgstr "Meus abertos " @@ -3845,6 +4059,12 @@ msgstr "" #~ msgid "Excluded Answers :" #~ msgstr "Respostas Excluídas :" +#~ msgid "Profiling" +#~ msgstr "Avaliação" + +#~ msgid "My cases" +#~ msgstr "Meus casos" + #~ msgid "All Draft " #~ msgstr "Todos esboços " @@ -3860,14 +4080,36 @@ msgstr "" #~ msgid "My Unclosed " #~ msgstr "Meus não fechados " -#~ msgid "List With Calendar" -#~ msgstr "Lista com calendário" +#~ msgid "Profiling Options" +#~ msgstr "Filtrando Opções" + +#~ msgid "My Pending " +#~ msgstr "Minhas pendências " + +#~ msgid "New Form" +#~ msgstr "Novo formulário" #~ msgid "" -#~ "You may want to create a new parent menu to put all the created menus in." +#~ "These people will receive a copy of the futur communication between partner " +#~ "and users by email" #~ msgstr "" -#~ "Pode ser que você queira criar um novo menu principal para agregar todos " -#~ "os menus criados." +#~ "Essas pessoas receberão uma cópia por e-mail da futura comunicação entre " +#~ "parceiros e usuários" + +#~ msgid "New With Calendar" +#~ msgstr "Novo com calendário" + +#~ msgid "List With Calendar" +#~ msgstr "Lista com calendário" + +#~ msgid "Calendar View" +#~ msgstr "Visualização do Calendário" + +#~ msgid "Created Menus" +#~ msgstr "Menus criados" + +#~ msgid "Parent Menu" +#~ msgstr "Menu Superior(pai)" #~ msgid "Included Answers :" #~ msgstr "Respostas incluídas :" @@ -3878,8 +4120,8 @@ msgstr "" #~ msgid "Base Menu Name" #~ msgstr "Nome do menu básico" -#~ msgid "Created Menus" -#~ msgstr "Menus criados" +#~ msgid "All Unassigned " +#~ msgstr "Tudo não atribuído " #~ msgid "All Unclosed " #~ msgstr "Tudo aberto " @@ -3893,13 +4135,14 @@ msgstr "" #~ msgid "Create Menus For Cases" #~ msgstr "Criar Menus para os Casos" +#~ msgid "All Pending " +#~ msgstr "Tudo Pendente " + #~ msgid "All Canceled " #~ msgstr "Tudo cancelado " -#~ msgid "Deadline Date is automatically computed from Start Date + Duration" -#~ msgstr "" -#~ "Data limite é calculada automaticamente pela soma da Data Inicial + " -#~ "Duração" +#~ msgid "All " +#~ msgstr "Tudo " #~ msgid "List" #~ msgstr "Listar" @@ -3913,11 +4156,11 @@ msgstr "" #~ msgid "My Canceled " #~ msgstr "Meus cancelados " -#~ msgid "Form View" -#~ msgstr "Visualização de formulário" +#~ msgid "Mail to watchers (Cc)" +#~ msgstr "Correio para observadors (cc)" #~ msgid "crm.case.section.open" #~ msgstr "crm.case.section.open" -#~ msgid "Update The Proposed Menus To Be Created" -#~ msgstr "Atualizar os menus propostos para serem criados" +#~ msgid "Form View" +#~ msgstr "Visualização de formulário" diff --git a/addons/crm/wizard/__init__.py b/addons/crm/wizard/__init__.py index 68fe0f06e8d..62be2041d98 100644 --- a/addons/crm/wizard/__init__.py +++ b/addons/crm/wizard/__init__.py @@ -23,12 +23,8 @@ import crm_opportunity_wizard import crm_lead_wizard import crm_phonecall_wizard - import wizard_crm_send_email import wizard_crm_new_send_email -import wizard_cal_export -import wizard_cal_import -import wizard_cal_subscribe import wizard_history_event diff --git a/addons/crm/wizard/crm_lead_wizard.py b/addons/crm/wizard/crm_lead_wizard.py index decb2101557..27c36d3634f 100644 --- a/addons/crm/wizard/crm_lead_wizard.py +++ b/addons/crm/wizard/crm_lead_wizard.py @@ -103,6 +103,8 @@ class lead2opportunity(wizard.interface): 'planned_revenue': data['form']['planned_revenue'], 'probability': data['form']['probability'], 'partner_id': data['form']['partner_id'], + 'section_id':lead.section_id.id, + 'description':lead.description, }) new_opportunity = opportunity_case_obj.browse(cr, uid, new_opportunity_id) @@ -115,7 +117,7 @@ class lead2opportunity(wizard.interface): lead_case_obj.write(cr, uid, [lead.id], vals) lead_case_obj.case_cancel(cr, uid, [lead.id]) - # opportunity_case_obj.case_open(cr, uid, [new_opportunity_id]) + opportunity_case_obj.case_open(cr, uid, [new_opportunity_id]) value = { 'name': _('Opportunity'), diff --git a/addons/crm/wizard/crm_opportunity_wizard.py b/addons/crm/wizard/crm_opportunity_wizard.py index 49ae48f62fa..3a01fde870c 100644 --- a/addons/crm/wizard/crm_opportunity_wizard.py +++ b/addons/crm/wizard/crm_opportunity_wizard.py @@ -41,20 +41,20 @@ class opportunity2phonecall(wizard.interface): <field name='note' colspan="4"/> <newline /> <field name='section_id' /> - <field name='category_id' domain="[('section_id','=',section_id)]"/> + <field name='category_id' domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.phonecall')]"/> </form>""" case_fields = { 'user_id' : {'string' : 'Assign To', 'type' : 'many2one', 'relation' : 'res.users'}, - 'deadline' : {'string' : 'Planned Date', 'type' : 'datetime'}, + 'deadline' : {'string' : 'Planned Date', 'type' : 'datetime' ,'required' :True}, 'note' : {'string' : 'Goals', 'type' : 'text'}, - 'category_id' : {'string' : 'Category', 'type' : 'many2one', 'relation' : 'crm.phonecall.categ', 'required' :True}, + 'category_id' : {'string' : 'Category', 'type' : 'many2one', 'relation' : 'crm.case.categ', 'required' :True}, 'section_id' : {'string' : 'Section', 'type' : 'many2one', 'relation' : 'crm.case.section'}, } def _default_values(self, cr, uid, data, context): case_obj = pooler.get_pool(cr.dbname).get('crm.opportunity') - categ_id = pooler.get_pool(cr.dbname).get('crm.phonecall.categ').search(cr, uid, [('name','=','Outbound')]) + categ_id = pooler.get_pool(cr.dbname).get('crm.case.categ').search(cr, uid, [('name','=','Outbound')]) case = case_obj.browse(cr, uid, data['id']) return { 'user_id' : case.user_id and case.user_id.id, @@ -91,9 +91,15 @@ class opportunity2phonecall(wizard.interface): 'categ_id' : form['category_id'], 'description' : form['note'], 'date' : form['deadline'], - 'section_id' : form['section_id'] + 'section_id' : form['section_id'], + 'partner_id': opportunity.partner_id.id, + 'partner_address_id':opportunity.partner_address_id.id, + 'description':opportunity.description }, context=context) - + vals = {} + if not opportunity.phonecall_id: + vals.update({'phonecall_id' : new_case}) + opportunity_case_obj.write(cr, uid, [opportunity.id], vals) opportunity_case_obj.case_cancel(cr, uid, [opportunity.id]) phonecall_case_obj.case_open(cr, uid, [new_case]) @@ -127,6 +133,19 @@ class opportunity2meeting(wizard.interface): def _makeMeeting(self, cr, uid, data, context): pool = pooler.get_pool(cr.dbname) + opportunity_case_obj = pool.get('crm.opportunity') + meeting_case_obj = pool.get('crm.meeting') + for opportunity in opportunity_case_obj.browse(cr, uid, data['ids']): + new_meeting_id = meeting_case_obj.create(cr, uid, { + 'name': opportunity.name, + 'date': opportunity.date, + 'date_deadline': opportunity.date_deadline, + }) + new_meeting = meeting_case_obj.browse(cr, uid, new_meeting_id) + vals = {} + opportunity_case_obj.write(cr, uid, [opportunity.id], vals) + opportunity_case_obj.case_cancel(cr, uid, [opportunity.id]) + meeting_case_obj.case_open(cr, uid, [new_meeting_id]) data_obj = pool.get('ir.model.data') result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter') id = data_obj.read(cr, uid, result, ['res_id']) @@ -203,7 +222,7 @@ class partner_opportunity(wizard.interface): address = part_obj.address_get(cr, uid, data['ids' ]) - categ_obj = pool.get('crm.opportunity.categ') + categ_obj = pool.get('crm.case.categ') categ_ids = categ_obj.search(cr, uid, [('name','ilike','Part%')]) case_obj = pool.get('crm.opportunity') diff --git a/addons/crm/wizard/crm_phonecall_wizard.py b/addons/crm/wizard/crm_phonecall_wizard.py index 227b874fb58..3393662e420 100644 --- a/addons/crm/wizard/crm_phonecall_wizard.py +++ b/addons/crm/wizard/crm_phonecall_wizard.py @@ -104,6 +104,8 @@ class phonecall2opportunity(wizard.interface): 'probability': data['form']['probability'], 'partner_id': data['form']['partner_id'], 'phonecall_id':phonecall.id, + 'section_id':phonecall.section_id.id, + 'description':phonecall.description, }) new_opportunity = opportunity_case_obj.browse(cr, uid, new_opportunity_id) vals = { @@ -192,6 +194,19 @@ class phonecall2meeting(wizard.interface): def _makeMeeting(self, cr, uid, data, context): pool = pooler.get_pool(cr.dbname) + phonecall_case_obj = pool.get('crm.phonecall') + meeting_case_obj = pool.get('crm.meeting') + for phonecall in phonecall_case_obj.browse(cr, uid, data['ids']): + new_meeting_id = meeting_case_obj.create(cr, uid, { + 'name': phonecall.name, + 'date': phonecall.date, + 'duration': phonecall.duration, + }) + new_meeting = meeting_case_obj.browse(cr, uid, new_meeting_id) + vals = {} + phonecall_case_obj.write(cr, uid, [phonecall.id], vals) + phonecall_case_obj.case_cancel(cr, uid, [phonecall.id]) + meeting_case_obj.case_open(cr, uid, [new_meeting_id]) data_obj = pool.get('ir.model.data') result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter') id = data_obj.read(cr, uid, result, ['res_id']) diff --git a/addons/crm_hr/crm_hr.py b/addons/crm_hr/crm_hr.py index e3aaadb45fe..7fe2f2c4878 100644 --- a/addons/crm_hr/crm_hr.py +++ b/addons/crm_hr/crm_hr.py @@ -34,43 +34,6 @@ from osv.orm import except_orm from crm import crm -class crm_job_categ(osv.osv): - _name = "crm.job.categ" - _description = "Job 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_job_categ() - -class crm_job_type(osv.osv): - _name = "crm.job.type" - _description = "Job 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_job_type() - -class crm_job_stage(osv.osv): - _name = "crm.job.stage" - _description = "Stage of job 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_job_stage() class crm_job(osv.osv): _name = "crm.job" @@ -80,7 +43,7 @@ class crm_job(osv.osv): _columns = { 'date_closed': fields.datetime('Closed', readonly=True), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'categ_id': fields.many2one('crm.job.categ', 'Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.job')]"), 'planned_revenue': fields.float('Planned Revenue'), 'planned_cost': fields.float('Planned Costs'), 'probability': fields.float('Probability (%)'), @@ -88,8 +51,8 @@ class crm_job(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.job.stage', 'Stage', domain="[('section_id','=',section_id)]"), - 'type_id': fields.many2one('crm.job.type', 'Type Name', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.job')]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Type Name', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.job')]"), 'duration': fields.float('Duration'), 'case_id': fields.many2one('crm.case', 'Related Case'), 'ref' : fields.reference('Reference', selection=crm._links_get, size=128), @@ -99,13 +62,14 @@ class crm_job(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)."), + 'phonecall_id':fields.many2one ('crm.phonecall', 'Phonecall'), } def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.categ.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_job() diff --git a/addons/crm_hr/crm_hr_data.xml b/addons/crm_hr/crm_hr_data.xml index 2486981eded..94a47be6d2f 100644 --- a/addons/crm_hr/crm_hr_data.xml +++ b/addons/crm_hr/crm_hr_data.xml @@ -5,60 +5,72 @@ <!-- CASE CATEGORY(categ_id) --> - <record model="crm.job.categ" id="categ_job1"> + <record model="crm.case.categ" id="categ_job1"> <field name="name">Salesman</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.categ" id="categ_job2"> + <record model="crm.case.categ" id="categ_job2"> <field name="name">Junior Developer</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <!-- CATEGORY2(category2_id) --> + <!-- Resource(type_id) --> - <record model="crm.job.type" id="type_job1"> + <record model="crm.case.resource.type" id="type_job1"> <field name="name">Graduate</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.type" id="type_job2"> + <record model="crm.case.resource.type" id="type_job2"> <field name="name">Licenced</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.type" id="type_job3"> + <record model="crm.case.resource.type" id="type_job3"> <field name="name"> > Bac +5</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> <!-- STAGE(stage_id) --> - <record model="crm.job.stage" id="stage_job1"> + <record model="crm.case.stage" id="stage_job1"> <field name="name">Initial Jobs Demand</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job2"> + <record model="crm.case.stage" id="stage_job2"> <field name="name">First Interview</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job3"> + <record model="crm.case.stage" id="stage_job3"> <field name="name">Second Interview</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job4"> + <record model="crm.case.stage" id="stage_job4"> <field name="name">Contract Proposed</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.claim')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job5"> + <record model="crm.case.stage" id="stage_job5"> <field name="name">Contract Signed</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job6"> + <record model="crm.case.stage" id="stage_job6"> <field name="name">Refused by Employee</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> - <record model="crm.job.stage" id="stage_job7"> + <record model="crm.case.stage" id="stage_job7"> <field name="name">Refused by Company</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.job')]" model="ir.model"/> </record> </data> </openerp> diff --git a/addons/crm_hr/crm_hr_view.xml b/addons/crm_hr/crm_hr_view.xml index bb90d62b960..ca0a7d635d7 100644 --- a/addons/crm_hr/crm_hr_view.xml +++ b/addons/crm_hr/crm_hr_view.xml @@ -5,70 +5,25 @@ # ------------------------------------------------------ # Job Categories # ------------------------------------------------------ - - <record id="crm_job_categ_view_form" model="ir.ui.view"> - <field name="name">crm.job.categ.form</field> - <field name="model">crm.job.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Job Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_job_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.job.categ.tree</field> - <field name="model">crm.job.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Job Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> <record id="crm_job_categ_action" model="ir.actions.act_window"> <field name="name">Job Categories</field> - <field name="res_model">crm.job.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_job_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.claim')]</field> + <field name="context">{'object_id':'crm.job'}</field> </record> # ------------------------------------------------------ - # Stage + # Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_job_stage_tree"> - <field name="name">crm.job.stage.tree</field> - <field name="model">crm.job.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_job_stage_form"> - <field name="name">crm.job.stage.form</field> - <field name="model">crm.job.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> <record id="crm_job_stage_act" model="ir.actions.act_window"> <field name="name">Job Stages</field> - <field name="res_model">crm.claim.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_job_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.claim')]</field> + <field name="context">{'object_id':'crm.job'}</field> </record> <menuitem action="crm_job_stage_act" id="menu_crm_job_stage_act" parent="crm.menu_crm_case_stage"/> # ------------------------------------------------------ @@ -110,8 +65,6 @@ <field name="name" string="Description" colspan="2"/> <field name="section_id" colspan="1" widget="selection"/> <field name="user_id" string="Responsible" select="2"/> - <button string="Schedule a Phone Call" - name="%(wizard_crm_job_reschedule_phone_call)d" icon="gtk-redo" type="action" /> <newline/> <label string="Stage: " align="1.0"/> <group colspan="1" col="2"> @@ -121,6 +74,10 @@ <field name="date" string="Next Interview"/> <field name="duration" widget="float_time"/> <button name="%(wizard_crm_job_meeting_set)d" string="Schedule Meeting" icon="terp-crm" type="action"/> + <field name="phonecall_id" select="1"/> + <button string="Schedule a Phone Call" + name="%(wizard_crm_job_reschedule_phone_call)d" icon="gtk-redo" type="action" attrs="{'invisible':[('phonecall_id','!=',False)]}"/> + </group> <notebook colspan="4"> <page string="Job Info"> diff --git a/addons/crm_hr/wizard/crm_hr_wizard.py b/addons/crm_hr/wizard/crm_hr_wizard.py index 28491098c27..66736c5ce47 100644 --- a/addons/crm_hr/wizard/crm_hr_wizard.py +++ b/addons/crm_hr/wizard/crm_hr_wizard.py @@ -58,7 +58,8 @@ class job2phonecall(wizard.interface): case = case_obj.browse(cr, uid, data['id']) return { 'user_id' : case.user_id and case.user_id.id, - 'category_id' : categ_id and categ_id[0] or case.categ_id and case.categ_id.id, + 'category_id' : categ_id and categ_id[0] or case.categ_id and case.categ_id.id, + 'section_id' : case.section_id and case.section_id.id or False, 'note' : case.description } @@ -84,17 +85,23 @@ class job2phonecall(wizard.interface): #TODO : Take other info from job new_phonecall_id = phonecall_case_obj.create(cr, uid, { 'name' : job.name, - 'case_id' : job.inherit_case_id.id, 'user_id' : form['user_id'], 'categ_id' : form['category_id'], 'description' : form['note'], 'date' : form['deadline'], - 'section_id' : form['section_id'] + 'section_id' : form['section_id'], + 'description':job.description, + 'partner_id':job.partner_id.id, + 'partner_address_id':job.partner_address_id.id, + 'partner_phone':job.partner_phone, + 'partner_mobile':job.partner_mobile, + 'description':job.description, + 'date':job.date, }, context=context) new_phonecall = phonecall_case_obj.browse(cr, uid, new_phonecall_id) vals = {} if not job.case_id: - vals.update({'case_id' : new_phonecall.inherit_case_id.id}) + vals.update({'phonecall_id' : new_phonecall.id}) job_case_obj.write(cr, uid, [job.id], vals) job_case_obj.case_cancel(cr, uid, [job.id]) phonecall_case_obj.case_open(cr, uid, [new_phonecall_id]) @@ -128,6 +135,20 @@ class job2meeting(wizard.interface): def _makeMeeting(self, cr, uid, data, context): pool = pooler.get_pool(cr.dbname) + job_case_obj = pool.get('crm.job') + meeting_case_obj = pool.get('crm.meeting') + for job in job_case_obj.browse(cr, uid, data['ids']): + new_meeting_id = meeting_case_obj.create(cr, uid, { + 'name': job.name, + 'date': job.date, + 'duration': job.duration, + }) + new_meeting = meeting_case_obj.browse(cr, uid, new_meeting_id) + vals = {} + job_case_obj.write(cr, uid, [job.id], vals) + job_case_obj.case_cancel(cr, uid, [job.id]) + meeting_case_obj.case_open(cr, uid, [new_meeting_id]) + data_obj = pool.get('ir.model.data') result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter') id = data_obj.read(cr, uid, result, ['res_id']) diff --git a/addons/crm_project/crm_bugs_data.xml b/addons/crm_project/crm_bugs_data.xml index b43d61adf8f..ca891949499 100644 --- a/addons/crm_project/crm_bugs_data.xml +++ b/addons/crm_project/crm_bugs_data.xml @@ -6,30 +6,35 @@ --> <!-- For Bugs --> - <record model="crm.bug.categ" id="categ1"> + <record model="crm.case.categ" id="categ1"> <field name="name">Bugs</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.categ" id="categ2"> + <record model="crm.case.categ" id="categ2"> <field name="name">Patches</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.categ" id="categ3"> + <record model="crm.case.categ" id="categ3"> <field name="name">Feature Requests</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> <!-- - Case Category2 + Case type_id --> <!-- For Bugs --> - <record model="crm.bug.type" id="type1"> + <record model="crm.case.resource.type" id="type1"> <field name="name">Version 4.2</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.type" id="type2"> + <record model="crm.case.resource.type" id="type2"> <field name="name">Version 4.4</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> <!-- @@ -37,33 +42,40 @@ --> <!-- For Bugs --> - <record model="crm.bug.stage" id="stage1"> + <record model="crm.case.stage" id="stage1"> <field name="name">Accepted as Bug</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage2"> + <record model="crm.case.stage" id="stage2"> <field name="name">Fixed</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage3"> + <record model="crm.case.stage" id="stage3"> <field name="name">Won't fix</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage4"> + <record model="crm.case.stage" id="stage4"> <field name="name">Invalid</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage5"> + <record model="crm.case.stage" id="stage5"> <field name="name">Awaiting Response</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage6"> + <record model="crm.case.stage" id="stage6"> <field name="name">Works For Me</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage7"> + <record model="crm.case.stage" id="stage7"> <field name="name">Future</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> </data> diff --git a/addons/crm_project/crm_bugs_menu.xml b/addons/crm_project/crm_bugs_menu.xml index 6fc73243ddb..627fab57aba 100644 --- a/addons/crm_project/crm_bugs_menu.xml +++ b/addons/crm_project/crm_bugs_menu.xml @@ -3,29 +3,35 @@ <data noupdate="1"> - <record model="crm.bug.categ" id="categ1"> + <record model="crm.case.categ" id="categ1"> <field name="name">Bugs</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.categ" id="categ2"> + <record model="crm.case.categ" id="categ2"> <field name="name">Patches</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.categ" id="categ3"> + <record model="crm.case.categ" id="categ3"> <field name="name">Feature Requests</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage2"> + <record model="crm.case.stage" id="stage2"> <field name="name">Fixed</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage5"> + <record model="crm.case.stage" id="stage5"> <field name="name">Awaiting Response</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="stage7"> + <record model="crm.case.stage" id="stage7"> <field name="name">Future</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.bug')]" model="ir.model"/> </record> diff --git a/addons/crm_project/crm_bugs_view.xml b/addons/crm_project/crm_bugs_view.xml index cbda54e128b..04f596751f9 100644 --- a/addons/crm_project/crm_bugs_view.xml +++ b/addons/crm_project/crm_bugs_view.xml @@ -7,70 +7,25 @@ # Bug Categories # ------------------------------------------------------ - - <record id="crm_bug_categ_view_form" model="ir.ui.view"> - <field name="name">crm.bug.categ.form</field> - <field name="model">crm.bug.categ</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Bug Category"> - <field name="name" select="1"/> - <field name="probability"/> - <field name="section_id"/> - </form> - </field> - </record> - <record id="crm_bug_categ_view_tree" model="ir.ui.view"> - <field name="name">crm.bug.categ.tree</field> - <field name="model">crm.bug.categ</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Bug Category"> - <field name="name"/> - <field name="probability"/> - <field name="section_id"/> - </tree> - </field> - </record> <record id="crm_bug_categ_action" model="ir.actions.act_window"> <field name="name">Bug Categories</field> - <field name="res_model">crm.bug.categ</field> + <field name="res_model">crm.case.categ</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_bug_categ_view_tree"/> + <field name="view_id" ref="crm.crm_case_categ_tree-view"/> + <field name="domain">[('object_id.model', '=', 'crm.project.bug')]</field> + <field name="context">{'object_id':'crm.project.bug'}</field> </record> # ------------------------------------------------------ # Stage # ------------------------------------------------------ - <record model="ir.ui.view" id="crm_bug_stage_tree"> - <field name="name">crm.bug.stage.tree</field> - <field name="model">crm.bug.stage</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Stages"> - <field name="sequence"/> - <field name="name"/> - <field name="section_id"/> - </tree> - </field> - </record> - <record model="ir.ui.view" id="crm_bug_stage_form"> - <field name="name">crm.bug.stage.form</field> - <field name="model">crm.bug.stage</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Stage"> - <field name="name" select="1"/> - <field name="section_id" select="1" widget="selection"/> - <field name="sequence"/> - </form> - </field> - </record> <record id="crm_bug_stage_act" model="ir.actions.act_window"> <field name="name">Bug Stages</field> - <field name="res_model">crm.bug.stage</field> + <field name="res_model">crm.case.stage</field> <field name="view_type">form</field> - <field name="view_id" ref="crm_bug_stage_tree"/> + <field name="view_id" ref="crm.crm_case_stage_tree"/> + <field name="domain">[('object_id.model', '=', 'crm.project.bug')]</field> + <field name="context">{'object_id':'crm.project.bug'}</field> </record> <menuitem action="crm_bug_stage_act" id="menu_crm_bug_stage_act" parent="crm.menu_crm_case_stage"/> diff --git a/addons/crm_project/crm_feature_menu.xml b/addons/crm_project/crm_feature_menu.xml index 25b8b14f2f9..299c441e0cf 100644 --- a/addons/crm_project/crm_feature_menu.xml +++ b/addons/crm_project/crm_feature_menu.xml @@ -3,17 +3,20 @@ <data noupdate="1"> - <record model="crm.bug.categ" id="future_patch_categ"> + <record model="crm.case.categ" id="future_patch_categ"> <field name="name">Patches</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.future')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="future_fixed_categ"> + <record model="crm.case.stage" id="future_fixed_categ"> <field name="name">Fixed</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.future')]" model="ir.model"/> </record> - <record model="crm.bug.stage" id="future_awaiting_categ"> + <record model="crm.case.stage" id="future_awaiting_categ"> <field name="name">Awaiting Response</field> <field name="section_id" ref="crm.section_sales_department"/> + <field name="object_id" search="[('model','=','crm.project.future')]" model="ir.model"/> </record> diff --git a/addons/crm_project/crm_project_bug.py b/addons/crm_project/crm_project_bug.py index 98439ffba33..fa408b8a570 100644 --- a/addons/crm_project/crm_project_bug.py +++ b/addons/crm_project/crm_project_bug.py @@ -34,44 +34,6 @@ from osv.orm import except_orm from crm import crm -class crm_bug_categ(osv.osv): - _name = "crm.bug.categ" - _description = " Bug 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_bug_categ() - -class crm_bug_type(osv.osv): - _name = "crm.bug.type" - _description = "Bug 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_bug_type() - -class crm_bug_stage(osv.osv): - _name = "crm.bug.stage" - _description = "Stage of Project Bug" - _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_bug_stage() class crm_project_bug(osv.osv): _name = "crm.project.bug" @@ -89,14 +51,14 @@ class crm_project_bug(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.bug.categ','Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'type_id': fields.many2one('crm.bug.type', 'Bug Type', domain="[('section_id','=',section_id)]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Bug Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"), '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.bug.stage', 'Stage', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"), 'project_id':fields.many2one('project.project', 'Project'), 'duration': fields.float('Duration') , 'probability': fields.float('Probability (%)'), @@ -114,7 +76,7 @@ class crm_project_bug(osv.osv): def onchange_categ_id(self, cr, uid, ids, categ, context={}): if not categ: return {'value':{}} - cat = self.pool.get('crm.bug.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_project/crm_project_feature.py b/addons/crm_project/crm_project_feature.py index 6200b3b2d01..18674cda5db 100644 --- a/addons/crm_project/crm_project_feature.py +++ b/addons/crm_project/crm_project_feature.py @@ -50,14 +50,14 @@ class crm_project_future_request(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.bug.categ','Category', domain="[('section_id','=',section_id)]"), + 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"), 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), - 'type_id': fields.many2one('crm.bug.type', 'Bug Type', domain="[('section_id','=',section_id)]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Bug Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"), '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.bug.stage', 'Stage', domain="[('section_id','=',section_id)]"), + 'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"), 'project_id':fields.many2one('project.project', 'Project'), 'duration': fields.float('Duration') , 'probability': fields.float('Probability (%)'), @@ -71,6 +71,12 @@ class crm_project_future_request(osv.osv): _defaults = { 'project_id':_get_project } + def onchange_categ_id(self, cr, uid, ids, categ, context={}): + if not categ: + return {'value':{}} + cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability + return {'value':{'probability':cat}} + crm_project_future_request() diff --git a/addons/event/event.py b/addons/event/event.py index 3e4cf5566d2..cad4d7f23d1 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -25,6 +25,7 @@ import netsvc import pooler import tools from tools.translate import _ +from crm import crm class crm_case_log(osv.osv): _inherit = 'crm.case.log' @@ -241,6 +242,16 @@ class event_registration(osv.osv): "invoice_label":fields.char("Label Invoice",size=128,required=True), "tobe_invoiced":fields.boolean("To be Invoiced"), "invoice_id":fields.many2one("account.invoice","Invoice"), + 'date_closed': fields.datetime('Closed', readonly=True), + 'ref' : fields.reference('Reference', selection=crm._links_get, size=128), + 'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128), + 'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id)]"), + 'canal_id': fields.many2one('res.partner.canal', 'Channel',help="The channels represent the different communication modes available with the customer." \ + " With each commercial opportunity, you can indicate the canall which is this opportunity source."), + '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)."), + } _defaults = { 'nb_register': lambda *a: 1, diff --git a/addons/hr/__terp__.py b/addons/hr/__terp__.py index 6f405e2a03d..f78bdc4ef18 100644 --- a/addons/hr/__terp__.py +++ b/addons/hr/__terp__.py @@ -36,7 +36,7 @@ """, 'author': 'Tiny', 'website': 'http://www.openerp.com', - 'depends': ['base', 'process'], + 'depends': ['base', 'process', 'resource'], 'init_xml': [], 'update_xml': [ 'security/hr_security.xml', @@ -46,7 +46,8 @@ 'process/hr_process.xml', 'hr_installer.xml' ], - 'demo_xml': ['hr_demo.xml', 'hr_department_demo.xml'], + 'demo_xml': ['hr_demo.xml', + 'hr_department_demo.xml'], 'installable': True, 'active': False, 'certificate': '0086710558965', diff --git a/addons/hr/hr.py b/addons/hr/hr.py index 40c428a9663..a49bad405dc 100644..100755 --- a/addons/hr/hr.py +++ b/addons/hr/hr.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). # @@ -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 <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## @@ -26,78 +26,16 @@ import math from osv import fields, osv from tools.translate import _ -class hr_timesheet_group(osv.osv): - _name = "hr.timesheet.group" - _description = "Working Time" - _columns = { - 'name' : fields.char("Group name", size=64, required=True), - 'timesheet_id' : fields.one2many('hr.timesheet', 'tgroup_id', 'Working Time'), - 'manager' : fields.many2one('res.users', 'Workgroup manager'), - } - def interval_min_get(self, cr, uid, id, dt_from, hours): - if not id: - return [(dt_from-DateTime.RelativeDateTime(hours=int(hours)*3), dt_from)] - todo = hours - cycle = 0 - result = [] - maxrecur = 100 - current_hour = dt_from.hour - while (todo>0) and maxrecur: - cr.execute("select hour_from,hour_to from hr_timesheet where dayofweek='%s' and tgroup_id=%s order by hour_from desc", (dt_from.day_of_week,id)) - for (hour_from,hour_to) in cr.fetchall(): - if (hour_from<current_hour) and (todo>0): - m = min(hour_to, current_hour) - if (m-hour_from)>todo: - hour_from = m-todo - d1 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_from)),int((hour_from%1) * 60)) - d2 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) - result.append((d1, d2)) - current_hour = hour_from - todo -= (m-hour_from) - dt_from -= DateTime.RelativeDateTime(days=1) - current_hour = 24 - maxrecur -= 1 - result.reverse() - return result - - def interval_get(self, cr, uid, id, dt_from, hours, byday=True): - if not id: - return [(dt_from,dt_from+DateTime.RelativeDateTime(hours=int(hours)*3))] - todo = hours - cycle = 0 - result = [] - maxrecur = 100 - current_hour = dt_from.hour - while (todo>0) and maxrecur: - cr.execute("select hour_from,hour_to from hr_timesheet where dayofweek='%s' and tgroup_id=%s order by hour_from", (dt_from.day_of_week,id)) - for (hour_from,hour_to) in cr.fetchall(): - if (hour_to>current_hour) and (todo>0): - m = max(hour_from, current_hour) - if (hour_to-m)>todo: - hour_to = m+todo - d1 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) - d2 = DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60)) - result.append((d1, d2)) - current_hour = hour_to - todo -= (hour_to - m) - dt_from += DateTime.RelativeDateTime(days=1) - current_hour = 0 - maxrecur -= 1 - return result - -hr_timesheet_group() - - class hr_employee_category(osv.osv): _name = "hr.employee.category" _description = "Employee Category" - + _columns = { 'name' : fields.char("Category", size=64, required=True), 'parent_id': fields.many2one('hr.employee.category', 'Parent Category', select=True), 'child_ids': fields.one2many('hr.employee.category', 'parent_id', 'Child Categories') } - + def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): @@ -107,23 +45,18 @@ class hr_employee_category(osv.osv): return False level -= 1 return True - + _constraints = [ (_check_recursion, 'Error ! You cannot create recursive Categories.', ['parent_id']) ] - + hr_employee_category() class hr_employee(osv.osv): _name = "hr.employee" _description = "Employee" - + _inherits = {'resource.resource':"resource_id"} _columns = { - 'name' : fields.char("Employee's Name", size=128, required=True), - 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the employee record without removing it."), - 'company_id': fields.many2one('res.company', 'Company'), - 'user_id' : fields.many2one('res.users', 'Related User', help='Related user name for an employee to manage his access rights.'), - 'country_id' : fields.many2one('res.country', 'Nationality'), 'birthday' : fields.date("Birthday"), 'ssnid': fields.char('SSN No', size=32, help='Social Security Number'), @@ -134,19 +67,20 @@ class hr_employee(osv.osv): 'address_id': fields.many2one('res.partner.address', 'Working Address'), 'address_home_id': fields.many2one('res.partner.address', 'Home Address'), - 'work_phone': fields.char('Work Phone', size=32), - 'work_email': fields.char('Work Email', size=128), + 'work_phone': fields.related('address_id', 'phone', type='char', string='Work Phone'), + 'work_email': fields.related('address_id', 'email', type='char', string='Work E-mail'), 'work_location': fields.char('Office Location', size=32), 'notes': fields.text('Notes'), 'parent_id': fields.many2one('hr.employee', 'Manager', select=True), 'category_id' : fields.many2one('hr.employee.category', 'Category'), 'child_ids': fields.one2many('hr.employee', 'parent_id','Subordinates'), + 'resource_id': fields.many2one('resource.resource','Resource',ondelete='cascade'), } _defaults = { 'active' : lambda *a: True, } - + def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): @@ -156,26 +90,10 @@ class hr_employee(osv.osv): return False level -= 1 return True - + _constraints = [ (_check_recursion, 'Error ! You cannot create recursive Hierarchy of Employees.', ['parent_id']) ] - -hr_employee() - -class hr_timesheet(osv.osv): - _name = "hr.timesheet" - _description = "Timesheet Line" - _columns = { - 'name' : fields.char("Name", size=64, required=True), - 'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of week'), - 'date_from' : fields.date('Starting date'), - 'hour_from' : fields.float('Work from', size=8, required=True), - 'hour_to' : fields.float("Work to", size=8, required=True), - 'tgroup_id' : fields.many2one("hr.timesheet.group", "Employee's timesheet group", select=True), - } - _order = 'dayofweek, hour_from' -hr_timesheet() - +hr_employee() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/hr/hr_demo.xml b/addons/hr/hr_demo.xml index 3b1a3edfed7..fc01109d86c 100644 --- a/addons/hr/hr_demo.xml +++ b/addons/hr/hr_demo.xml @@ -1,90 +1,90 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - + <!-- Example employee --> - - <record id="timesheet_group1" model="hr.timesheet.group"> + + <record id="timesheet_group1" model="resource.calendar"> <field name="name">38 Hours/Week</field> </record> - + <record id="employee1" model="hr.employee"> <field name="name">Fabien Pinckaers</field> <!--<field name="regime">45</field>--> <field name="user_id" ref="base.user_root"/> <!--<field name="holiday_max">25</field>--> </record> - - <record model="hr.timesheet"> + + <record model="resource.calendar.week"> <field name="name">Monday morning</field> <field name="dayofweek">0</field> <field name="hour_from">08</field> <field name="hour_to">12</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Monday evening</field> <field name="dayofweek">0</field> <field name="hour_from">13</field> <field name="hour_to">18</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Tuesday morning</field> <field name="dayofweek">1</field> <field name="hour_from">08</field> <field name="hour_to">12</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Tuesday evening</field> <field name="dayofweek">1</field> <field name="hour_from">13</field> <field name="hour_to">18</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Wednesday morning</field> <field name="dayofweek">2</field> <field name="hour_from">08</field> <field name="hour_to">12</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Wednesday evening</field> <field name="dayofweek">2</field> <field name="hour_from">13</field> <field name="hour_to">18</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Thursday morning</field> <field name="dayofweek">3</field> <field name="hour_from">08</field> <field name="hour_to">12</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Thursday evening</field> <field name="hour_from">13</field> <field name="hour_to">18</field> <field name="dayofweek">3</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Friday morning</field> <field name="dayofweek">4</field> <field name="hour_from">08</field> <field name="hour_to">12</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - <record model="hr.timesheet"> + <record model="resource.calendar.week"> <field name="name">Friday evening</field> <field name="dayofweek">4</field> <field name="hour_from">13</field> <field name="hour_to">18</field> - <field name="tgroup_id" ref="timesheet_group1"/> + <field name="calendar_id" ref="timesheet_group1"/> </record> - + </data> </openerp> diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml index 2588e21591d..b93e7f658cd 100644 --- a/addons/hr/hr_view.xml +++ b/addons/hr/hr_view.xml @@ -12,8 +12,12 @@ id="menu_hr_configuration" name="Configuration" parent="hr.menu_hr_root" - sequence="50" groups="group_hr_manager"/> - + sequence="50" /> +<!-- <menuitem + id="menu_hr_time" + name="Time Tracking" + parent="hr.menu_hr_root"/> + --> <menuitem id="menu_view_employee_category_configuration_form" parent="hr.menu_hr_configuration" name="Employees" sequence="1"/> <!-- ========== @@ -105,6 +109,7 @@ </record> <!-- <menuitem id="menu_open_view_employee_list" + name="Employees" action="open_view_employee_list" groups="group_hr_manager" parent="menu_hr_human_resources"/> @@ -167,62 +172,6 @@ <field eval="True" name="replace"/> </ir_set> - - <!-- - ============ - Working Time - ============ - --> - <record id="create_group" model="ir.ui.view"> - <field name="name">hr.timesheet.group.form</field> - <field name="model">hr.timesheet.group</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Working Time Category"> - <field name="name" select="1"/> - <field name="manager" select="1"/> - <newline/> - <field colspan="4" name="timesheet_id" nolabel="1" widget="one2many_list"/> - </form> - </field> - </record> - <record id="edit_workgroup" model="ir.actions.act_window"> - <field name="name">Working Schedules</field> - <field name="res_model">hr.timesheet.group</field> - <field name="view_type">form</field> - <field name="view_id" eval="False"/> - </record> - - <menuitem action="edit_workgroup" id="menu_edit_workgroup" name="Work Schedules" parent="menu_view_employee_category_configuration_form" sequence="4"/> - - <record id="view_timesheet_tree" model="ir.ui.view"> - <field name="name">hr.timesheet.tree</field> - <field name="model">hr.timesheet</field> - <field name="type">tree</field> - <field name="arch" type="xml"> - <tree string="Working Time"> - <field name="name"/> - <field name="dayofweek"/> - <field name="hour_from" widget="float_time"/> - <field name="hour_to" widget="float_time"/> - </tree> - </field> - </record> - <record id="view_timesheet_form" model="ir.ui.view"> - <field name="name">hr.timesheet.form</field> - <field name="model">hr.timesheet</field> - <field name="type">form</field> - <field name="arch" type="xml"> - <form string="Working Time"> - <field colspan="4" name="name" select="1"/> - <field name="date_from"/> - <field name="dayofweek" select="1"/> - <field name="hour_from" widget="float_time"/> - <field name="hour_to" widget="float_time"/> - </form> - </field> - </record> - <!-- ============ Employee Category @@ -272,7 +221,6 @@ <menuitem action="open_view_categ_form" id="menu_view_employee_category_form" parent="menu_view_employee_category_configuration_form" sequence="1"/> - <record id="open_view_categ_tree" model="ir.actions.act_window"> <field name="name">Categories structure</field> <field name="res_model">hr.employee.category</field> diff --git a/addons/hr/security/ir.model.access.csv b/addons/hr/security/ir.model.access.csv index d6e8f812590..676a1c36eba 100644 --- a/addons/hr/security/ir.model.access.csv +++ b/addons/hr/security/ir.model.access.csv @@ -1,10 +1,6 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"access_hr_timesheet_group","hr.timesheet.group","model_hr_timesheet_group","hr.group_hr_user",1,0,0,0 "access_hr_employee_category","hr.employee.category","model_hr_employee_category","hr.group_hr_user",1,0,0,0 "access_hr_employee","hr.employee","model_hr_employee","hr.group_hr_user",1,1,1,1 -"access_hr_timesheet_manager","hr.timesheet manager","model_hr_timesheet","hr.group_hr_manager",1,1,1,1 -"access_hr_timesheet","hr.timesheet","model_hr_timesheet","hr.group_hr_user",1,1,1,1 "access_hr_department","hr.department","model_hr_department","hr.group_hr_user",1,0,0,0 -"access_hr_timesheet_group_manager","hr.timesheet.group.manager","model_hr_timesheet_group","hr.group_hr_manager",1,1,1,1 "access_hr_employee_category_manager","hr.employee.category.manager","model_hr_employee_category","hr.group_hr_manager",1,1,1,1 "access_hr_department_manager","hr.department.manager","model_hr_department","hr.group_hr_manager",1,1,1,1 diff --git a/addons/hr_attendance/hr_attendance.py b/addons/hr_attendance/hr_attendance.py index 2161f0886b1..8994f96de4a 100644 --- a/addons/hr_attendance/hr_attendance.py +++ b/addons/hr_attendance/hr_attendance.py @@ -114,7 +114,11 @@ class hr_employee(osv.osv): def attendance_action_change(self, cr, uid, ids, type='action', context={}, dt=False, *args): id = False warning_sign = 'sign' - + + #Special case when button calls this method :type=context + if isinstance(type,dict): + type = type.get('type','action') + if type == 'sign_in': warning_sign = "Sign In" elif type == 'sign_out': @@ -125,7 +129,7 @@ class hr_employee(osv.osv): raise osv.except_osv(_('Warning'), _('You tried to %s with a date anterior to another event !\nTry to contact the administrator to correct attendances.')%(warning_sign,)) res = {'action' : type, 'employee_id' : emp['id']} - + if dt: res['name'] = dt diff --git a/addons/hr_attendance/hr_attendance_view.xml b/addons/hr_attendance/hr_attendance_view.xml index 2511d76b1f5..a39af8cabf4 100644 --- a/addons/hr_attendance/hr_attendance_view.xml +++ b/addons/hr_attendance/hr_attendance_view.xml @@ -88,8 +88,8 @@ <field name="view_mode">tree,form</field> <field name="view_id" ref="view_attendance_reason"/> </record> - <menuitem sequence="9" id="menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/> - <menuitem action="open_view_attendance_reason" id="menu_open_view_attendance_reason" parent="menu_open_view_attendance_reason_config"/> + <menuitem sequence="9" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/> + <menuitem action="open_view_attendance_reason" id="menu_open_view_attendance_reason" parent="hr.menu_open_view_attendance_reason_config"/> <record id="hr_attendance_employee" model="ir.ui.view"> <field name="name">hr.employee.form1</field> @@ -99,8 +99,8 @@ <field name="arch" type="xml"> <field name="parent_id" position="after"> <field name="state"/> - <button name="sign_in" states="absent" string="Sign In" type="object" icon="gtk-go-back"/> - <button name="sign_out" states="present" string="Sign Out" type="object" icon="gtk-go-forward"/> + <button name="attendance_action_change" states="absent" string="Sign In" type="object" icon="gtk-go-back" context="{'type':'sign_in'}"/> + <button name="attendance_action_change" states="present" string="Sign Out" type="object" icon="gtk-go-forward" context="{'type':'sign_out'}"/> </field> </field> </record> diff --git a/addons/hr_contract/hr_contract.py b/addons/hr_contract/hr_contract.py index fead03ac084..7eea1133a6b 100644 --- a/addons/hr_contract/hr_contract.py +++ b/addons/hr_contract/hr_contract.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). # @@ -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 <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## @@ -85,7 +85,7 @@ class hr_contract(osv.osv): 'function' : fields.many2one('res.partner.function', 'Function'), 'date_start' : fields.date('Start Date', required=True), 'date_end' : fields.date('End Date'), - 'working_hours_per_day_id' : fields.many2one('hr.timesheet.group','Working hours per day'), + 'working_hours_per_day_id' : fields.many2one('resource.calendar','Working hours per day'), 'wage_type_id' : fields.many2one('hr.contract.wage.type', 'Wage Type', required=True), 'wage' : fields.float('Wage', required=True), 'notes' : fields.text('Notes'), diff --git a/addons/hr_holidays/hr.py b/addons/hr_holidays/hr.py index e5ca010125a..048b80b0744 100644..100755 --- a/addons/hr_holidays/hr.py +++ b/addons/hr_holidays/hr.py @@ -54,7 +54,7 @@ class hr_holidays_status(osv.osv): return_false = False if context and context.has_key('employee_id'): if not context['employee_id']: - return_false = True + return_false = True employee_id = context['employee_id'] else: employee_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id','=',uid)]) @@ -71,9 +71,9 @@ class hr_holidays_status(osv.osv): 'color_name' : fields.selection([('red', 'Red'), ('lightgreen', 'Light Green'), ('lightblue','Light Blue'), ('lightyellow', 'Light Yellow'), ('magenta', 'Magenta'),('lightcyan', 'Light Cyan'),('black', 'Black'),('lightpink', 'Light Pink'),('brown', 'Brown'),('violet', 'Violet'),('lightcoral', 'Light Coral'),('lightsalmon', 'Light Salmon'),('lavender', 'Lavender'),('wheat', 'Wheat'),('ivory', 'Ivory')],'Color of the status', required=True, help='This color will be used in the leaves summary located in Reporting\Print Summary of Leaves'), 'limit' : fields.boolean('Allow to override Limit', help='If you thick this checkbox, the system will allow, for this section, the employees to take more leaves than the available ones.'), 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the leave type without removing it."), - 'max_leaves' : fields.function(_user_left_days, method=True, string='Maximum Leaves Allowed', help='This value is given by the sum of all holidays requests with a positive value.', multi='user_left_days'), - 'leaves_taken' : fields.function(_user_left_days, method=True, string='Leaves Already Taken', help='This value is given by the sum of all holidays requests with a negative value.', multi='user_left_days'), - 'remaining_leaves' : fields.function(_user_left_days, method=True, string='Remaining Leaves', multi='user_left_days'), + 'max_leaves' : fields.function(_user_left_days, method=True, string='Maximum Leaves Allowed', help='This value is given by the sum of all holidays requests with a positive value.', multi='user_left_days'), + 'leaves_taken' : fields.function(_user_left_days, method=True, string='Leaves Already Taken', help='This value is given by the sum of all holidays requests with a negative value.', multi='user_left_days'), + 'remaining_leaves' : fields.function(_user_left_days, method=True, string='Remaining Leaves', multi='user_left_days'), } _defaults = { @@ -165,7 +165,6 @@ class hr_holidays(osv.osv): _order = 'date_from desc' def create(self, cr, uid, vals, context={}): - print 'create', vals, context if context: if context.has_key('type'): vals['type'] = context['type'] @@ -182,7 +181,7 @@ class hr_holidays(osv.osv): #~ return True #_constraints = [(_check_date, 'Start date should not be greater than end date! ', ['number_of_days'])] - + def onchange_date_from(self, cr, uid, ids, date_to, date_from): result = {} if date_to and date_from: @@ -242,11 +241,10 @@ class hr_holidays(osv.osv): 'state':'validate', } ids2 = self.pool.get('hr.employee').search(cr, uid, [('user_id','=', uid)]) - if ids2: vals['manager_id'] = ids2[0] else: - raise osv.except_osv(_('Warning !'),_('Either there is no Employee defined, or no User attached with it.')) + raise osv.except_osv(_('Warning !'),_('Either there is no Employee defined, or no User attached with it.')) self.write(cr, uid, ids, vals) return True @@ -269,6 +267,16 @@ class hr_holidays(osv.osv): 'number_of_days': nb, 'user_id': user_id }) + vals= { + 'name':record.name, + 'date_from':record.date_from, + 'date_to':record.date_to, + 'calendar_id':record.employee_id.calendar_id.id, + 'company_id':record.employee_id.company_id.id, + 'resource_id':record.employee_id.resource_id.id + } + self.pool.get('resource.calendar.leaves').create(cr,uid,vals) + return True def holidays_refuse(self, cr, uid, ids, *args): @@ -325,7 +333,7 @@ class hr_holidays(osv.osv): 'date_to' : record.date_to, 'notes' : record.notes, 'number_of_days': record.number_of_days, - 'number_of_days_temp': record.number_of_days_temp, + 'number_of_days_temp': record.number_of_days_temp, 'type': record.type, 'allocation_type': record.allocation_type, 'parent_id': record.id, diff --git a/addons/hr_holidays/hr_view.xml b/addons/hr_holidays/hr_view.xml index aec11a98736..b8e6c2af47e 100644 --- a/addons/hr_holidays/hr_view.xml +++ b/addons/hr_holidays/hr_view.xml @@ -258,6 +258,7 @@ <field name="view_mode">tree,form</field> </record> + <menuitem sequence="9" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/> <!--<menuitem action="open_view_holiday_status" id="menu_open_view_holiday_status" @@ -265,7 +266,7 @@ <menuitem name="Leaves Statuses" action="open_view_holiday_status" id="menu_open_view_holiday_status" - parent="hr_attendance.menu_open_view_attendance_reason_config"/> + parent="hr.menu_open_view_attendance_reason_config"/> <!-- Shortcuts --> <act_window name="My Holiday Requests" diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py index 1e484abc1ab..836df03b0f9 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py @@ -639,8 +639,10 @@ class hr_timesheet_sheet_sheet_day(osv.osv): from hr_attendance a LEFT JOIN (hr_timesheet_sheet_sheet s - LEFT JOIN hr_employee e - ON (s.user_id = e.user_id)) + LEFT JOIN resource_resource r + LEFT JOIN hr_employee e + ON (e.resource_id = r.id) + ON (s.user_id = r.user_id)) ON (a.employee_id = e.id AND s.date_to >= date_trunc('day',a.name) AND s.date_from <= a.name) diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index 8d2a65bb725..6e3c8c39004 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -46,7 +46,7 @@ </tree> </field> </record> - +<!-- <record id="hr_timesheet_day_form" model="ir.ui.view"> <field name="name">hr.timesheet.day.form</field> <field name="model">hr_timesheet_sheet.sheet.day</field> @@ -61,7 +61,7 @@ </form> </field> </record> - + <record id="hr_timesheet_day_tree" model="ir.ui.view"> <field name="name">hr.timesheet.day.tree</field> <field name="model">hr_timesheet_sheet.sheet.day</field> @@ -76,7 +76,7 @@ </tree> </field> </record> - +--> <record id="hr_timesheet_sheet_form" model="ir.ui.view"> <field name="name">hr.timesheet.sheet.form</field> <field name="model">hr_timesheet_sheet.sheet</field> @@ -266,7 +266,7 @@ </record> <act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_day" name="Timesheet by Account" res_model="hr_timesheet_sheet.sheet.account" src_model="hr_timesheet_sheet.sheet"/> - <act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_account" name="Timesheet by Day" res_model="hr_timesheet_sheet.sheet.day" src_model="hr_timesheet_sheet.sheet"/> +<!-- <act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_by_account" name="Timesheet by Day" res_model="hr_timesheet_sheet.sheet.day" src_model="hr_timesheet_sheet.sheet"/> --> <act_window domain="[('sheet_id', '=', active_id)]" id="act_hr_timesheet_sheet_sheet_2_hr_analytic_timesheet" name="Timesheet Lines" res_model="hr.analytic.timesheet" src_model="hr_timesheet_sheet.sheet"/> diff --git a/addons/idea/i18n/el.po b/addons/idea/i18n/el.po new file mode 100644 index 00000000000..3ff44e1c7c0 --- /dev/null +++ b/addons/idea/i18n/el.po @@ -0,0 +1,383 @@ +# Greek translation for openobject-addons +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-08-28 16:01+0000\n" +"PO-Revision-Date: 2010-01-18 19:17+0000\n" +"Last-Translator: spyros <Unknown>\n" +"Language-Team: Greek <el@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2010-01-19 04:41+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. module: idea +#: field:idea.category,name:0 +#: field:idea.idea,category_id:0 +msgid "Category" +msgstr "Κατηγορία" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Very Good" +msgstr "Πολύ Καλό" + +#. module: idea +#: view:idea.idea:0 +#: field:idea.idea,stat_vote_ids:0 +msgid "Statistics" +msgstr "Στατιστικά" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_idea_my_idea +#: model:ir.ui.menu,name:idea.menu_idea_idea_my_idea +msgid "My Ideas" +msgstr "Οι ιδέες μου" + +#. module: idea +#: constraint:ir.actions.act_window:0 +msgid "Invalid model name in the action definition." +msgstr "Ιδέα" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Not Voted" +msgstr "Δεν έχει ψήφους" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_idea_open_my +#: model:ir.ui.menu,name:idea.menu_idea_idea_open_my +msgid "My Open Ideas" +msgstr "" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_idea +#: model:ir.ui.menu,name:idea.menu_ideas +#: model:ir.ui.menu,name:idea.menu_ideas1 +msgid "Ideas" +msgstr "Ιδέες" + +#. module: idea +#: field:idea.category,child_ids:0 +msgid "Child Categories" +msgstr "Παράγωγες Κατηγορίες" + +#. module: idea +#: view:idea.idea:0 +msgid "New Idea" +msgstr "Νέα Ιδέα" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_category_tree +#: model:ir.ui.menu,name:idea.menu_idea_category_tree +msgid "Ideas by Categories" +msgstr "Ιδέες Ανά Κατηγορία" + +#. module: idea +#: field:idea.vote,score:0 +#: field:idea.vote.stat,score:0 +msgid "Score" +msgstr "Βαθμολογία" + +#. module: idea +#: selection:idea.idea,state:0 +msgid "Draft" +msgstr "Πρόχειρο" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_vote +msgid "Idea's vote" +msgstr "Βαθμολογία Ιδέας" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_vote_stat +msgid "Statistics on Votes" +msgstr "Στατιστικά Βαθμολογίας" + +#. module: idea +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"Το όνομα του Αντικειμένου πρέπει να ξεκινά με x_ και δεν πρέπει να περιέχει " +"ειδικούς χαρακτήρες!" + +#. module: idea +#: model:ir.model,name:idea.model_idea_category +msgid "Category for an idea" +msgstr "Κατηγορία Για Μια Ιδέα" + +#. module: idea +#: model:ir.module.module,shortdesc:idea.module_meta_information +msgid "Idea Manager" +msgstr "Διαχείρηση Ιδεών" + +#. module: idea +#: model:ir.ui.menu,name:idea.menu_idea_vote_stat +msgid "Vote Statistics" +msgstr "Στατιστικά ψήφων" + +#. module: idea +#: selection:idea.idea,state:0 +msgid "Opened" +msgstr "Ανοιχτές" + +#. module: idea +#: field:idea.idea,state:0 +msgid "Status" +msgstr "Κατάσταση" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Good" +msgstr "Καλή." + +#. module: idea +#: field:idea.idea,description:0 +msgid "Description" +msgstr "Περιγραφή" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Normal" +msgstr "Κανονική" + +#. module: idea +#: model:ir.ui.menu,name:idea.menu_reporting +msgid "Reporting" +msgstr "Αναφορές" + +#. module: idea +#: model:ir.model,name:idea.model_idea_vote_stat +msgid "Idea Votes Statistics" +msgstr "Στατιστικά Ψήφων Ιδέας" + +#. module: idea +#: model:ir.model,name:idea.model_idea_vote +msgid "idea.vote" +msgstr "" + +#. module: idea +#: field:idea.comment,user_id:0 +#: field:idea.vote,user_id:0 +msgid "User" +msgstr "Χρήστης" + +#. module: idea +#: view:idea.idea:0 +msgid "Your comment" +msgstr "Τα σχόλιά σας" + +#. module: idea +#: model:ir.ui.menu,name:idea.menu_config +msgid "Configuration" +msgstr "Παραμετροποίηση" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_category +#: model:ir.ui.menu,name:idea.menu_idea_category +msgid "Categories" +msgstr "" + +#. module: idea +#: view:idea.stat:0 +msgid "stat" +msgstr "" + +#. module: idea +#: field:idea.idea,my_vote:0 +msgid "My Vote" +msgstr "" + +#. module: idea +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "" + +#. module: idea +#: view:idea.vote:0 +msgid "Votes" +msgstr "" + +#. module: idea +#: model:ir.module.module,description:idea.module_meta_information +msgid "" +"This module allows your user to easily and efficiently participate in the " +"innovation of the enterprise. It allows everybody to express ideas about " +"different subjects. Then, others users can comment these ideas and vote for " +"particular ideas. Each idea as a score based on the different votes. The " +"managers can obtain an easy view on best ideas from all the users. Once " +"installed, check the menu 'Ideas' in the 'Tools' main menu." +msgstr "" + +#. module: idea +#: field:idea.comment,create_date:0 +#: field:idea.idea,create_date:0 +msgid "Creation date" +msgstr "" + +#. module: idea +#: field:idea.idea,count_votes:0 +msgid "Count of votes" +msgstr "" + +#. module: idea +#: field:idea.vote.stat,nbr:0 +msgid "Number of Votes" +msgstr "" + +#. module: idea +#: model:ir.model,name:idea.model_idea_idea +msgid "idea.idea" +msgstr "" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_idea_draft_my +#: model:ir.ui.menu,name:idea.menu_idea_idea_draft_my +msgid "My Draft Ideas" +msgstr "" + +#. module: idea +#: field:idea.idea,vote_ids:0 +msgid "Vote" +msgstr "" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Bad" +msgstr "" + +#. module: idea +#: view:idea.idea:0 +#: model:ir.ui.menu,name:idea.menu_idea_idea +msgid "All Ideas" +msgstr "" + +#. module: idea +#: view:idea.comment:0 +#: view:idea.idea:0 +#: field:idea.idea,comment_ids:0 +#: model:ir.model,name:idea.model_idea_comment +msgid "Comments" +msgstr "" + +#. module: idea +#: field:idea.idea,count_comments:0 +msgid "Count of comments" +msgstr "" + +#. module: idea +#: field:idea.idea,title:0 +msgid "Idea Summary" +msgstr "" + +#. module: idea +#: view:idea.category:0 +msgid "Category of ideas" +msgstr "" + +#. module: idea +#: field:idea.category,summary:0 +msgid "Summary" +msgstr "" + +#. module: idea +#: model:ir.actions.act_window,name:idea.action_idea_idea_categ_open +#: model:ir.actions.act_window,name:idea.action_idea_idea_open +#: model:ir.ui.menu,name:idea.menu_idea_idea_open +msgid "Open Ideas" +msgstr "" + +#. module: idea +#: view:idea.idea:0 +#: view:idea.vote.stat:0 +msgid "vote_stat of ideas" +msgstr "" + +#. module: idea +#: view:idea.comment:0 +#: field:idea.comment,content:0 +#: view:idea.idea:0 +msgid "Comment" +msgstr "" + +#. module: idea +#: field:idea.category,parent_id:0 +msgid "Parent Categories" +msgstr "" + +#. module: idea +#: field:idea.idea,user_id:0 +msgid "Creator" +msgstr "" + +#. module: idea +#: model:ir.ui.menu,name:idea.menu_tools +msgid "Tools" +msgstr "" + +#. module: idea +#: field:idea.comment,idea_id:0 +#: view:idea.idea:0 +#: field:idea.vote,idea_id:0 +#: field:idea.vote.stat,idea_id:0 +msgid "Idea" +msgstr "" + +#. module: idea +#: selection:idea.idea,my_vote:0 +#: selection:idea.vote,score:0 +#: selection:idea.vote.stat,score:0 +msgid "Very Bad" +msgstr "" + +#. module: idea +#: selection:idea.idea,state:0 +msgid "Canceled" +msgstr "" + +#. module: idea +#: model:ir.ui.menu,name:idea.menu_idea_vote +msgid "All Votes" +msgstr "" + +#. module: idea +#: view:idea.idea:0 +msgid "Cancel" +msgstr "" + +#. module: idea +#: view:idea.idea:0 +msgid "Close" +msgstr "" + +#. module: idea +#: field:idea.idea,vote_avg:0 +msgid "Average Score" +msgstr "" + +#. module: idea +#: view:idea.idea:0 +msgid "Open" +msgstr "" + +#. module: idea +#: help:idea.idea,description:0 +msgid "Content of the idea" +msgstr "" diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 4d155ea7b8e..df41baf7bc2 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -40,21 +40,14 @@ from tools.translate import _ class mrp_workcenter(osv.osv): _name = 'mrp.workcenter' _description = 'Work Center' + _inherits = {'resource.resource':"resource_id"} _columns = { - 'name': fields.char('Work Center Name', size=64, required=True), - 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the work center without removing it."), - 'type': fields.selection([('machine','Machine'),('hr','Human Resource'),('tool','Tool')], 'Type', required=True), - 'code': fields.char('Code', size=16), - 'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="The normal working time of the workcenter."), +# 'name': fields.char('Work Center Name', size=64, required=True), 'note': fields.text('Description', help="Description of the workcenter. Explain here what's a cycle according to this workcenter."), - 'capacity_per_cycle': fields.float('Capacity per Cycle', help="Number of operations this workcenter can do in parallel. If this workcenter represents a team of 5 workers, the capacity per cycle is 5."), - 'time_cycle': fields.float('Time for 1 cycle (hour)', help="Time in hours for doing one cycle."), 'time_start': fields.float('Time before prod.', help="Time in hours for the setup."), 'time_stop': fields.float('Time after prod.', help="Time in hours for the cleaning."), - 'time_efficiency': fields.float('Efficiency factor', help="Factor to adjust the work center cycle and before and after production durations"), - 'costs_hour': fields.float('Cost per hour'), 'costs_hour_account_id': fields.many2one('account.analytic.account', 'Hour Account', domain=[('type','<>','view')], help="Complete this only if you want automatic analytic accounting entries on production orders."), @@ -63,15 +56,12 @@ class mrp_workcenter(osv.osv): help="Complete this only if you want automatic analytic accounting entries on production orders."), 'costs_journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal'), 'costs_general_account_id': fields.many2one('account.account', 'General Account', domain=[('type','<>','view')]), - 'company_id': fields.many2one('res.company','Company',required=True), +# 'company_id': fields.many2one('res.company','Company',required=True), + 'resource_id': fields.many2one('resource.resource','Resource',ondelete='cascade'), } _defaults = { - 'active': lambda *a: 1, - 'type': lambda *a: 'machine', - 'time_efficiency': lambda *a: 1.0, 'capacity_per_cycle': lambda *a: 1.0, - 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.workcenter', context=c) - } + } mrp_workcenter() @@ -130,7 +120,7 @@ class mrp_routing_workcenter(osv.osv): 'cycle_nbr': fields.float('Number of Cycles', required=True, help="Time in hours for doing one cycle."), 'hour_nbr': fields.float('Number of Hours', required=True, help="Cost per hour"), - 'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade', + 'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade', help="Routing indicates all the workcenters used, for how long and/or cycles." \ "If Routing is indicated then,the third tab of a production order (workcenters) will be automatically pre-completed."), 'note': fields.text('Description') @@ -175,7 +165,7 @@ class mrp_bom(osv.osv): 'name': fields.char('Name', size=64, required=True), 'code': fields.char('Code', size=16), 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the bills of material without removing it."), - 'type': fields.selection([('normal','Normal BoM'),('phantom','Sets / Phantom')], 'BoM Type', required=True, + 'type': fields.selection([('normal','Normal BoM'),('phantom','Sets / Phantom')], 'BoM Type', required=True, help= "If a sub-product is used in several products, it can be useful to create its own BoM."\ "Though if you don't want separated production orders for this sub-product, select Set/Phantom as BoM type."\ "If a Phantom BoM is used for a root product, it will be sold and shipped as a set of components, instead of being produced."), @@ -833,7 +823,7 @@ class mrp_procurement(osv.osv): help='When a procurement is created the state is set to \'Draft\'.\n If the procurement is confirmed, the state is set to \'Confirmed\'.\ \nAfter confirming the state is set to \'Running\'.\n If any exception arises in the order then the state is set to \'Exception\'.\n Once the exception is removed the state becomes \'Ready\'.\n It is in \'Waiting\'. state when the procurement is waiting for another one to finish.'), 'note' : fields.text('Note'), - 'company_id': fields.many2one('res.company','Company',required=True), + 'company_id': fields.many2one('res.company','Company',required=True), } _defaults = { 'state': lambda *a: 'draft', @@ -1205,7 +1195,7 @@ class stock_warehouse_orderpoint(osv.osv): 'qty_multiple': fields.integer('Qty Multiple', required=True, help="The requisition quantity will by rounded up to this multiple."), 'procurement_id': fields.many2one('mrp.procurement', 'Purchase Order'), - 'company_id': fields.many2one('res.company','Company',required=True), + 'company_id': fields.many2one('res.company','Company',required=True), } _defaults = { 'active': lambda *a: 1, diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index fadc0443e0d..40145749a22 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -120,8 +120,8 @@ </group> <notebook colspan="4"> <page string="Work Center"> - <field name="type"/> - <field name="timesheet_id"/> + <field name="resource_type"/> + <field name="calendar_id"/> <separator colspan="4" string="Description"/> <field colspan="4" name="note" nolabel="1"/> <separator colspan="4" string="Capacity Information"/> diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 3767ed3935f..f3cae96266c 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -27,6 +27,6 @@ "access_account_account","account.account mrp_worker","account.model_account_account","mrp.group_mrp_user",1,0,0,0 "access_purchase_order_mrp_worker","purchase.order mrp_worker","purchase.model_purchase_order","mrp.group_mrp_user",1,0,0,0 "access_purchase_order_line_mrp_worker","purchase.order.line mrp_worker","purchase.model_purchase_order_line","mrp.group_mrp_user",1,0,0,0 -"access_hr_timesheet_group_mrp_worker","hr.timesheet.group mrp_worker","hr.model_hr_timesheet_group","mrp.group_mrp_user",1,0,0,0 +"access_hr_timesheet_group_mrp_worker","resource.calendar mrp_worker","resource.model_resource_calendar","mrp.group_mrp_user",1,0,0,0 "access_mrp_procurement_stock_worker","mrp.procurement stock_worker","model_mrp_procurement","stock.group_stock_user",1,1,1,1 "access_mrp_production_stock_worker","mrp.production stock_worker","model_mrp_production","stock.group_stock_user",1,0,0,0 diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py index bf76f834daf..1848470ad15 100644 --- a/addons/mrp_operations/mrp_operations.py +++ b/addons/mrp_operations/mrp_operations.py @@ -60,7 +60,7 @@ class mrp_production_workcenter_line(osv.osv): res[op.id]= False if op.date_planned: d = DateTime.strptime(op.date_planned,'%Y-%m-%d %H:%M:%S') - i = self.pool.get('hr.timesheet.group').interval_get(cr, uid, op.workcenter_id.timesheet_id.id or False, d, op.hour or 0.0) + i = self.pool.get('resource.calendar').interval_get(cr, uid, op.workcenter_id.calendar_id.id or False, d, op.hour or 0.0) if i: res[op.id] = i[-1][1].strftime('%Y-%m-%d %H:%M:%S') else: @@ -204,10 +204,10 @@ class mrp_production(osv.osv): self.pool.get('mrp.production.workcenter.line').write(cr, uid, [wc.id], { 'date_planned':dt.strftime('%Y-%m-%d %H:%M:%S') }, context=context, update=False) - i = self.pool.get('hr.timesheet.group').interval_get( + i = self.pool.get('resource.calendar').interval_get( cr, uid, - wc.workcenter_id.timesheet_id and wc.workcenter_id.timesheet_id.id or False, + wc.workcenter_id.calendar_id and wc.workcenter_id.calendar_id.id or False, dt, wc.hour or 0.0 ) @@ -235,10 +235,10 @@ class mrp_production(osv.osv): if l.production_id and (l.production_id.date_finnished>dt): if l.production_id.state not in ('done','cancel'): for wc in l.production_id.workcenter_lines: - i = self.pool.get('hr.timesheet.group').interval_min_get( + i = self.pool.get('resource.calendar').interval_min_get( cr, uid, - wc.workcenter_id.timesheet_id.id or False, + wc.workcenter_id.calendar_id.id or False, dt, wc.hour or 0.0 ) dt = i[0][0] diff --git a/addons/multi_company/i18n/pt_BR.po b/addons/multi_company/i18n/pt_BR.po new file mode 100644 index 00000000000..d0009b8cdf3 --- /dev/null +++ b/addons/multi_company/i18n/pt_BR.po @@ -0,0 +1,198 @@ +# Brazilian Portuguese translation for openobject-addons +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-12-08 11:46+0000\n" +"PO-Revision-Date: 2010-01-20 00:41+0000\n" +"Last-Translator: pedrobom <pedrobomlimeira@gmail.com>\n" +"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. module: multi_company +#: help:multi_company.default,object_id:0 +msgid "Object affect by this rules" +msgstr "Objeto afetado por esta regra" + +#. module: multi_company +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"O nome do Objeto deve iniciar com x_ e não conter nenhum caracter especial!" + +#. module: multi_company +#: constraint:product.template:0 +msgid "" +"Error: The default UOM and the purchase UOM must be in the same category." +msgstr "" +"Erro: A unidade padrão e a unidade de compra devem ser da mesma categoria." + +#. module: multi_company +#: constraint:res.partner:0 +msgid "The VAT doesn't seem to be correct." +msgstr "O imposto não parece estar correto." + +#. module: multi_company +#: constraint:ir.actions.act_window:0 +msgid "Invalid model name in the action definition." +msgstr "Nome de modelo inválido na definição da ação" + +#. module: multi_company +#: model:res.company,overdue_msg:multi_company.res_company_odoo +#: model:res.company,overdue_msg:multi_company.res_company_oerp_be +#: model:res.company,overdue_msg:multi_company.res_company_oerp_editor +#: model:res.company,overdue_msg:multi_company.res_company_oerp_in +#: model:res.company,overdue_msg:multi_company.res_company_oerp_us +msgid "" +"Would your payment have been carried out after this mail was sent, please " +"consider the present one as void. Do not hesitate to contact our accounting " +"department" +msgstr "" + +#. module: multi_company +#: field:multi_company.default,company_dest_id:0 +msgid "Default Company" +msgstr "Empresa Padrão" + +#. module: multi_company +#: field:multi_company.default,object_id:0 +msgid "Object" +msgstr "Objeto" + +#. module: multi_company +#: model:ir.module.module,shortdesc:multi_company.module_meta_information +#: view:multi_company.default:0 +msgid "Multi Company" +msgstr "Multi Empresa" + +#. module: multi_company +#: model:ir.module.module,description:multi_company.module_meta_information +msgid "" +"This module add the possibility to easily manage \n" +" the default value for each object\n" +" " +msgstr "" +"Este módulo acrescenta a possibilidade de gerenciar facilmente \n" +" o valor padrão para cada objeto\n" +" " + +#. module: multi_company +#: field:multi_company.default,company_id:0 +msgid "Main Company" +msgstr "Empresa principal" + +#. module: multi_company +#: view:multi_company.default:0 +msgid "Condition" +msgstr "Condição" + +#. module: multi_company +#: help:multi_company.default,company_dest_id:0 +msgid "Company to store the current record" +msgstr "Empresa para guardar o registro atual" + +#. module: multi_company +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "XML inválido para Arquitetura da View" + +#. module: multi_company +#: field:multi_company.default,name:0 +msgid "Name" +msgstr "Nome" + +#. module: multi_company +#: constraint:product.template:0 +msgid "Error: UOS must be in a different category than the UOM" +msgstr "" +"Erro: Unidade de venda deve ser de categoria diferente da unidade de medida" + +#. module: multi_company +#: model:product.category,name:multi_company.Odoo1 +msgid "Odoo Offers" +msgstr "" + +#. module: multi_company +#: constraint:res.company:0 +msgid "Error! You can not create recursive companies." +msgstr "Erro! Você não pode criar empresas recursivas." + +#. module: multi_company +#: help:multi_company.default,name:0 +msgid "Name it to easily find a record" +msgstr "" + +#. module: multi_company +#: model:ir.ui.menu,name:multi_company.menu_custom_multicompany +msgid "Multi company" +msgstr "Multi empresa" + +#. module: multi_company +#: model:ir.model,name:multi_company.model_multi_company_default +msgid "multi_company.default" +msgstr "" + +#. module: multi_company +#: help:multi_company.default,company_id:0 +msgid "Company where the user is connected" +msgstr "Empresa onde o usuário está conectado" + +#. module: multi_company +#: model:ir.actions.act_window,name:multi_company.action_inventory_form +msgid "Default Company per Object" +msgstr "Empresa Padrão por Objeto" + +#. module: multi_company +#: field:multi_company.default,expression:0 +msgid "Expression" +msgstr "Expressão" + +#. module: multi_company +#: model:product.template,name:multi_company.product_product_odoo1_product_template +msgid "Odoo Offer" +msgstr "" + +#. module: multi_company +#: field:multi_company.default,sequence:0 +msgid "Sequence" +msgstr "Seqüência" + +#. module: multi_company +#: constraint:product.category:0 +msgid "Error ! You can not create recursive categories." +msgstr "Erro! Você não pode criar categorias recursivas." + +#. module: multi_company +#: constraint:product.product:0 +msgid "Error: Invalid ean code" +msgstr "Erro: Código EAN inválido" + +#. module: multi_company +#: help:multi_company.default,expression:0 +msgid "Expression, must be True to match" +msgstr "" + +#. module: multi_company +#: model:ir.ui.menu,name:multi_company.menu_action_inventory_form +msgid "Default company per Object" +msgstr "Empresa padrão por Objeto" + +#. module: multi_company +#: code:addons/multi_company/multi_company.py:0 +#, python-format +msgid " (copy)" +msgstr " (cópia)" + +#. module: multi_company +#: view:multi_company.default:0 +msgid "Matching" +msgstr "" diff --git a/addons/product/product.py b/addons/product/product.py index 08729a44d7d..b2e70cab81d 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -245,7 +245,7 @@ class product_template(osv.osv): 'description': fields.text('Description',translate=True), 'description_purchase': fields.text('Purchase Description',translate=True), 'description_sale': fields.text('Sale Description',translate=True), - 'type': fields.selection([('product','Stockable Product'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way requisitions are processed. Consumables are stockable products with infinite stock, or for use when you have no inventory management in the system."), + 'type': fields.selection([('product','Stockable Product'),('rima','Rima'),('consu', 'Consumable'),('service','Service')], 'Product Type', required=True, help="Will change the way requisitions are processed. Consumables are stockable products with infinite stock, or for use when you have no inventory management in the system."), 'supply_method': fields.selection([('produce','Produce'),('buy','Buy')], 'Supply method', required=True, help="Produce will generate production order or tasks, according to the product type. Purchase will trigger purchase orders when requested."), 'sale_delay': fields.float('Customer Lead Time', help="This is the average time between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."), 'produce_delay': fields.float('Manufacturing Lead Time', help="Average time to produce this product. This is only for the production order and, if it is a multi-level bill of material, it's only for the level of this product. Different lead times will be summed for all levels and purchase orders."), diff --git a/addons/profile_accounting/i18n/pt_BR.po b/addons/profile_accounting/i18n/pt_BR.po index c239ff94706..62e88b45ace 100644 --- a/addons/profile_accounting/i18n/pt_BR.po +++ b/addons/profile_accounting/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:19+0000\n" -"Last-Translator: Pedro_Maschio <pedro.bicudo@tgtconsult.com.br>\n" +"PO-Revision-Date: 2010-01-19 23:15+0000\n" +"Last-Translator: pedrobom <pedrobomlimeira@gmail.com>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2009-12-16 05:02+0000\n" +"X-Launchpad-Export-Date: 2010-01-20 04:36+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: profile_accounting @@ -104,7 +104,7 @@ msgstr "" #. module: profile_accounting #: field:profile.accounting.config.install_modules_wizard,account_budget:0 msgid "Budgets" -msgstr "" +msgstr "Orçamentos" #. module: profile_accounting #: view:profile.accounting.config.install_modules_wizard:0 @@ -119,7 +119,7 @@ msgstr "" #. module: profile_accounting #: model:ir.module.module,shortdesc:profile_accounting.module_meta_information msgid "Accounting only profile" -msgstr "" +msgstr "Perfil apenas contábil" #. module: profile_accounting #: field:profile.accounting.config.install_modules_wizard,account_analytic_analysis:0 @@ -129,7 +129,7 @@ msgstr "" #. module: profile_accounting #: field:profile.accounting.config.install_modules_wizard,board_document:0 msgid "Document Management" -msgstr "" +msgstr "Gestão de Documentos" #. module: profile_accounting #: model:ir.model,name:profile_accounting.model_profile_accounting_config_install_modules_wizard diff --git a/addons/project/__terp__.py b/addons/project/__terp__.py index 40d41a8fdd1..5c7030a8acb 100644 --- a/addons/project/__terp__.py +++ b/addons/project/__terp__.py @@ -41,7 +41,9 @@ works done on tasks, eso. It is able to render planning, order tasks, eso. "process/task_process.xml", "project_installer.xml", ], - 'demo_xml': ['project_demo.xml'], + 'demo_xml': [ + 'project_demo.xml' + ], 'installable': True, 'active': False, 'certificate': '0075116868317', diff --git a/addons/project/project.py b/addons/project/project.py index 8bd78c1c80f..815f69ecf3d 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -20,18 +20,32 @@ ############################################################################## from lxml import etree -from mx import DateTime -from mx.DateTime import now +import mx.DateTime +import datetime import time from tools.translate import _ - from osv import fields, osv from tools.translate import _ +class project_task_type(osv.osv): + _name = 'project.task.type' + _description = 'Project task type' + _columns = { + 'name': fields.char('Type', required=True, size=64, translate=True), + 'description': fields.text('Description'), + 'sequence': fields.integer('Sequence'), + } + _order = 'sequence' + + _defaults = { + 'sequence': lambda *args: 1 + } +project_task_type() + class project(osv.osv): _name = "project.project" _description = "Project" - + _inherits = {'account.analytic.account':"category_id"} def _complete_name(self, cr, uid, ids, name, args, context): res = {} for m in self.browse(cr, uid, ids, context=context): @@ -73,7 +87,7 @@ class project(osv.osv): tocompute = [project] while tocompute: p = tocompute.pop() - tocompute += p.child_id + tocompute += p.child_ids for i in range(3): s[i] += progress.get(p.id, (0.0,0.0,0.0))[i] res[project.id] = { @@ -90,51 +104,60 @@ class project(osv.osv): raise osv.except_osv(_('Operation Not Permitted !'), _('You can not delete a project with tasks. I suggest you to deactivate it.')) return super(project, self).unlink(cr, uid, ids, *args, **kwargs) _columns = { - 'name': fields.char("Project Name", size=128, required=True), - 'complete_name': fields.function(_complete_name, method=True, string="Project Name", type='char', size=128), +# 'name': fields.char("Project Name", size=128, required=True), +# 'complete_name': fields.function(_complete_name, method=True, string="Project Name", type='char', size=128), 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the project without removing it."), 'category_id': fields.many2one('account.analytic.account','Analytic Account', help="Link this project to an analytic account if you need financial management on projects. It enables you to connect projects with budgets, planning, cost and revenue analysis, timesheets on projects, etc."), 'priority': fields.integer('Sequence'), - 'manager': fields.many2one('res.users', 'Project Manager'), +# 'manager': fields.many2one('res.users', 'Project Manager'), 'warn_manager': fields.boolean('Warn Manager', help="If you check this field, the project manager will receive a request each time a task is completed by his team."), - 'members': fields.many2many('res.users', 'project_user_rel', 'project_id', 'uid', 'Project Members', help="Project's member. Not used in any computation, just for information purpose."), + 'resource_ids': fields.many2many('resource.resource', 'project_resource_rel', 'project_id', 'resource_id', 'Project Members', help="Project's member. Not used in any computation, just for information purpose."), 'tasks': fields.one2many('project.task', 'project_id', "Project tasks"), - 'parent_id': fields.many2one('project.project', 'Parent Project',\ - help="If you have [?] in the name, it means there are no analytic account linked to project."), - 'child_id': fields.one2many('project.project', 'parent_id', 'Subproject'), +# 'parent_id': fields.many2one('project.project', 'Parent Project',\ +# help="If you have [?] in the name, it means there are no analytic account linked to project."), +# 'child_id': fields.one2many('project.project', 'parent_id', 'Subproject'), 'planned_hours': fields.function(_progress_rate, multi="progress", method=True, string='Planned Time', help="Sum of planned hours of all tasks related to this project."), 'effective_hours': fields.function(_progress_rate, multi="progress", method=True, string='Time Spent', help="Sum of spent hours of all tasks related to this project."), 'total_hours': fields.function(_progress_rate, multi="progress", method=True, string='Total Time', help="Sum of total hours of all tasks related to this project."), 'progress_rate': fields.function(_progress_rate, multi="progress", method=True, string='Progress', type='float', help="Percent of tasks closed according to the total of tasks todo."), - 'date_start': fields.date('Starting Date'), - 'date_end': fields.date('Expected End'), - 'partner_id': fields.many2one('res.partner', 'Partner'), - 'contact_id': fields.many2one('res.partner.address', 'Contact'), +# 'partner_id': fields.many2one('res.partner', 'Partner'), +# 'contact_id': fields.many2one('res.partner.address', 'Contact'), 'warn_customer': fields.boolean('Warn Partner', help="If you check this, the user will have a popup when closing a task that propose a message to send by email to the customer."), 'warn_header': fields.text('Mail Header', help="Header added at the beginning of the email for the warning message sent to the customer when a task is closed."), 'warn_footer': fields.text('Mail Footer', help="Footer added at the beginning of the email for the warning message sent to the customer when a task is closed."), - 'notes': fields.text('Notes', help="Internal description of the project."), - 'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"), - 'state': fields.selection([('template', 'Template'), ('open', 'Running'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', required=True, readonly=True, - help='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\'.'), - 'company_id': fields.many2one('res.company', 'Company'), +# 'notes': fields.text('Notes', help="Internal description of the project."), + 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"), +# 'state': fields.selection([('template', 'Template'), ('open', 'Running'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', required=True, readonly=True, +# help='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\'.'), +# 'company_id': fields.many2one('res.company', 'Company'), +# 'timesheet_id': fields.many2one('hr.timesheet.group', 'Working Time', help="Timetable working hours to adjust the gantt diagram report"), + 'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Allowed Task Types'), } _defaults = { 'active': lambda *a: True, - 'manager': lambda object,cr,uid,context: uid, +# 'manager': lambda object,cr,uid,context: uid, 'priority': lambda *a: 1, - 'date_start': lambda *a: time.strftime('%Y-%m-%d'), - 'state': lambda *a: 'open', - 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.project', context=c) +# 'state': lambda *a: 'open', +# 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.project', context=c) } + def _check_dates(self, cr, uid, ids): + leave = self.read(cr, uid, ids[0],['date_start','date']) + if leave['date_start'] and leave['date']: + if leave['date_start'] > leave['date']: + return False + return True - _order = "parent_id,priority,name" _constraints = [ - (check_recursion, 'Error ! You can not create recursive projects.', ['parent_id']) + (_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date']) ] +# _order = "parent_id,priority,name" +# _constraints = [ +# (check_recursion, 'Error ! You can not create recursive projects.', ['parent_id']) +# ] + # toggle activity of projects, their sub projects and their tasks def set_template(self, cr, uid, ids, context={}): res = self.setActive(cr, uid, ids, value=False, context=context) @@ -206,19 +229,33 @@ class project(osv.osv): return True project() -class project_task_type(osv.osv): - _name = 'project.task.type' - _description = 'Project task type' - _columns = { - 'name': fields.char('Type', required=True, size=64, translate=True), - 'description': fields.text('Description'), - } -project_task_type() - class task(osv.osv): _name = "project.task" _description = "Tasks" _date_name = "date_start" + +# def compute_date(self,cr,uid): +# project_id = self.pool.get('project.project').search(cr,uid,[]) +# for i in range(len(project_id)): +# task_ids = self.pool.get('project.task').search(cr,uid,[('project_id','=',project_id[i])]) +# if task_ids: +# task_obj = self.pool.get('project.task').browse(cr,uid,task_ids) +# task_1 = task_obj[0] +# task_1.date_start = self.pool.get('project.project').browse(cr,uid,project_id[i]).date_start +# dt = mx.DateTime.strptime(task_1.date_start,"%Y-%m-%d").strftime("%Y-%m-%d") +# def Project_1(): +# title = "New Project" +# start = dt +# +# def task1(): +# start = dt +# effort = task_1.planned_hours +# title = "Task 1" +## project_1 = BalancedProject(Project_1) +## for t in project_1: +## print 'details:::',t.indent_name(), t.start, t.end, t.effort + + def _str_get(self, task, level=0, border='***', context={}): return border+' '+(task.user_id and task.user_id.name.upper() or '')+(level and (': L'+str(level)) or '')+(' - %.1fh / %.1fh'%(task.effective_hours or 0.0,task.planned_hours))+' '+border+'\n'+ \ border[0]+' '+(task.name or '')+'\n'+ \ @@ -228,12 +265,12 @@ class task(osv.osv): result = {} for task in self.browse(cr, uid, ids, context=context): result[task.id] = self._str_get(task, border='===') - t2 = task.parent_id + t2 = task.parent_ids level = 0 while t2: level -= 1 result[task.id] = self._str_get(t2, level) + result[task.id] - t2 = t2.parent_id + t2 = t2.parent_ids t3 = map(lambda x: (x,1), task.child_ids) while t3: t2 = t3.pop(0) @@ -258,8 +295,19 @@ class task(osv.osv): res[task.id]['delay_hours'] = res[task.id]['total_hours'] - task.planned_hours return res - def onchange_planned(self, cr, uid, ids, planned, effective=0.0): - return {'value':{'remaining_hours': planned-effective}} + def onchange_planned(self, cr, uid, ids, planned, effective, date_start,occupation_rate=0.0): + result = {} + for res in self.browse(cr, uid, ids): + if date_start and planned: + resource_id = self.pool.get('resource.resource').search(cr,uid,[('user_id','=',res.user_id.id)]) + resource_obj = self.pool.get('resource.resource').browse(cr,uid,resource_id)[0] + d = mx.DateTime.strptime(date_start,'%Y-%m-%d %H:%M:%S') + hrs = (planned)/(occupation_rate) + work_times = self.pool.get('resource.calendar').interval_get(cr, uid, resource_obj.calendar_id.id or False, d, hrs or 0.0, resource_obj.id) + result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S') + result['remaining_hours'] = planned-effective + return {'value':result} + def _default_project(self, cr, uid, context={}): if 'project_id' in context and context['project_id']: @@ -275,26 +323,34 @@ class task(osv.osv): default['work_ids'] = [] return super(task, self).copy_data(cr, uid, id, default, context) + def _check_date(self,cr,uid,ids): + for res in self.browse(cr,uid,ids): + if res.date_start and res.date_end: + if res.date_start > res.date_end: + return False + return True + _columns = { 'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the task without removing it."), - 'name': fields.char('Task summary', size=128, required=True), + 'name': fields.char('Task Summary', size=128, required=True), 'description': fields.text('Description'), 'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'), ('0','Very urgent')], 'Importance'), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."), - 'type': fields.many2one('project.task.type', 'Type'), + 'type': fields.many2one('project.task.type', 'Type', readonly=True), 'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True, help='If the task is created the state \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\ \n If the task is over, the states is set to \'Done\'.'), 'date_start': fields.datetime('Starting Date'), + 'date_end': fields.datetime('Ending Date'), 'date_deadline': fields.datetime('Deadline'), 'date_close': fields.datetime('Date Closed', readonly=True), 'project_id': fields.many2one('project.project', 'Project', ondelete='cascade', help="If you have [?] in the project name, it means there are no analytic account linked to this project."), - 'parent_id': fields.many2one('project.task', 'Parent Task'), - 'child_ids': fields.one2many('project.task', 'parent_id', 'Delegated Tasks'), + 'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'), + 'child_ids': fields.many2many('project.task', 'project_task_child_rel', 'task_id', 'child_id', 'Delegated Tasks'), 'history': fields.function(_history_get, method=True, string="Task Details", type="text"), 'notes': fields.text('Notes'), - + 'occupation_rate': fields.float('Occupation Rate', help='The occupation rate fields indicates how much of his time a user is working on a task. A 100% occupation rate means the user works full time on the tasks. The ending date of a task is computed like this: Starting Date + Duration / Occupation Rate.'), 'planned_hours': fields.float('Planned Hours', required=True, help='Estimated time to do the task, usually set by the project manager when the task is in draft state.'), 'effective_hours': fields.function(_hours_get, method=True, string='Hours Spent', multi='hours', store=True, help="Computed using the sum of the task work done."), 'remaining_hours': fields.float('Remaining Hours', digits=(16,4), help="Total remaining time, can be re-estimated periodically by the assignee of the task."), @@ -318,6 +374,7 @@ class task(osv.osv): 'active': lambda *a: True, 'date_start': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'project_id': _default_project, + 'occupation_rate':lambda *a: '1', 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c) } _order = "sequence, priority, date_deadline, id" @@ -359,24 +416,24 @@ class task(osv.osv): for task in tasks: project = task.project_id if project: - if project.warn_manager and project.manager and (project.manager.id != uid): + if project.warn_manager and project.user_id and (project.user_id.id != uid): request.create(cr, uid, { 'name': _("Task '%s' closed") % task.name, 'state': 'waiting', 'act_from': uid, - 'act_to': project.manager.id, + 'act_to': project.user_id.id, 'ref_partner_id': task.partner_id.id, 'ref_doc1': 'project.task,%d'% (task.id,), 'ref_doc2': 'project.project,%d'% (project.id,), }) self.write(cr, uid, [task.id], {'state': 'done', 'date_close':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0}) - if task.parent_id and task.parent_id.state in ('pending','draft'): + if task.parent_ids and task.parent_ids.state in ('pending','draft'): reopen = True - for child in task.parent_id.child_ids: + for child in task.parent_ids.child_ids: if child.id != task.id and child.state not in ('done','cancelled'): reopen = False if reopen: - self.do_reopen(cr, uid, [task.parent_id.id]) + self.do_reopen(cr, uid, [task.parent_ids.id]) return True def do_reopen(self, cr, uid, ids, *args): @@ -384,12 +441,12 @@ class task(osv.osv): tasks = self.browse(cr, uid, ids) for task in tasks: project = task.project_id - if project and project.warn_manager and project.manager.id and (project.manager.id != uid): + if project and project.warn_manager and project.user_id.id and (project.user_id.id != uid): request.create(cr, uid, { 'name': _("Task '%s' set in progress") % task.name, 'state': 'waiting', 'act_from': uid, - 'act_to': project.manager.id, + 'act_to': project.user_id.id, 'ref_partner_id': task.partner_id.id, 'ref_doc1': 'project.task,%d' % task.id, 'ref_doc2': 'project.project,%d' % project.id, @@ -403,12 +460,12 @@ class task(osv.osv): tasks = self.browse(cr, uid, ids) for task in tasks: project = task.project_id - if project.warn_manager and project.manager and (project.manager.id != uid): + if project.warn_manager and project.user_id and (project.user_id.id != uid): request.create(cr, uid, { 'name': _("Task '%s' cancelled") % task.name, 'state': 'waiting', 'act_from': uid, - 'act_to': project.manager.id, + 'act_to': project.user_id.id, 'ref_partner_id': task.partner_id.id, 'ref_doc1': 'project.task,%d' % task.id, 'ref_doc2': 'project.project,%d' % project.id, @@ -431,6 +488,25 @@ class task(osv.osv): self.write(cr, uid, ids, {'state': 'pending'}) return True + def next_type(self, cr, uid, ids, *args): + for typ in self.browse(cr, uid, ids): + typeid = typ.type.id + types = map(lambda x:x.id, typ.project_id.type_ids) + if types: + if typeid and typeid in types and types.index(typeid) != len(types)-1 : + index = types.index(typeid) + self.write(cr, uid, typ.id, {'type': types[index+1]}) + return True + + def prev_type(self, cr, uid, ids, *args): + for typ in self.browse(cr, uid, ids): + typeid = typ.type.id + types = map(lambda x:x.id, typ.project_id.type_ids) + if types: + if typeid and typeid in types and types.index(typeid) != 0 : + index = types.index(typeid) + self.write(cr, uid, typ.id, {'type': types[index-1]}) + return True task() @@ -508,10 +584,13 @@ class message(osv.osv): message() def _project_get(self, cr, uid, context={}): + if uid==1: + ids = self.pool.get('project.project').search(cr, uid, []) + res = self.pool.get('project.project').read(cr, uid, ids, ['id','name'], context) + return [(str(r['id']),r['name']) for r in res] cr.execute("""SELECT to_char(id, '99999'),name FROM project_project where manager=%s OR id IN (SELECT project_id from project_user_rel where uid=%s)""" % (uid, uid)) - projects = cr.fetchall() - return projects + return cr.fetchall() class users(osv.osv): _inherit = 'res.users' @@ -522,4 +601,4 @@ class users(osv.osv): users() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index e762d3874ba..7b5d565fead 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -9,23 +9,30 @@ <field name="project_time_mode_id" ref="product.uom_hour"></field> </record> - <record id="project_tt_analysis" model="project.task.type"> - <field name="name">Analysis</field> + <!-- Task Types --> + <record id="project_tt_specification" model="project.task.type"> + <field name="sequence">1</field> + <field name="name">Specification</field> </record> - <record id="project_tt_feature" model="project.task.type"> - <field name="name">New Feature</field> + <record id="project_tt_development" model="project.task.type"> + <field name="sequence">2</field> + <field name="name">Development</field> </record> - <record id="project_tt_quote" model="project.task.type"> - <field name="name">Quotation</field> + <record id="project_tt_testing" model="project.task.type"> + <field name="sequence">3</field> + <field name="name">Testing</field> </record> - <record id="project_tt_bug" model="project.task.type"> - <field name="name">Bug</field> + <record id="project_tt_merge" model="project.task.type"> + <field name="sequence">4</field> + <field name="name">Merge</field> </record> - + + <!-- Projects --> <record id="project_project_9" model="project.project"> <field name="warn_manager">1</field> <field name="name">Open ERP Integration</field> <field name="manager" ref="base.user_root"/> + <field eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge')])]" name="type_ids"/> </record> <record id="project_project_21" model="project.project"> <field name="warn_manager">1</field> @@ -34,6 +41,7 @@ <field name="name">Study + Prototype</field> <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> <field name="manager" ref="base.user_root"/> + <field eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development')])]" name="type_ids"/> </record> <record id="project_project_22" model="project.project"> <field name="priority">20</field> @@ -41,6 +49,7 @@ <field name="name">Specific Developements</field> <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> <field name="manager" ref="base.user_root"/> + <field eval="[(6, 0, [ref('project_tt_specification'), ref('project_tt_development')])]" name="type_ids"/> </record> <record id="project_project_23" model="project.project"> <field name="priority">30</field> @@ -48,12 +57,14 @@ <field name="name">Install, data import, configuration</field> <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> <field name="manager" ref="base.user_root"/> + <field eval="[(6, 0, [ref('project_tt_development')])]" name="type_ids"/> </record> + <!-- Tasks --> <record id="project_task_116" model="project.task"> <field name="planned_hours">38.0</field> <field name="remaining_hours">38.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field name="user_id" ref="base.user_root"/> <field name="project_id" ref="project_project_22"/> <field name="description">BoM, After sales returns, interventions. Tracability.</field> @@ -62,7 +73,7 @@ <record id="project_task_130" model="project.task"> <field name="planned_hours">16.0</field> <field name="remaining_hours">16.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field model="res.users" name="user_id" search="[('login','=','demo')]"/> <field name="project_id" ref="project_project_23"/> <field name="name">Data importation + Doc</field> @@ -70,7 +81,7 @@ <record id="project_task_131" model="project.task"> <field name="planned_hours">16.0</field> <field name="remaining_hours">16.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field model="res.users" name="user_id" search="[('login','=','demo')]"/> <field name="project_id" ref="project_project_23"/> <field name="name">Modifications asked by the customer.</field> @@ -78,7 +89,7 @@ <record id="project_task_184" model="project.task"> <field name="planned_hours">16.0</field> <field name="remaining_hours">16.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field model="res.users" name="user_id" search="[('login','=','demo')]"/> <field name="priority">0</field> <field name="project_id" ref="project_project_21"/> @@ -88,7 +99,7 @@ <field name="sequence">15</field> <field name="planned_hours">8.0</field> <field name="remaining_hours">8.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field model="res.users" name="user_id" search="[('login','=','demo')]"/> <field name="project_id" ref="project_project_21"/> <field name="name">Internal testing + Software Install</field> @@ -98,7 +109,7 @@ <field name="sequence">17</field> <field name="planned_hours">16.0</field> <field name="remaining_hours">16.0</field> - <field name="type" ref="project_tt_feature"/> + <field name="type" ref="project_tt_development"/> <field model="res.users" name="user_id" search="[('login','=','demo')]"/> <field name="priority">2</field> <field name="state">open</field> diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index c7cfee65d20..cee6d9ac2e2 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -30,11 +30,11 @@ <field name="arch" type="xml"> <form string="Project"> <group colspan="6" col="6"> - <field name="name" select="1"/> - <field name="parent_id"/> - <field name="manager" select="1"/> + <field name="name" string="Project Name" select="1"/> + <field name="parent_id" string="Parent Project"/> + <field name="user_id" string="Project Manager" select="1"/> <field name="date_start"/> - <field name="date_end"/> + <field name="date"/> <field name="progress_rate" widget="progressbar"/> </group> <notebook colspan="4"> @@ -42,14 +42,14 @@ <field name="warn_manager"/> <field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/> <field name="priority"/> - <field name="timesheet_id"/> + <field name="resource_calendar_id"/> <field name="active" select="2"/> <field name="planned_hours" widget="float_time"/> <field name="effective_hours" widget="float_time"/> - <field name="category_id" select="2" context="{'default_name':name}"/> + <newline/> <separator colspan="4" string="Project's members"/> - <field colspan="4" name="members" nolabel="1"/> + <field colspan="4" name="resource_ids" nolabel="1"/> <group col="9" colspan="8"> <field name="state" select="1"/> <button name="set_template" string="Set as Template" type="object" states="open" icon="gtk-convert"/> @@ -83,25 +83,12 @@ <label string="Date Stop: %%(date_stop)s"/> </group> </page> - <page string="Tasks"> - <field name="tasks" nolabel="1" attrs="{'readonly':[('state','in',['cancelled','done'])]}"> - <tree colors="grey:state in ('cancelled','done');blue:remaining_hours<0;red:bool(date_deadline) and (date_deadline<current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks"> - <!-- <tree string="Tasks">--> - <field name="sequence"/> - <field name="name"/> - <field name="user_id"/> - <field name="date_deadline"/> - <field name="planned_hours" sum="Planned" widget="float_time"/> - <field name="delay_hours" sum="Delay" widget="float_time"/> - <field name="progress" widget="progressbar"/> - <field name="priority"/> - <field name="state"/> - <field name="remaining_hours" invisible="1"/> - </tree> - </field> + <page string="Tasks" groups="base.group_extended"> + <separator string="Task Types"/> + <field nolabel="1" name="type_ids" colspan="4"/> </page> <page string="Notes"> - <field colspan="4" name="notes" nolabel="1"/> + <field colspan="4" name="description" nolabel="1"/> </page> </notebook> <newline/> @@ -115,9 +102,9 @@ <field name="priority" eval="5"/> <field name="arch" type="xml"> <tree string="Projects"> - <field name="complete_name"/> - <field name="manager"/> - <field name="partner_id"/> + <field name="complete_name" string="Project Name"/> + <field name="user_id" string="Project Manager"/> + <field name="partner_id" string="Partner"/> <field name="effective_hours" widget="float_time"/> <field name="total_hours" widget="float_time"/> <field name="state"/> @@ -132,11 +119,11 @@ <field name="arch" type="xml"> <search string="Search Project"> <group col='8' colspan='4'> - <filter icon="terp-project" string="My Projects" domain="[('manager', '=', uid)]" help="My Projects"/> + <filter icon="terp-project" string="My Projects" domain="[('user_id', '=', uid)]" help="My Projects"/> <filter icon="terp-project" string="Templates" domain="[('state','=','template')]" help="Template Projects"/> <separator orientation="vertical"/> - <field name="name" select='1'/> - <field name="partner_id" select='1'/> + <field name="name" string="Project Name" select='1'/> + <field name="partner_id" string="Partner" select='1'/> <field name="state" select="1"/> </group> </search> @@ -147,12 +134,12 @@ <field name="name">project.project.tree</field> <field name="model">project.project</field> <field name="type">tree</field> - <field name="field_parent">child_id</field> + <field name="field_parent">child_ids</field> <field name="arch" type="xml"> <tree string="Projects"> - <field name="name"/> - <field name="manager"/> - <field name="partner_id"/> + <field name="name" string="Project Name"/> + <field name="user_id" string="Project Manager"/> + <field name="partner_id" string="Partner"/> <field name="planned_hours" widget="float_time"/> <field name="total_hours" widget="float_time"/> <field name="effective_hours" widget="float_time"/> @@ -216,11 +203,11 @@ <field name="name">project.project.tree</field> <field name="model">project.project</field> <field name="type">tree</field> - <field name="field_parent">child_id</field> + <field name="field_parent">child_ids</field> <field name="arch" type="xml"> <tree string="My projects"> - <field name="name"/> - <field name="partner_id"/> + <field name="name" string="Project Name"/> + <field name="partner_id" string="Partner"/> <field name="planned_hours" widget="float_time"/> <field name="effective_hours" widget="float_time"/> <field name="progress_rate" widget="progressbar"/> @@ -281,7 +268,10 @@ <field name="name" select="1"/> <field name="project_id" required="1" select="1"/> <field name="total_hours" widget="float_time"/> + <field name="date_start"/> <field name="date_deadline" select="2"/> + <field name="occupation_rate"/> + <field name="date_end"/> <field name="user_id" select="1"/> <field name="progress" widget="progressbar"/> </group> @@ -292,7 +282,7 @@ name="planned_hours" widget="float_time" attrs="{'readonly':[('state','!=','draft')]}" - on_change="onchange_planned(planned_hours,effective_hours)"/> + on_change="onchange_planned(planned_hours,effective_hours,date_start,occupation_rate)"/> <field name="remaining_hours" select="2" widget="float_time" attrs="{'readonly':[('state','!=','draft')]}" colspan="2"/> <button name="%(action_config_compute_remaining)d" string="Review" type="action" colspan="1" target="new" states="open,pending" icon="gtk-edit"/> </group> @@ -304,10 +294,10 @@ <field colspan="4" name="description" nolabel="1" select="2" attrs="{'readonly':[('state','=','done')]}" widget="text_wiki"/> <field colspan="4" name="work_ids" nolabel="1" attrs="{'readonly':[('state','in',['draft','done'])]}"> <tree string="Task Work" editable="top"> - <field name="date" /> - <field name="user_id" /> - <field name="hours" widget="float_time" /> <field name="name" /> + <field name="hours" widget="float_time" /> + <field name="user_id" /> + <field name="date" /> </tree> </field> <newline/> @@ -320,12 +310,12 @@ <button groups="base.group_extended" name="%(wizard_delegate_task)d" states="pending,open" string="Delegate" type="action" icon="gtk-sort-descending"/> <button name="%(wizard_close_task)d" states="pending,open" string="Done" type="action" icon="gtk-jump-to"/> <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel"/> - </group> </page> <page groups="base.group_extended" string="Delegations"> - <field name="parent_id"/> - <newline/> + <separator string="Parent Tasks" colspan="4"/> + <field colspan="4" height="150" name="parent_ids" nolabel="1"/> + <separator string="Delegated tasks" colspan="4"/> <field colspan="4" height="150" name="child_ids" nolabel="1" attrs="{'readonly':[('state','!=','draft')]}"> <tree string="Delegated tasks"> <field name="name"/> @@ -339,6 +329,7 @@ </field> <field colspan="4" name="history" nolabel="1"/> </page> + <page groups="base.group_extended" string="Extra Info" attrs="{'readonly':[('state','=','done')]}"> <group colspan="2" col="2"> <separator string="Planning" colspan="2"/> @@ -347,14 +338,17 @@ </group> <group colspan="2" col="2"> <separator string="Dates" colspan="2"/> - <field name="date_start" select="2"/> <field name="date_close" select="2"/> </group> <separator string="Miscelleanous" colspan="4"/> - <field name="type" widget="selection"/> + <field name="partner_id" select="2"/> <field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/> + <group col="4" colspan="2"> + <field name="type" widget="selection" /> + <button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Type"/> + <button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Type"/> + </group> <field name="active" select="2"/> - <field name="partner_id" select="2"/> <separator colspan="4" string="Notes"/> <field colspan="4" name="notes" nolabel="1"/> </page> @@ -369,12 +363,14 @@ <field eval="2" name="priority"/> <field name="arch" type="xml"> <tree colors="grey:state in ('cancelled','done');blue:remaining_hours<0;red:bool(date_deadline) and (date_deadline<current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks"> - <field name="sequence" string="Seq."/> + <field name="sequence" invisible="1"/> <field name="name"/> <field name="project_id" icon="gtk-indent"/> <field name="user_id"/> <field name="date_deadline"/> <field name="remaining_hours" widget="float_time"/> + <field name="type"/> + <button name="next_type" states="draft,open,pending" string="Change Type" type="object" icon="gtk-go-forward" help="Change Type"/> <field name="progress" widget="progressbar"/> <field name="state"/> <button name="do_open" states="pending,draft" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state"/> @@ -474,19 +470,21 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Task Edition"> - <group col="8" colspan="4"> + <group col="20" colspan="4"> + <filter string="By Users" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> + <filter string="By Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/> + <filter string="By Type" icon="terp-project" domain="[]" context="{'group_by':'type'}"/> + <separator orientation="vertical"/> <filter string="Draft" domain="[('state','=','draft')]" help="Draft Tasks" icon="terp-project"/> - <filter string="Open" domain="[('state','=','open')]" help="Open Tasks" icon="terp-project"/> + <filter string="In Progress" domain="[('state','=','open')]" help="Open Tasks" icon="terp-project"/> <filter string="Pending" domain="[('state','=','pending')]" help="Pending Tasks" icon="terp-project"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="project_id" select="1" widget="selection"> <filter domain="[('manager_id','=',False)]" help="Unassigned Project" icon="terp-project"/> </field> - </group> - <group col="4" colspan="1"> <field name="user_id" select="1" widget="selection"> - <filter domain="[('user_id','=',uid)]" help="My Tasks" icon="gtk-execute"/> + <filter domain="[('user_id','=',uid)]" help="My Tasks" icon="gtk-execute" default="1"/> <filter domain="[('user_id','=',False)]" help="Unassigned Tasks" icon="gtk-execute" separator="1"/> </field> </group> @@ -495,70 +493,18 @@ </record> <record id="action_view_task" model="ir.actions.act_window"> - <field name="name">All Tasks</field> + <field name="name">Tasks</field> <field name="res_model">project.task</field> <field name="view_type">form</field> <field name="view_mode">tree,form,calendar,gantt,graph</field> <field eval="False" name="view_id"/> <field eval="True" name="filter"/> + <field name="view_id" ref="view_task_tree2"/> <field name="search_view_id" ref="view_task_search_form"/> </record> <!--<menuitem action="action_view_task" id="menu_action_view_task" parent="project.menu_tasks"/> --> <menuitem action="action_view_task" id="menu_action_view_task" parent="project.menu_project_management" name="Tasks"/> - <record id="action_view_task_department" model="ir.actions.act_window"> - <field name="name">My Department Tasks</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,gantt,graph</field> - <field eval="True" name="filter"/> - <field name="domain">[('user_id', 'child_of', [uid])]</field> - <field eval="True" name="filter"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - - <record id="action_view_task5_departments_pending" model="ir.actions.act_window"> - <field name="name">My Department's Pending Tasks</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph</field> - <field name="domain">[('user_id', 'child_of', [uid]),('state','=','pending')]</field> - <field name="view_id" ref="my_pending_task"/> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - - <record id="action_view_task5_departments_prog" model="ir.actions.act_window"> - <field name="name">My Department's Current Tasks</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph</field> - <field eval="True" name="filter"/> - <field name="domain">[('user_id', 'child_of', [uid]),('state','in',('open','draft'))]</field> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - - <record id="action_view_task5_departments_prog_prog" model="ir.actions.act_window"> - <field name="name">My Department's Tasks in Progress</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph</field> - <field name="domain">[('user_id', 'child_of', [uid]),('state','=','open')]</field> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - - <record id="action_view_task5_departments_prog_draft" model="ir.actions.act_window"> - <field name="name">My Department's Draft Tasks</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph</field> - <field name="domain">[('user_id', 'child_of', [uid]),('state','=','draft')]</field> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - <record id="action_view_task_overpassed_draft" model="ir.actions.act_window"> <field name="name">Overpassed Tasks</field> <field name="res_model">project.task</field> @@ -569,26 +515,6 @@ <field name="search_view_id" ref="view_task_search_form"/> </record> - <record id="action_view_task6_prog" model="ir.actions.act_window"> - <field name="name">Tasks in Progress</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph,gantt</field> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - <field name="domain">[('state','=','open')]</field> - </record> -menu_main - <record id="action_view_task7" model="ir.actions.act_window"> - <field name="name">Unassigned Tasks</field> - <field name="res_model">project.task</field> - <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,graph,gantt</field> - <field name="domain">[('user_id', '=', False)]</field> - <field name="filter" eval="True"/> - <field name="search_view_id" ref="view_task_search_form"/> - </record> - <!-- Opening task when double clicking on project --> <record id="dblc_proj" model="ir.actions.act_window"> <field name="res_model">project.task</field> @@ -613,7 +539,8 @@ menu_main <field name="type">form</field> <field name="arch" type="xml"> <form string="Task type"> - <field colspan="4" name="name" select="1"/> + <field name="name" select="1"/> + <field name="sequence"/> <field colspan="4" name="description" select="1"/> </form> </field> @@ -624,6 +551,7 @@ menu_main <field name="type">tree</field> <field name="arch" type="xml"> <tree string="Task type"> + <field name="sequence"/> <field name="name"/> </tree> </field> @@ -636,7 +564,7 @@ menu_main </record> <menuitem action="open_task_type_form" id="menu_task_types" parent="project.menu_definitions"/> - <act_window domain="[('manager', '=', active_id)]" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/> + <act_window domain="[('user_id', '=', active_id)]" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/> <act_window domain="[('project_id', '=', active_id)]" @@ -650,7 +578,7 @@ menu_main <act_window domain="[('project_id', '=', active_id)]" id="act_project_project_2_project_task_all" - name="All Tasks" + name="Tasks" res_model="project.task" src_model="project.project" view_mode="tree,form,calendar,graph" diff --git a/addons/project/project_wizard.xml b/addons/project/project_wizard.xml index d86781ab4ab..3e441e3f8f0 100644 --- a/addons/project/project_wizard.xml +++ b/addons/project/project_wizard.xml @@ -3,6 +3,5 @@ <data> <wizard id="wizard_close_task" menu="False" model="project.task" name="project.task.close" string="Close Task"/> <wizard id="wizard_delegate_task" menu="False" model="project.task" name="project.task.delegate" string="Delegate Task"/> - <!-- <wizard id="wizard_attachment_task" model="project.task" name="project.task.attachment" string="All Attachments"/> --> </data> </openerp> diff --git a/addons/project/report/_date_compute.py b/addons/project/report/_date_compute.py index cf900d2d08b..1d44bd5c3cf 100644 --- a/addons/project/report/_date_compute.py +++ b/addons/project/report/_date_compute.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). # @@ -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 <http://www.gnu.org/licenses/>. +# along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## @@ -58,7 +58,7 @@ def _compute_tasks(cr, uid, task_list, date_begin): # Compute the closing date of the task tasks[task.id] = [] - res = pooler.get_pool(cr.dbname).get('hr.timesheet.group').interval_get(cr, uid, task.project_id.timesheet_id.id, date_start, task.remaining_hours) + res = pooler.get_pool(cr.dbname).get('resource.calendar').interval_get(cr, uid, task.project_id.resource_calendar_id.id, date_start, task.remaining_hours) for (d1,d2) in res: tasks[task.id].append((d1, d2, task.name, task.user_id.login)) date_close = tasks[task.id][-1][1] @@ -72,7 +72,7 @@ def _compute_tasks(cr, uid, task_list, date_begin): def _compute_project(cr, uid, project, date_begin): tasks, last_date = _compute_tasks(cr, uid, project.tasks, date_begin) - for proj in project.child_id: + for proj in project.child_ids: d0 = DateTime.strptime(proj.date_start,'%Y-%m-%d') if d0 > last_date: last_date = d0 diff --git a/addons/project/wizard/__init__.py b/addons/project/wizard/__init__.py index 997b02c90f9..4618faf8463 100644 --- a/addons/project/wizard/__init__.py +++ b/addons/project/wizard/__init__.py @@ -21,7 +21,6 @@ import close_task import task_delegate -import task_attachment # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/wizard/task_attachment.py b/addons/project/wizard/task_attachment.py deleted file mode 100644 index 0d3c88e4874..00000000000 --- a/addons/project/wizard/task_attachment.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). -# -# 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 <http://www.gnu.org/licenses/>. -# -############################################################################## - -import wizard -import pooler - -'''View the attachments of the parent + children tasks''' - -def _show_attachment(self, cr, uid, data, context): - task_obj = pooler.get_pool(cr.dbname).get('project.task') - task_browse_id = task_obj.browse(cr, uid, [data['id']], context)[0] - attachment_list = [child_id.id for child_id in task_browse_id.child_ids] - attachment_list.extend([task_browse_id.parent_id.id]) - value = { - 'domain': [('res_model','=',data['model']),('res_id','in',attachment_list)], - 'name': 'Attachments', - 'view_type': 'form', - 'view_mode': 'tree,form', - 'res_model': 'ir.attachment', - 'context': { }, - 'type': 'ir.actions.act_window' - } - return value -class wizard_attachment(wizard.interface): - states = { - 'init': { - 'actions': [], - 'result': {'type':'action', 'action':_show_attachment, 'state': 'end'}, - }, - } -wizard_attachment('project.task.attachment') diff --git a/addons/project_calendar/__init__.py b/addons/project_calendar/__init__.py index 0f6717fccc8..6cd8cd53857 100644 --- a/addons/project_calendar/__init__.py +++ b/addons/project_calendar/__init__.py @@ -20,6 +20,5 @@ ############################################################################## import project_calendar -import wizard # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_calendar/project_calendar.py b/addons/project_calendar/project_calendar.py index f9722e26794..11a6c080c31 100644 --- a/addons/project_calendar/project_calendar.py +++ b/addons/project_calendar/project_calendar.py @@ -19,301 +19,14 @@ # ############################################################################## -from caldav import common -from datetime import datetime from osv import fields, osv -from service import web_services -import base64 -import re -import time class project_task(osv.osv): - _inherit = "project.task" - + _name = "project.task" + _inherit = ["calendar.todo", "project.task"] _columns = { - 'class': fields.selection([('public', 'Public'), ('private', 'Private'), \ - ('confidential', 'Confidential')], 'Mark as'), - 'location': fields.char('Location', size=264, help="Location of Task"), - '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"), - 'attendee_ids': fields.many2many('calendar.attendee', 'task_attendee_rel', 'task_id', 'attendee_id', 'Attendees'), - 'caldav_url': fields.char('Calendar URL', size=34), - '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'), - } - - __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 onchange_rrule_type(self, cr, uid, ids, type, *args, **argv): - if type == 'none': - return {'value': {'rrule': ''}} - if type == 'custom': - return {} - rrule = self.pool.get('calendar.custom.rrule') - rrulestr = rrule.compute_rule_string(cr, uid, {'freq': type.upper(), \ - 'interval': 1}) - return {'value': {'rrule': rrulestr}} - - def import_cal(self, cr, uid, data, context={}): - file_content = base64.decodestring(data) - todo_obj = self.pool.get('basic.calendar.todo') - todo_obj.__attribute__.update(self.__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 - is_exists = common.uid2openobjectid(cr, val['id'], self._name) - val.pop('id') - if is_exists: - self.write(cr, uid, [is_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_obj.__attribute__.update(self.__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'}) - caendar_val = ical.serialize() - caendar_val = caendar_val.replace('"', '').strip() - return caendar_val - - 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 t.id, t.rrule, t.date_start, t.exdate \ - from project_task t\ - where t.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_start'], "%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 = common.real_id2caldav_id(data['id'], data['date_start']) - 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_start'], "%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 = common.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_start', unicode('date_start')): - args_without_date.append(arg) - else: - if arg[1] in ('>', '>='): - start_date = arg[2] - elif arg[1] in ('<', '<='): - until_date = arg[2] - res = super(project_task, 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 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, common.caldav_id2real_id(x)), select) - result = [] - if fields and 'date_start' not in fields: - fields.append('date_start') - for caldav_id, real_id in select: - res = super(project_task, self).read(cr, uid, real_id, fields=fields, context=context, load=load) - ls = common.caldav_id2real_id(caldav_id, with_date=True) - if not isinstance(ls, (str, int, long)) and len(ls) >= 2: - res['date_start'] = ls[1] - res['id'] = caldav_id - - result.append(res) - if isinstance(ids, (str, int, long)): - return result and result[0] or False - return result - - 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 = common.caldav_id2real_id(id) - if not id in new_ids: - new_ids.append(id) - res = super(project_task, 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_start') - 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:common.caldav_id2real_id(x), select) - res = super(project_task, 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 copy(self, cr, uid, id, default=None, context={}): - res = super(project_task, self).copy(cr, uid, common.caldav_id2real_id(id), default, context) - alarm_obj = self.pool.get('res.alarm') - alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date_start') - return res - - def unlink(self, cr, uid, ids, context=None): - for id in ids: - if len(str(id).split('-')) > 1: - date_new = time.strftime("%Y-%m-%d %H:%M:%S", \ - time.strptime(str(str(id).split('-')[1]), "%Y%m%d%H%M%S")) - for record in self.read(cr, uid, [common.caldav_id2real_id(id)], \ - ['date_start', 'rrule', 'exdate']): - if record['rrule']: - exdate = (record['exdate'] and (record['exdate'] + ',') or '') + \ - ''.join((re.compile('\d')).findall(date_new)) + 'Z' - if record['date_start'] == date_new: - self.write(cr, uid, [common.caldav_id2real_id(id)], {'exdate': exdate}) - else: - ids = map(lambda x:common.caldav_id2real_id(x), ids) - return super(project_task, self).unlink(cr, uid, ids) - else: - return super(project_task, self).unlink(cr, uid, ids) + 'attendee_ids': fields.many2many('calendar.attendee', 'task_attendee_rel', 'task_id', 'attendee_id', 'Attendees'), + } project_task() diff --git a/addons/project_calendar/project_calendar_view.xml b/addons/project_calendar/project_calendar_view.xml index a27d2f1f464..d331f8614c7 100644 --- a/addons/project_calendar/project_calendar_view.xml +++ b/addons/project_calendar/project_calendar_view.xml @@ -2,18 +2,6 @@ <openerp> <data> - <record id="caldav_project_task_view" model="ir.ui.view"> - <field name="name">project.task.caldav.tree</field> - <field name="model">project.task</field> - <field name="type">tree</field> - <field name="inherit_id" ref="project.view_task_tree2"/> - <field name="arch" type="xml"> - <field name="sequence" position="before"> - <field name="id" widget="char"/> - </field> - </field> - </record> - <record id="view_project_caldav_task_form" model="ir.ui.view"> <field name="name">project.task.caldav.form</field> <field name="model">project.task</field> diff --git a/addons/project_calendar/project_calendar_wizard.xml b/addons/project_calendar/project_calendar_wizard.xml index b30abb809e0..b0f17cae08a 100644 --- a/addons/project_calendar/project_calendar_wizard.xml +++ b/addons/project_calendar/project_calendar_wizard.xml @@ -1,21 +1,18 @@ <openerp> <data> - <wizard string="Import ICS File" model="project.task" - name="caldav.project.import" id="wizard_project_cal_import" - multi="True" - /> - <wizard string="Export ICS File" model="project.task" - name="caldav.project.export" id="wizard_project_cal_export" - multi="True" - /> - - <wizard string="Subscribe to a Remote calendar" model="project.task" - name="caldav.project.subscribe" id="wizard_project_cal_subscribe" multi="True" - /> - - <wizard string="Set RRULE" model="crm.case" - name="caldav.set.rrule" id="wizard_crm_set_rrule" menu="False" - /> + <wizard string="Import .ics File" model="project.task" + name="caldav.event.import" id="caldav.wizard_cal_event_import" multi="True" /> + + <wizard string="Subscribe to a Remote calendar" + model="project.task" name="caldav.event.subscribe" + id="caldav.wizard_cal_event_subscribe" multi="True" /> + + <wizard string="Export .ics File" model="project.task" + name="caldav.event.export" id="caldav.wizard_cal_event_export" multi="True" /> + + <wizard string="Edit this event" model="project.task" + name="calendar.event.edit.this" id="caldav.wizard_edit_this_event" + menu="False" /> </data> </openerp> diff --git a/addons/project_calendar/wizard/wizard_cal_export.py b/addons/project_calendar/wizard/wizard_cal_export.py deleted file mode 100644 index 6bd407169a0..00000000000 --- a/addons/project_calendar/wizard/wizard_cal_export.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). -# -# 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 <http://www.gnu.org/licenses/>. -# -############################################################################## - -import wizard -import base64 -import pooler - - -class project_cal_export_wizard(wizard.interface): - form1 = '''<?xml version="1.0"?> - <form string="Export ICS"> - <field name="name"/> - <field name="file_path" colspan="4" width="300"/> - </form>''' - - form1_fields = { - 'file_path': { - 'string': 'Save ICS file', - 'type': 'binary', - 'required' : True, - 'filters' : '*.ics' - }, - 'name': { - 'string': 'File name', - 'type': 'char', - 'size': 34, - 'required': True, - 'help': 'Save in .ics format'}, - } - - def _process_export_ics(self, cr, uid, data, context): - task_obj = pooler.get_pool(cr.dbname).get('project.task') - calendar = task_obj.export_cal(cr, uid, data['ids'], context) - return {'file_path': base64.encodestring(calendar), \ - 'name': 'OpenERP Tasks.ics'} - - states = { - 'init': { - 'actions': [_process_export_ics], - 'result': {'type': 'form', 'arch':form1, 'fields':form1_fields, \ - 'state': [('end', '_Cancel', 'gtk-cancel'), ('end', 'Ok', 'gtk-ok')]} - }, - } - -project_cal_export_wizard('caldav.project.export') - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file diff --git a/addons/project_calendar/wizard/wizard_cal_import.py b/addons/project_calendar/wizard/wizard_cal_import.py deleted file mode 100644 index 9aa2b9de027..00000000000 --- a/addons/project_calendar/wizard/wizard_cal_import.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). -# -# 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 <http://www.gnu.org/licenses/>. -# -############################################################################## - -import wizard -import pooler - -class project_cal_imp_wizard(wizard.interface): - form1 = '''<?xml version="1.0"?> - <form string="Import ICS"> - <separator string="Select ICS file"/> - <field name="file_path" colspan="4" width="300" nolabel="1"/> - </form>''' - - form1_fields = { - 'file_path': { - 'string': 'Select ICS file', - 'type': 'binary', - 'required': True, - 'filters': '*.ics' - } - } - display = '''<?xml version="1.0"?> - <form string="Import Message"> - <field name="msg" colspan="4" width="300" nolabel="1"/> - </form>''' - - display_fields = { - 'msg': { - 'string': '', - 'type': 'text', - 'readonly': True, - 'default': 'Imported %s Tasks' - } - } - - def _process_imp_ics(self, cr, uid, data, context=None): - task_obj = pooler.get_pool(cr.dbname).get('project.task') - vals = task_obj.import_cal(cr, uid, data['form']['file_path'], context) - global cnt - cnt = 0 - if vals: - cnt = vals['count'] - return {} - - def _result_set(self, cr, uid, data, context=None): - return {'msg': 'Imported %s Task(s)' % cnt} - - states = { - 'init': { - 'actions': [], - 'result': {'type': 'form', 'arch': form1, 'fields': form1_fields, \ - 'state': [('end', '_Cancel', 'gtk-cancel'), ('open', '_Import', 'gtk-ok')]} - }, - 'open': { - 'actions': [], - 'result': {'type': 'action', 'action': _process_imp_ics, 'state': 'display'} - }, - 'display': { - 'actions': [_result_set], - 'result': {'type': 'form', 'arch': display, 'fields': display_fields, \ - 'state': [('end', 'Ok', 'gtk-ok')]} - }, - } - -project_cal_imp_wizard('caldav.project.import') - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file diff --git a/addons/project_calendar/wizard/wizard_cal_subscribe.py b/addons/project_calendar/wizard/wizard_cal_subscribe.py deleted file mode 100644 index 0a41770af37..00000000000 --- a/addons/project_calendar/wizard/wizard_cal_subscribe.py +++ /dev/null @@ -1,95 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). -# -# 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 <http://www.gnu.org/licenses/>. -# -############################################################################## - -from tools.translate import _ -import base64 -import pooler -import urllib -import wizard - -class project_cal_subscribe_wizard(wizard.interface): - form1 = '''<?xml version="1.0"?> - <form string="Subscribe to Remote ICS"> - <separator string="Provide path for Remote Calendar"/> - <field name="url_path" colspan="4" width="300" nolabel="1" widget="url"/> - </form>''' - - form1_fields = { - 'url_path': { - 'string': 'Provide path for remote calendar', - 'type': 'char', - 'required': True, - 'size': 124 - } - } - display = '''<?xml version="1.0"?> - <form string="Message..."> - <field name="msg" colspan="4" width="300" nolabel="1"/> - </form>''' - - display_fields = { - 'msg': { - 'string': '', - 'type': 'text', - 'readonly': True, - } - } - - def _process_imp_ics(self, cr, uid, data, context=None): - global cnt - cnt = 0 - try: - f = urllib.urlopen(data['form']['url_path']) - caldata= f.fp.read() - f.close() - except Exception,e: - raise wizard.except_wizard(_('Error!'), _('Please provide Proper URL !')) - - task_obj = pooler.get_pool(cr.dbname).get('project.task') - context.update({'url': data['form']['url_path']}) - vals = task_obj.import_cal(cr, uid, base64.encodestring(caldata), context) - if vals: - cnt = vals['count'] - return {} - - def _result_set(self, cr, uid, data, context=None): - return {'msg': 'Subscribed %s Task(s)' % cnt} - - states = { - 'init': { - 'actions': [], - 'result': {'type': 'form', 'arch': form1, 'fields': form1_fields, \ - 'state': [('end', '_Cancel', 'gtk-cancel'), ('open', '_Subscribe', 'gtk-ok')]} - }, - 'open': { - 'actions': [], - 'result': {'type': 'action', 'action': _process_imp_ics, 'state': 'display'} - }, - 'display': { - 'actions': [_result_set], - 'result': {'type': 'form', 'arch': display, 'fields': display_fields, \ - 'state': [('end', 'Ok', 'gtk-ok')]} - }, - } - -project_cal_subscribe_wizard('caldav.project.subscribe') - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py index ca7409771dc..a6df9823cf1 100644 --- a/addons/project_gtd/project_gtd.py +++ b/addons/project_gtd/project_gtd.py @@ -130,17 +130,17 @@ class project_task(osv.osv): _defaults = { 'context_id': _get_context } - def next_timebox(self, cr, uid, ids, *args): timebox_obj = self.pool.get('project.gtd.timebox') timebox_ids = timebox_obj.search(cr,uid,[]) + if not timebox_ids: return True for task in self.browse(cr,uid,ids): timebox = task.timebox_id.id - if timebox and timebox_ids.index(timebox) != len(timebox_ids)-1 : + if not timebox: + self.write(cr, uid, task.id, {'timebox_id': timebox_ids[0]}) + elif timebox_ids.index(timebox) != len(timebox_ids)-1: index = timebox_ids.index(timebox) - else: - index = -1 - self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index+1]}) + self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index+1]}) return True def prev_timebox(self, cr, uid, ids, *args): @@ -150,11 +150,9 @@ class project_task(osv.osv): timebox = task.timebox_id.id if timebox and timebox_ids.index(timebox) != 0 : index = timebox_ids.index(timebox) - else: - index = len(timebox_ids) - self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index - 1]}) + self.write(cr, uid, task.id, {'timebox_id': timebox_ids[index - 1]}) return True - + def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): res = super(project_task,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) search_extended = False @@ -162,14 +160,14 @@ class project_task(osv.osv): if res['type'] == 'search': tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[])) search_extended ='''<newline/><group col="%d">''' % (len(tt)+6,) - search_extended += '''<filter domain="[('timebox_id','=', 0)]" icon="gtk-new" string="Inbox"/>''' + search_extended += '''<filter domain="[('timebox_id','=', False)]" icon="gtk-new" string="Inbox"/>''' search_extended += '''<separator orientation="vertical"/>''' for time in tt: if time.icon: icon = time.icon else : icon="" - search_extended += ''' <filter domain="[('timebox_id','=', ''' + str(time.id) + ''')]" icon="''' + icon + '''" string="''' + time.name + '''"/>''' + search_extended += '''<filter domain="[('timebox_id','=', ''' + str(time.id) + ''')]" icon="''' + icon + '''" string="''' + time.name + '''"/>''' search_extended += ''' <separator orientation="vertical"/> <field name="context_id" select="1" widget="selection"/> diff --git a/addons/project_gtd/project_gtd_demo.xml b/addons/project_gtd/project_gtd_demo.xml index ac73d5c7e1e..73584a57c0f 100644 --- a/addons/project_gtd/project_gtd_demo.xml +++ b/addons/project_gtd/project_gtd_demo.xml @@ -45,7 +45,7 @@ <field name="remaining_hours">38.0</field> <field name="timebox_id" ref="timebox_daily"/> <field name="context_id" ref="context_office"/> - <field name="type" ref="project.project_tt_feature"/> + <field name="type" ref="project.project_tt_development"/> <field name="user_id" ref="base.user_root"/> <field name="project_id" ref="project.project_project_22"/> <field name="name">Specific adaptation to MRP</field> @@ -78,7 +78,7 @@ <field name="remaining_hours">38.0</field> <field name="timebox_id" ref="timebox_daily"/> <field name="context_id" ref="context_office"/> - <field name="type" ref="project.project_tt_feature"/> + <field name="type" ref="project.project_tt_development"/> <field name="user_id" ref="base.user_root"/> <field name="project_id" ref="project.project_project_22"/> <field name="name">Specific adaptation to MRP</field> diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml index 3b9e211cd2c..dfaca11e286 100644 --- a/addons/project_gtd/project_gtd_view.xml +++ b/addons/project_gtd/project_gtd_view.xml @@ -76,8 +76,8 @@ <field name="arch" type="xml"> <field name="project_id" position="after"> <field name="timebox_id"/> - <button name="next_timebox" string="Next Timebox" type="object" icon="gtk-indent" attrs="{'invisible':[('timebox_id.type','=','other')]}"/> - <button name="prev_timebox" string="Previous Timebox" type="object" icon="gtk-indent" attrs="{'invisible':[('timebox_id.type','=','daily')]}"/> + <button name="prev_timebox" type="object" icon="gtk-go-back" string="Previous" states="draft,pending,open"/> + <button name="next_timebox" type="object" icon="gtk-go-forward" string="Next" states="draft,pending,open"/> </field> </field> </record> @@ -103,12 +103,16 @@ <field eval="2" name="priority"/> <field name="arch" type="xml"> <tree editable="top" colors="grey:state in ('done',);red:state in ('cancelled');black:state not in ('done','cancelled')" string="Tasks"> + <field name="sequence" invisible="1"/> <field name="name"/> <field name="user_id"/> <field name="timebox_id" widget="selection"/> + <button name="prev_timebox" type="object" icon="gtk-go-back" string="Previous" states="draft,pending,open"/> + <button name="next_timebox" type="object" icon="gtk-go-forward" string="Next" states="draft,pending,open"/> <field name="planned_hours" widget="float_time"/> <field name="state" invisible="1"/> <button name="%(project.wizard_close_task)d" states="draft,pending,open" string="Done" type="action" icon="gtk-jump-to" help="For changing to done state"/> + <button groups="base.group_extended" name="%(project.wizard_delegate_task)d" states="pending,open" string="Delegate" type="action" icon="gtk-sort-descending"/> <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/> <button name="do_reopen" states="done,cancelled" string="Reactivate" type="object" icon="gtk-convert" help="For reopening the tasks"/> </tree> @@ -123,11 +127,11 @@ <field name="search_view_id" ref="project.view_task_search_form"/> </record> - <!-- <menuitem name="Todo List" + <menuitem name="To-Dos" groups="group_project_getting" id="menu_task_inbox" - parent="project.menu_main" - action="action_prject_task_tree"/>--> + parent="project.menu_project_management" + action="action_prject_task_tree"/> <act_window name="My Inbox" domain="[('user_id', '=', uid),('state','in',('draft','open'))]" diff --git a/addons/project_long_term/__init__.py b/addons/project_long_term/__init__.py new file mode 100644 index 00000000000..33adeb520b9 --- /dev/null +++ b/addons/project_long_term/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + +import project + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/project_long_term/__terp__.py b/addons/project_long_term/__terp__.py new file mode 100644 index 00000000000..1b5dfa348ad --- /dev/null +++ b/addons/project_long_term/__terp__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + + +{ + "name" : "Long Term Project Management", + "version": "1.1", + "author" : "Tiny", + "website" : "http://www.openerp.com", + "category" : "Generic Modules/Projects & Services", + "depends" : ["project"], + "description": """Long Term Project management module that track planning, scheduling, resources allocation. + """, + "init_xml" : [], + "demo_xml" : [#"project_demo.xml" +], + "update_xml": [ + "project_view.xml", + ], + 'installable': True, + 'active': False, + 'certificate': None, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project_long_term/project.py b/addons/project_long_term/project.py new file mode 100644 index 00000000000..c5734263ea5 --- /dev/null +++ b/addons/project_long_term/project.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + +from lxml import etree +from mx import DateTime +from mx.DateTime import now +import time +from tools.translate import _ + +from osv import fields, osv +from tools.translate import _ + +class project_phase(osv.osv): + _name = "project.phase" + _description = "Project Phase" + + def _check_recursion(self,cr,uid,ids): + obj_self = self.browse(cr, uid, ids[0]) + prev_ids = obj_self.previous_phase_ids + next_ids = obj_self.next_phase_ids + #it should nither be in prev_ids nor in next_ids + if (obj_self in prev_ids) or (obj_self in next_ids): + return False + ids = [id for id in prev_ids if id in next_ids] + + #both prev_ids and next_ids must be unique + if ids: + return False + #unrelated project + + prev_ids = [rec.id for rec in prev_ids] + next_ids = [rec.id for rec in next_ids] + + #iter prev_ids + while prev_ids: + cr.execute('select distinct prv_phase_id from project_phase_previous_rel where phase_id in ('+','.join(map(str, prev_ids))+')') + prv_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall())) + if obj_self.id in prv_phase_ids: + return False + ids = [id for id in prv_phase_ids if id in next_ids] + if ids: + return False + prev_ids = prv_phase_ids + + #iter next_ids + while next_ids: + cr.execute('select distinct next_phase_id from project_phase_next_rel where phase_id in ('+','.join(map(str, next_ids))+')') + next_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall())) + if obj_self.id in next_phase_ids: + return False + ids = [id for id in next_phase_ids if id in prev_ids] + if ids: + return False + next_ids = next_phase_ids + return True + + _columns = { + 'name': fields.char("Phase Name", size=64, required=True), + 'date_start': fields.datetime('Starting Date'), + 'date_end': fields.datetime('End Date'), + 'constraint_date_start': fields.datetime('Constraint Starting Date'), + 'constraint_date_end': fields.datetime('Constraint End Date'), + 'project_id': fields.many2one('project.project', 'Project', required=True), + 'next_phase_ids': fields.many2many('project.phase', 'project_phase_next_rel', 'phase_id', 'next_phase_id', 'Next Phases'), + 'previous_phase_ids': fields.many2many('project.phase', 'project_phase_previous_rel', 'phase_id', 'prv_phase_id', 'Previous Phases'), + 'duration': fields.float('Duration'), + 'product_uom': fields.many2one('product.uom', 'Duration UoM', help="UoM (Unit of Measure) is the unit of measurement for Duration"), + 'task_ids': fields.one2many('project.task', 'phase_id', "Project Tasks"), + 'resource_ids': fields.one2many('project.resource.allocation', 'phase_id', "Project Resources"), + } + + _defaults = { + 'date_start': lambda *a: time.strftime('%Y-%m-%d'), + } + + _order = "name" + _constraints = [ + (_check_recursion,'Error ! Loops In Phases Not Allowed',['next_phase_ids','previous_phase_ids']) + ] +project_phase() + +class project_resource_allocation(osv.osv): + _name = 'project.resource.allocation' + _description = 'Project Resource Allocation' + _columns = { + 'resource_id': fields.many2one('resource.resource', 'Resource', required=True), + 'phase_id': fields.many2one('project.phase', 'Project Phase', required=True), + 'useability': fields.float('Useability', help="Useability of this ressource for this project phase in percentage (=50%)"), + } + _defaults = { + 'useability': lambda *a: 100, + } +project_resource_allocation() + +class project(osv.osv): + _inherit = "project.project" + + _columns = { + 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases") + } + +project() + +class task(osv.osv): + _inherit = "project.task" + + _columns = { + 'phase_id': fields.many2one('project.phase', 'Project Phase') + } + def _check_dates(self, cr, uid, ids): + leave = self.read(cr, uid, ids[0],['date_start','date_end']) + if leave['date_start'] and leave['date_end']: + if leave['date_start'] > leave['date_end']: + return False + return True + + _constraints = [ + (_check_dates, 'Error! task start-date must be lower then task end-date.', ['date_start', 'date_end']) + ] + +task() +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/project_long_term/project_data.xml b/addons/project_long_term/project_data.xml new file mode 100644 index 00000000000..2addd68fa19 --- /dev/null +++ b/addons/project_long_term/project_data.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <!-- + Requests Links + --> + <record id="req_link_project" model="res.request.link"> + <field name="name">Project</field> + <field name="object">project.project</field> + </record> + <record id="req_link_task" model="res.request.link"> + <field name="name">Project task</field> + <field name="object">project.task</field> + </record> + </data> +</openerp> diff --git a/addons/project_long_term/project_data_scheduler.xml b/addons/project_long_term/project_data_scheduler.xml new file mode 100644 index 00000000000..32e74725d58 --- /dev/null +++ b/addons/project_long_term/project_data_scheduler.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + + + <record forcecreate="True" id="ir_cron_scheduler_action" model="ir.cron"> + <field name="name">Calculate Project Task Length Scheduler</field> + <field eval="False" name="active"/> + <field name="user_id" ref="base.user_root"/> + <field name="interval_number">1</field> + <field name="interval_type">minutes</field> + <field name="numbercall">-1</field> + <field eval="False" name="doall"/> + <field eval="True" name="active"/> + <field eval="'project.project'" name="model"/> + <field eval="'compute_date'" name="function"/> + <!--<field model="project.project" search="[]" name="args"/> + <field eval="select id from project.project" name="args"/>--> + </record> + + </data> +</openerp> + diff --git a/addons/project_long_term/project_demo.xml b/addons/project_long_term/project_demo.xml new file mode 100644 index 00000000000..e762d3874ba --- /dev/null +++ b/addons/project_long_term/project_demo.xml @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + + <!-- + Resource: project.project + --> + <record id="base.main_company" model="res.company"> + <field name="project_time_mode_id" ref="product.uom_hour"></field> + </record> + + <record id="project_tt_analysis" model="project.task.type"> + <field name="name">Analysis</field> + </record> + <record id="project_tt_feature" model="project.task.type"> + <field name="name">New Feature</field> + </record> + <record id="project_tt_quote" model="project.task.type"> + <field name="name">Quotation</field> + </record> + <record id="project_tt_bug" model="project.task.type"> + <field name="name">Bug</field> + </record> + + <record id="project_project_9" model="project.project"> + <field name="warn_manager">1</field> + <field name="name">Open ERP Integration</field> + <field name="manager" ref="base.user_root"/> + </record> + <record id="project_project_21" model="project.project"> + <field name="warn_manager">1</field> + <field name="priority">10</field> + <field name="parent_id" ref="project_project_9"/> + <field name="name">Study + Prototype</field> + <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> + <field name="manager" ref="base.user_root"/> + </record> + <record id="project_project_22" model="project.project"> + <field name="priority">20</field> + <field name="parent_id" ref="project_project_9"/> + <field name="name">Specific Developements</field> + <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> + <field name="manager" ref="base.user_root"/> + </record> + <record id="project_project_23" model="project.project"> + <field name="priority">30</field> + <field name="parent_id" ref="project_project_9"/> + <field name="name">Install, data import, configuration</field> + <field model="account.analytic.account" name="category_id" search="[('name','=', 'Seagate P1')]"/> + <field name="manager" ref="base.user_root"/> + </record> + + <record id="project_task_116" model="project.task"> + <field name="planned_hours">38.0</field> + <field name="remaining_hours">38.0</field> + <field name="type" ref="project_tt_feature"/> + <field name="user_id" ref="base.user_root"/> + <field name="project_id" ref="project_project_22"/> + <field name="description">BoM, After sales returns, interventions. Tracability.</field> + <field name="name">Specific adaptation to MRP</field> + </record> + <record id="project_task_130" model="project.task"> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field name="type" ref="project_tt_feature"/> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_23"/> + <field name="name">Data importation + Doc</field> + </record> + <record id="project_task_131" model="project.task"> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field name="type" ref="project_tt_feature"/> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_23"/> + <field name="name">Modifications asked by the customer.</field> + </record> + <record id="project_task_184" model="project.task"> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field name="type" ref="project_tt_feature"/> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="priority">0</field> + <field name="project_id" ref="project_project_21"/> + <field name="name">Customer analysis + Architecture</field> + </record> + <record id="project_task_186" model="project.task"> + <field name="sequence">15</field> + <field name="planned_hours">8.0</field> + <field name="remaining_hours">8.0</field> + <field name="type" ref="project_tt_feature"/> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_21"/> + <field name="name">Internal testing + Software Install</field> + <field name="date_deadline">2008-06-06</field> + </record> + <record id="project_task_188" model="project.task"> + <field name="sequence">17</field> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field name="type" ref="project_tt_feature"/> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="priority">2</field> + <field name="state">open</field> + <field name="project_id" ref="project_project_21"/> + <field name="name">Analysis, Data Importation</field> + </record> + <record id="project_task_189" model="project.task"> + <field name="sequence">20</field> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field name="state">open</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_23"/> + <field name="name">Parameters</field> + </record> + <record id="project_task_190" model="project.task"> + <field name="sequence">20</field> + <field name="planned_hours">32.0</field> + <field name="remaining_hours">32.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="state">open</field> + <field name="project_id" ref="project_project_21"/> + <field name="name">Start of the doc redaction + MRP</field> + </record> + <record id="project_task_192" model="project.task"> + <field name="sequence">25</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_21"/> + <field name="state">done</field> + <field name="name">MRP Tests</field> + </record> + <record id="project_task_193" model="project.task"> + <field name="sequence">29</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field name="user_id" ref="base.user_root"/> + <field name="project_id" ref="project_project_21"/> + <field name="name">MRP; functionnal layer</field> + <field name="state">done</field> + <field eval="time.strftime('%Y-%m-%d 12:12')" name="date_close"/> + </record> + <record id="project_task_194" model="project.task"> + <field name="sequence">30</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Products Adaptation</field> + </record> + <record id="project_task_195" model="project.task"> + <field name="sequence">30</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_23"/> + <field name="name">Install + Super User Training</field> + </record> + <record id="project_task_196" model="project.task"> + <field name="sequence">30</field> + <field name="planned_hours">32.0</field> + <field name="remaining_hours">32.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Customer docs</field> + </record> + <record id="project_task_197" model="project.task"> + <field name="sequence">30</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_21"/> + <field name="name">Development of the presentation layer</field> + </record> + <record id="project_task_198" model="project.task"> + <field name="sequence">40</field> + <field name="planned_hours">32.0</field> + <field name="remaining_hours">32.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_21"/> + <field name="name">Free Time</field> + </record> + <record id="project_task_199" model="project.task"> + <field name="sequence">40</field> + <field name="planned_hours">50.0</field> + <field name="remaining_hours">50.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Specific tests</field> + </record> + <record id="project_task_200" model="project.task"> + <field name="sequence">40</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Sale module</field> + </record> + <record id="project_task_201" model="project.task"> + <field name="sequence">40</field> + <field name="planned_hours">32.0</field> + <field name="remaining_hours">32.0</field> + <field name="user_id" ref="base.user_root"/> + <field name="project_id" ref="project_project_23"/> + <field name="state">open</field> + <field name="name">In house training</field> + <field name="date_deadline">2007-06-06</field> + </record> + <record id="project_task_202" model="project.task"> + <field name="sequence">50</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field name="user_id" ref="base.user_root"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Validation + latest modifications.</field> + </record> + <record id="project_task_203" model="project.task"> + <field name="sequence">50</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Adaptations buy module</field> + </record> + <record id="project_task_204" model="project.task"> + <field name="sequence">60</field> + <field name="planned_hours">16.0</field> + <field name="remaining_hours">16.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_21"/> + <field name="name">Presentation of the software.</field> + </record> + <record id="project_task_205" model="project.task"> + <field name="sequence">60</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Adaptations Stock module</field> + </record> + <record id="project_task_206" model="project.task"> + <field name="sequence">70</field> + <field name="planned_hours">24.0</field> + <field name="remaining_hours">24.0</field> + <field model="res.users" name="user_id" search="[('login','=','demo')]"/> + <field name="project_id" ref="project_project_22"/> + <field name="name">Latest in house tests</field> + </record> + </data> +</openerp> diff --git a/addons/project_long_term/project_report.xml b/addons/project_long_term/project_report.xml new file mode 100644 index 00000000000..c3b681cdd8b --- /dev/null +++ b/addons/project_long_term/project_report.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <report auto="False" id="report_project_task_gantt" model="project.task" name="project.tasks.gantt" string="Gantt Representation"/> + <report auto="False" id="report_project_project_gantt" model="project.project" name="project.project.gantt" string="Gantt Representation"/> + </data> +</openerp> diff --git a/addons/project_long_term/project_view.xml b/addons/project_long_term/project_view.xml new file mode 100644 index 00000000000..eb968e38312 --- /dev/null +++ b/addons/project_long_term/project_view.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <record id="view_project_resource_allocation_form" model="ir.ui.view"> + <field name="name">project.resource.allocation.form</field> + <field name="model">project.resource.allocation</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Project Resource Allocation"> + <field name="resource_id" select="1"/> + <field name="phase_id"/> + <field name="useability"/> + </form> + </field> + </record> + <record id="view_project_resource_allocation_list" model="ir.ui.view"> + <field name="name">project.resource.allocation.list</field> + <field name="model">project.resource.allocation</field> + <field name="type">tree</field> + <field name="priority" eval="5"/> + <field name="arch" type="xml"> + <tree string="Project Resource Allocation"> + <field name="resource_id"/> + <field name="phase_id"/> + <field name="useability"/> + </tree> + </field> + </record> + <record id="view_project_phase_form" model="ir.ui.view"> + <field name="name">project.phase.form</field> + <field name="model">project.phase</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Project Phase"> + <group colspan="6" col="6"> + <field name="name" select="1"/> + <field name="project_id"/> + <field name="date_start"/> + <field name="date_end"/> + <field name="constraint_date_start"/> + <field name="constraint_date_end"/> + <field name="duration"/> + <field name="product_uom"/> + </group> + <notebook colspan="4"> + <page string="Task Detail"> + <separator colspan="4" string="Project's Tasks"/> + <field colspan="4" name="task_ids" nolabel="1"/> + </page> + <page string="Resource Allocation Detail"> + <separator colspan="4" string="Resource Allocation"/> + <field colspan="4" name="resource_ids" nolabel="1"/> + </page> + <page string="Other Info"> + <separator colspan="4" string="Next Phases"/> + <field colspan="4" name="next_phase_ids" nolabel="1"/> + <separator colspan="4" string="Previous Phases"/> + <field colspan="4" name="previous_phase_ids" nolabel="1"/> + </page> + </notebook> + <newline/> + </form> + </field> + </record> + <record id="view_project_phase_list" model="ir.ui.view"> + <field name="name">project.phase.list</field> + <field name="model">project.phase</field> + <field name="type">tree</field> + <field name="priority" eval="5"/> + <field name="arch" type="xml"> + <tree string="Project Phases"> + <field name="name"/> + <field name="project_id"/> + <field name="date_start"/> + <field name="date_end"/> + <field name="duration"/> + <field name="product_uom"/> + </tree> + </field> + </record> + + + <record id="act_project_phase" model="ir.actions.act_window"> + <field name="name">Project phases</field> + <field name="res_model">project.phase</field> + <field name="view_type">form</field> + </record> + + <act_window + id="project_phase_task_list" + name="Related Tasks" + res_model="project.task" + src_model="project.phase" + view_mode="tree,form" + domain="[('phase_id','=',active_id)]"/> + + <menuitem id="project.menu_all_project" parent="project.menu_main" name="Projects"/> + <menuitem action="act_project_phase" id="menu_project_phase" parent="project.menu_all_project"/> + + + </data> +</openerp> diff --git a/addons/project_long_term/project_wizard.xml b/addons/project_long_term/project_wizard.xml new file mode 100644 index 00000000000..109a003da4a --- /dev/null +++ b/addons/project_long_term/project_wizard.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <wizard id="wizard_close_task" menu="False" model="project.task" name="project.task.close" string="Close Task"/> + <wizard id="wizard_delegate_task" menu="False" model="project.task" name="project.task.delegate" string="Delegate Task"/> + <wizard id="wizard_attachment_task" model="project.task" name="project.task.attachment" string="All Attachments"/> + </data> +</openerp> diff --git a/addons/report_analytic_planning/report_analytic_planning.py b/addons/report_analytic_planning/report_analytic_planning.py index 424a4ce2a8f..3f9c77f253b 100644 --- a/addons/report_analytic_planning/report_analytic_planning.py +++ b/addons/report_analytic_planning/report_analytic_planning.py @@ -314,7 +314,7 @@ Business Days - (Time Allocation of Tasks + Time Allocation without Tasks + Holi WHERE holidays.employee_id IN ( SELECT emp.id - FROM hr_employee emp WHERE emp.user_id = users.id + FROM hr_employee emp, resource_resource res WHERE emp.resource_id = res.id and res.user_id = users.id ) AND holidays.state IN ('validate') AND holidays.type = 'remove' diff --git a/addons/report_crm/__terp__.py b/addons/report_crm/__terp__.py index be8ed55bf4d..dabe76d37db 100644 --- a/addons/report_crm/__terp__.py +++ b/addons/report_crm/__terp__.py @@ -32,7 +32,7 @@ 'init_xml': [], 'update_xml': ['security/ir.model.access.csv', 'report_crm_view.xml'], 'demo_xml': [], - 'installable': False, #TODO : After fixed problems , set True + 'installable': True, #TODO : After fixed problems , set True 'active': False, 'certificate': '0030422968285', } diff --git a/addons/report_crm/report_crm.py b/addons/report_crm/report_crm.py index 6ae41dc7417..f2f7c49faa5 100644 --- a/addons/report_crm/report_crm.py +++ b/addons/report_crm/report_crm.py @@ -37,18 +37,13 @@ class report_crm_case_user(osv.osv): _columns = { 'name': fields.char('Year',size=64,required=False, readonly=True), 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Section', readonly=True), - 'amount_revenue': fields.float('Est.Revenue', readonly=True), - 'amount_costs': fields.float('Est.Cost', readonly=True), - 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'nbr': fields.integer('# of Cases', readonly=True), 'probability': fields.float('Avg. Probability', readonly=True), 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True), - 'delay_close': fields.char('Delay to close', size=20, readonly=True), 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True), } - _order = 'name desc, user_id, section_id' + _order = 'name desc, user_id' def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_case_user') cr.execute(""" @@ -59,16 +54,10 @@ class report_crm_case_user(osv.osv): to_char(c.create_date, 'MM') as month, c.state, c.user_id, - c.section_id, - count(*) as nbr, - sum(planned_revenue) as amount_revenue, - sum(planned_cost) as amount_costs, - sum(planned_revenue*probability)::decimal(16,2) as amount_revenue_prob, - avg(probability)::decimal(16,2) as probability, - to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close + count(*) as nbr from crm_case c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id, c.section_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.user_id )""") report_crm_case_user() @@ -78,19 +67,12 @@ class report_crm_case_categ(osv.osv): _auto = False _columns = { 'name': fields.char('Year',size=64,required=False, readonly=True), - 'categ_id':fields.many2one('crm.case.categ', 'Category', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Section', readonly=True), - 'amount_revenue': fields.float('Est.Revenue', readonly=True), - 'amount_costs': fields.float('Est.Cost', readonly=True), - 'amount_revenue_prob': fields.float('Est. Rev*Prob.', readonly=True), 'nbr': fields.integer('# of Cases', readonly=True), - 'probability': fields.float('Avg. Probability', readonly=True), 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True), - 'delay_close': fields.char('Delay Close', size=20, readonly=True), 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True), } - _order = 'name desc, categ_id, section_id' + _order = 'name desc' def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_case_categ') cr.execute(""" @@ -100,17 +82,10 @@ class report_crm_case_categ(osv.osv): to_char(c.create_date, 'YYYY') as name, to_char(c.create_date, 'MM') as month, c.state, - c.categ_id, - c.section_id, - count(*) as nbr, - sum(planned_revenue) as amount_revenue, - sum(planned_cost) as amount_costs, - sum(planned_revenue*probability)::decimal(16,2) as amount_revenue_prob, - avg(probability)::decimal(16,2) as probability, - to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close + count(*) as nbr from crm_case c - group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state, c.categ_id, c.section_id + group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), c.state )""") report_crm_case_categ() @@ -145,16 +120,14 @@ class report_crm_case_section(osv.osv): _columns = { 'name': fields.char('Year',size=64,required=False, readonly=True), # 'user_id':fields.many2one('res.users', 'User', readonly=True), - 'section_id':fields.many2one('crm.case.section', 'Section', readonly=True), 'nbr_cases': fields.integer('# of Cases', readonly=True), 'avg_answers': fields.function(_get_data,string='Avg. Answers', method=True,type="integer"), - 'perc_done': fields.function(_get_data,string='%Done', method=True,type="float"), - 'perc_cancel': fields.function(_get_data,string='%Cancel', method=True,type="float"), - 'delay_close': fields.char('Delay to close', size=20, readonly=True), + # 'perc_done': fields.function(_get_data,string='%Done', method=True,type="float"), +# 'perc_cancel': fields.function(_get_data,string='%Cancel', method=True,type="float"), 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True), } - _order = 'name desc, section_id' + _order = 'name desc' def init(self, cr): tools.drop_view_if_exists(cr, 'report_crm_case_section') cr.execute(""" @@ -163,15 +136,11 @@ class report_crm_case_section(osv.osv): min(c.id) as id, to_char(c.create_date, 'YYYY') as name, to_char(c.create_date, 'MM') as month, - c.section_id as section_id, count(*) as nbr_cases, - 0 as avg_answers, - 0.0 as perc_done, - 0.0 as perc_cancel, - to_char(avg(date_closed-c.create_date), 'DD"d" HH24:MI:SS') as delay_close + 0 as avg_answers from crm_case c - group by to_char(c.create_date, 'YYYY'),to_char(c.create_date, 'MM'),c.section_id + group by to_char(c.create_date, 'YYYY'),to_char(c.create_date, 'MM') )""") report_crm_case_section() @@ -183,34 +152,23 @@ class report_crm_case_service_dashboard(osv.osv): 'date': fields.datetime('Date', readonly=True), 'date_deadline': fields.datetime('Deadline', readonly=True), 'name': fields.char('Description', size=64, readonly=True), - 'partner_id': fields.many2one('res.partner', 'Partner', readonly=True), 'user_id': fields.many2one('res.users', 'Responsible', readonly=True), - 'priority': fields.char('Priority', size=64, readonly=True), - 'planned_revenue': fields.float('Planned Revenue', readonly=True), - 'planned_cost': fields.float('Planned Costs', readonly=True), 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True), - 'date_closed' : fields.datetime('Date Closed', readonly=True), 'create_date' : fields.datetime('Create Date', readonly=True) } - _order = 'date_closed, create_date' + _order = 'create_date' def init(self, cr): cr.execute("""create or replace view report_crm_case_service_dashboard as ( select cse.id as id, cse.date as date, cse.date_deadline as date_deadline, - cse.name as name, cse.partner_id as partner_id, cse.user_id as user_id, - cse.priority as priority, cse.planned_revenue as planned_revenue, - cse.planned_cost as planned_cost, cse.state as state, - cse.date_closed as date_closed, cse.create_date as create_date + cse.name as name, cse.user_id as user_id, + cse.state as state, + cse.create_date as create_date from crm_case cse where - ((to_date(to_char(cse.date_closed, 'YYYY-MM-dd'),'YYYY-MM-dd') <= CURRENT_DATE) - AND - (to_date(to_char(cse.date_closed, 'YYYY-MM-dd'),'YYYY-MM-dd') > (CURRENT_DATE-15)) - AND - cse.state='done') - + (cse.state='done') OR ((to_date(to_char(cse.create_date, 'YYYY-MM-dd'),'YYYY-MM-dd') <= CURRENT_DATE) diff --git a/addons/report_crm/report_crm_view.xml b/addons/report_crm/report_crm_view.xml index 42850dad86e..afddfee6e07 100644 --- a/addons/report_crm/report_crm_view.xml +++ b/addons/report_crm/report_crm_view.xml @@ -15,13 +15,7 @@ <field name="name" /> <field name="month"/> <field name="user_id"/> - <field name="section_id"/> <field name="nbr"/> - <field name="delay_close"/> - <field name="amount_revenue"/> - <field name="amount_costs"/> - <field name="amount_revenue_prob"/> - <field name="probability"/> <field name="state"/> </tree> </field> @@ -35,7 +29,6 @@ <field name="name" select="1"/> <field name="month" select="1"/> <field name="user_id" select="1"/> - <field name="section_id" select="1" widget="selection"/> <field name="nbr" select="1"/> <field name="state" select="1"/> </form> @@ -70,7 +63,6 @@ <field name="name" select="1"/> <field name="month" select="1"/> <field name="user_id" select="1"/> - <field name="section_id" select="1" widget="selection"/> <field name="nbr" select="1"/> <field name="state" select="1"/> </group> @@ -78,8 +70,8 @@ </field> </record> -<!-- <menuitem id="crm.next_id_64" name="Reporting" parent="crm.menu_crm" sequence="50"/>--> -<!-- <menuitem id="crm.next_id_52" name="All Cases" parent="crm.next_id_64" sequence="0"/>--> + <menuitem id="crm.next_id_64" name="Reporting" parent="base.menu_base_partner" sequence="50"/> + <menuitem id="crm.next_id_52" name="Cases" parent="crm.next_id_64" sequence="0"/> <record id="action_report_crm_case_user_tree" model="ir.actions.act_window"> <field name="name">Cases by User and Section</field> @@ -88,7 +80,7 @@ <field name="view_mode">tree,graph</field> <field name="search_view_id" ref="view_crm_case_user_filter"/> </record> -<!-- <menuitem action="action_report_crm_case_user_tree" id="menu_crm_case_user_tree" parent="crm.next_id_64"/>--> + <menuitem action="action_report_crm_case_user_tree" id="menu_crm_case_user_tree" parent="crm.next_id_52"/> <!-- # Cases by section and categoryof case --> @@ -100,14 +92,7 @@ <tree string="Cases by User and Section"> <field name="name"/> <field name="month"/> - <field name="categ_id"/> - <field name="section_id"/> <field name="nbr"/> - <field name="delay_close"/> - <field name="amount_revenue"/> - <field name="amount_costs"/> - <field name="amount_revenue_prob"/> - <field name="probability"/> <field name="state"/> </tree> </field> @@ -120,8 +105,6 @@ <form string="Cases by User and Section"> <field name="name" select="1"/> <field name="month" select="1"/> - <field name="categ_id" select="1"/> - <field name="section_id" select="1" widget="selection"/> <field name="nbr" select="1"/> <field name="state" select="1"/> </form> @@ -139,9 +122,6 @@ <filter string="This Month" icon="terp-hr" domain="[('month','=',time.localtime()[1])]"/> <separator orientation="vertical"/> <field name="name" select="1"/> - <field name="month" select="1"/> - <field name="categ_id" select="1"/> - <field name="section_id" select="1" widget="selection"/> <field name="nbr" select="1"/> <field name="state" select="1"/> </group> @@ -156,7 +136,7 @@ <field name="view_mode">tree,graph</field> <field name="search_view_id" ref="view_crm_case_categ_filter"/> </record> -<!-- <menuitem action="action_report_crm_case_categ_tree" id="menu_crm_case_categ_tree" parent="crm.next_id_64"/>--> + <menuitem action="action_report_crm_case_categ_tree" id="menu_crm_case_categ_tree" parent="crm.next_id_52"/> <act_window domain="[('user_id', '=', active_id)]" id="act_res_users_2_report_crm_case_user" name="Monthly cases" res_model="report.crm.case.user" src_model="res.users"/> @@ -177,12 +157,8 @@ <tree string="Cases by Section"> <field name="name" select="1"/> <field name="month" select="1"/> - <field name="section_id" select="1"/> <field name="nbr_cases" select="1"/> <field name="avg_answers"/> - <field name="perc_done" select="2"/> - <field name="perc_cancel" select="2"/> - <field name="delay_close"/> </tree> </field> </record> @@ -211,7 +187,6 @@ <separator orientation="vertical"/> <field name="name" select="1"/> <field name="month" select="1"/> - <field name="section_id" select="1"/> <field name="nbr_cases" select="1"/> </group> </search> @@ -239,11 +214,7 @@ <field name="date" select="1"/> <field name="date_deadline"/> <field name="name" select="1"/> - <field name="partner_id" select="2"/> <field name="user_id" select="2"/> - <field name="priority"/> - <field name="planned_revenue" sum="Planned revenue"/> - <field name="planned_cost" sum="Planned costs"/> <field name="state" /> </tree> </field> @@ -255,15 +226,9 @@ <field name="type">tree</field> <field name="arch" type="xml"> <tree string="CRM Cases"> - <field name="date_closed" select="1"/> <field name="date"/> - <field name="date_deadline"/> <field name="name"/> - <field name="partner_id" select="2"/> <field name="user_id" select="2"/> - <field name="priority"/> - <field name="planned_revenue" sum="Planned revenue"/> - <field name="planned_cost" sum="Planned costs"/> <field name="state" /> </tree> </field> diff --git a/addons/resource/__init__.py b/addons/resource/__init__.py new file mode 100755 index 00000000000..2aa86a90c65 --- /dev/null +++ b/addons/resource/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + +import resource + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/resource/__terp__.py b/addons/resource/__terp__.py new file mode 100755 index 00000000000..4970fe2ceac --- /dev/null +++ b/addons/resource/__terp__.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + + +{ + "name" : "Resource", + "version" : "1.1", + "author" : "Tiny", + "category" : "Generic Modules/Projects", + "website" : "http://www.openerp.com", + "description": """ + Module for resource management. You can manage: + * Leave/Holidays or Days off of the company + + """, + 'author': 'Tiny', + 'website': 'http://www.openerp.com', + 'depends': ['base', 'process'], + 'init_xml': [], + 'update_xml': [ + #'security/resource_security.xml', +# 'security/ir.model.access.csv', + 'resource_view.xml', + ], + 'demo_xml': [#'resource_demo.xml' + ], + 'installable': True, + 'active': False, + 'certificate': None, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/resource/hr_demo.xml b/addons/resource/hr_demo.xml new file mode 100755 index 00000000000..fc01109d86c --- /dev/null +++ b/addons/resource/hr_demo.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <!-- Example employee --> + + <record id="timesheet_group1" model="resource.calendar"> + <field name="name">38 Hours/Week</field> + </record> + + <record id="employee1" model="hr.employee"> + <field name="name">Fabien Pinckaers</field> + <!--<field name="regime">45</field>--> + <field name="user_id" ref="base.user_root"/> + <!--<field name="holiday_max">25</field>--> + </record> + + <record model="resource.calendar.week"> + <field name="name">Monday morning</field> + <field name="dayofweek">0</field> + <field name="hour_from">08</field> + <field name="hour_to">12</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Monday evening</field> + <field name="dayofweek">0</field> + <field name="hour_from">13</field> + <field name="hour_to">18</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Tuesday morning</field> + <field name="dayofweek">1</field> + <field name="hour_from">08</field> + <field name="hour_to">12</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Tuesday evening</field> + <field name="dayofweek">1</field> + <field name="hour_from">13</field> + <field name="hour_to">18</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Wednesday morning</field> + <field name="dayofweek">2</field> + <field name="hour_from">08</field> + <field name="hour_to">12</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Wednesday evening</field> + <field name="dayofweek">2</field> + <field name="hour_from">13</field> + <field name="hour_to">18</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Thursday morning</field> + <field name="dayofweek">3</field> + <field name="hour_from">08</field> + <field name="hour_to">12</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Thursday evening</field> + <field name="hour_from">13</field> + <field name="hour_to">18</field> + <field name="dayofweek">3</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Friday morning</field> + <field name="dayofweek">4</field> + <field name="hour_from">08</field> + <field name="hour_to">12</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + <record model="resource.calendar.week"> + <field name="name">Friday evening</field> + <field name="dayofweek">4</field> + <field name="hour_from">13</field> + <field name="hour_to">18</field> + <field name="calendar_id" ref="timesheet_group1"/> + </record> + + </data> +</openerp> diff --git a/addons/resource/hr_department.py b/addons/resource/hr_department.py new file mode 100755 index 00000000000..907bc55a435 --- /dev/null +++ b/addons/resource/hr_department.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## + +from osv import fields,osv +import tools + +class hr_department(osv.osv): + _name = "hr.department" + _columns = { + 'name': fields.char('Department Name', size=64, required=True), + 'company_id': fields.many2one('res.company', 'Company', select=True, required=True), + 'parent_id': fields.many2one('hr.department', 'Parent Department', select=True), + 'child_ids': fields.one2many('hr.department', 'parent_id', 'Child Departments'), + 'note': fields.text('Note'), + 'manager_id': fields.many2one('res.users', 'Manager', required=True), + 'member_ids': fields.many2many('res.users', 'hr_department_user_rel', 'department_id', 'user_id', 'Members'), + } + def _get_members(self,cr, uid, context={}): + mids = self.search(cr, uid, [('manager_id','=',uid)]) + result = {uid:1} + for m in self.browse(cr, uid, mids, context): + for user in m.member_ids: + result[user.id] = 1 + return result.keys() + def _check_recursion(self, cr, uid, ids): + level = 100 + while len(ids): + cr.execute('select distinct parent_id from hr_department where id in ('+','.join(map(str, ids))+')') + ids = filter(None, map(lambda x:x[0], cr.fetchall())) + if not level: + return False + level -= 1 + return True + + _constraints = [ + (_check_recursion, 'Error! You can not create recursive departments.', ['parent_id']) + ] + +hr_department() + + +class ir_action_window(osv.osv): + _inherit = 'ir.actions.act_window' + + def read(self, cr, uid, ids, fields=None, context=None, + load='_classic_read'): + select = ids + if isinstance(ids, (int, long)): + select = [ids] + res = super(ir_action_window, self).read(cr, uid, select, fields=fields, + context=context, load=load) + for r in res: + mystring = 'department_users_get()' + if mystring in (r.get('domain', '[]') or ''): + r['domain'] = r['domain'].replace(mystring, str( + self.pool.get('hr.department')._get_members(cr, uid))) + if isinstance(ids, (int, long)): + if res: + return res[0] + else: + return False + return res + +ir_action_window() + +class res_users(osv.osv): + _inherit = 'res.users' + _description = 'res.users' + + def _parent_compute(self, cr, uid, ids, name, args, context={}): + result = {} + obj_dept = self.pool.get('hr.department') + for user_id in ids: + ids_dept = obj_dept.search(cr, uid, [('member_ids', 'in', [user_id])]) + parent_ids = [] + if ids_dept: + data_dept = obj_dept.read(cr, uid, ids_dept, ['manager_id']) + parent_ids = map(lambda x: x['manager_id'][0], data_dept) + result[user_id] = parent_ids + return result + + def _parent_search(self, cr, uid, obj, name, args): + parent = [] + for arg in args: + if arg[0] == 'parent_id': + parent = arg[2] + child_ids = self._child_compute(cr, uid, parent,name, args, {}) + if not child_ids: + return [('id', 'in', [0])] + return [('id', 'in', child_ids.get(uid,[]))] + + def _child_compute(self, cr, uid, ids, name, args, context={}): + obj_dept = self.pool.get('hr.department') + obj_user = self.pool.get('res.users') + result = {} + for manager_id in ids: + child_ids = [] + mgnt_dept_ids = obj_dept.search(cr, uid, [('manager_id', '=', manager_id)]) + ids_dept = obj_dept.search(cr, uid, [('id', 'child_of', mgnt_dept_ids)]) + if ids_dept: + data_dept = obj_dept.read(cr, uid, ids_dept, ['member_ids']) + childs = map(lambda x: x['member_ids'], data_dept) + childs = tools.flatten(childs) + childs = obj_user.search(cr, uid, [('id','in',childs),('active','=',True)]) + if manager_id in childs: + childs.remove(manager_id) + + child_ids.extend(tools.flatten(childs)) + set = {} + map(set.__setitem__, child_ids, []) + child_ids = set.keys() + else: + child_ids = [] + result[manager_id] = child_ids + return result + + def _child_search(self, cr, uid, obj, name, args): + parent = [] + for arg in args: + if arg[0] == 'child_ids': + parent = arg[2] + child_ids = self._child_compute(cr, uid, parent,name, args, {}) + if not child_ids: + return [('id', 'in', [0])] + return [('id', 'in', child_ids.get(uid,[]))] + + _columns = { + 'parent_id': fields.function(_parent_compute, relation='res.users',fnct_search=_parent_search, method=True, string="Managers", type='many2many'), + 'child_ids': fields.function(_child_compute, relation='res.users', fnct_search=_child_search,method=True, string="Subordinates", type='many2many'), + } + + +res_users() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file diff --git a/addons/resource/hr_department_demo.xml b/addons/resource/hr_department_demo.xml new file mode 100755 index 00000000000..c7ea68f1dc3 --- /dev/null +++ b/addons/resource/hr_department_demo.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + + <record id="dep_management" model="hr.department"> + <field name="name">Management</field> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + </record> + <record id="dep_administration" model="hr.department"> + <field name="name">Administration</field> + <field name="parent_id" ref="dep_management"/> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + </record> + + <record id="dep_technical" model="hr.department"> + <field name="name">Technical department</field> + <field name="parent_id" ref="dep_management"/> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + </record> + + <record id="dep_it" model="hr.department"> + <field name="name">IT</field> + <field name="parent_id" ref="dep_technical"/> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + </record> + + <record id="dep_marketing" model="hr.department"> + <field name="name">Marketing</field> + <field name="parent_id" ref="dep_management"/> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + </record> + + <record id="dep_sales" model="hr.department"> + <field name="name">Sales</field> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + <field name="parent_id" ref="dep_management"/> + </record> + + <record id="dep_sales_europe" model="hr.department"> + <field name="name">Sales Europe</field> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + <field name="parent_id" ref="dep_sales"/> + </record> + + <record id="dep_sales_america" model="hr.department"> + <field name="name">Sales America</field> + <field name="company_id" ref="base.main_company"/> + <field name="manager_id" ref="base.user_root"/> + <field name="parent_id" ref="dep_sales"/> + </record> + + + + + </data> +</openerp> diff --git a/addons/resource/hr_department_view.xml b/addons/resource/hr_department_view.xml new file mode 100755 index 00000000000..fe65d988237 --- /dev/null +++ b/addons/resource/hr_department_view.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <!-- + ====================== + department + ====================== + --> + <record id="view_department_form" model="ir.ui.view"> + <field name="name">hr.department.form</field> + <field name="model">hr.department</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="department"> + <field colspan="4" name="name" select="1"/> + <field name="company_id" select="1" widget="selection" groups="base.group_multi_company"/> + <field name="parent_id" select="2"/> + <field colspan="4" name="manager_id" select="1"/> + <notebook colspan="4" > + <page string="Members"> + <field colspan="4" name="member_ids" nolabel="1"/> + </page> + <page string="Notes"> + <field colspan="4" name="note" nolabel="1"/> + </page> + </notebook> + </form> + </field> + </record> + <record id="view_department_tree" model="ir.ui.view"> + <field name="name">hr.department.tree</field> + <field name="model">hr.department</field> + <field name="type">tree</field> + <field name="field_parent">child_ids</field> + <field name="arch" type="xml"> + <tree string="Companies"> + <field name="name"/> + <field name="company_id" groups="base.group_multi_company"/> + <field name="manager_id"/> + </tree> + </field> + </record> + <record id="open_module_tree_department_tree" model="ir.actions.act_window"> + <field name="name">Departments</field> + <field name="res_model">hr.department</field> + <field name="view_type">tree</field> + <field name="domain">[('parent_id','=',False)]</field> + </record> + <menuitem action="open_module_tree_department_tree" id="menu_department_tree" parent="base.menu_users"/> + + <record id="open_module_tree_department" model="ir.actions.act_window"> + <field name="name">Departments</field> + <field name="res_model">hr.department</field> + <field name="view_type">form</field> + </record> + + <menuitem action="open_module_tree_department" id="menu_department_def" parent="hr.menu_department_tree"/> + + <!-- res.users inherit --> + <record model="ir.ui.view" id="view_users_form_inherit"> + <field name="name">res.users.form</field> + <field name="type">form</field> + <field name="model">res.users</field> + <field name="inherit_id" ref="base.view_users_form"/> + <field name="arch" type="xml"> + <notebook position="inside"> + <page string="Departements Informations"> + <separator string="Managers" colspan="4"/> + <field name="parent_id" nolabel="1" colspan="4"/> + <separator string="Subordinates" colspan="4"/> + <field name="child_ids" nolabel="1" colspan="4"/> + </page> + </notebook> + </field> + </record> + + </data> +</openerp> diff --git a/addons/resource/hr_view.xml b/addons/resource/hr_view.xml new file mode 100755 index 00000000000..abf3c5f023f --- /dev/null +++ b/addons/resource/hr_view.xml @@ -0,0 +1,296 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <menuitem icon="terp-hr" id="menu_hr_root" name="Human Resources"/> + <menuitem + id="menu_hr_reporting" + name="Reporting" + parent="hr.menu_hr_root" + sequence="40" /> + <menuitem + id="menu_hr_configuration" + name="Configuration" + parent="hr.menu_hr_root" + sequence="5" groups="group_hr_manager"/> + + <!-- + ========== + Employee + ========== + --> + <record id="view_employee_form" model="ir.ui.view"> + <field name="name">hr.employee.form</field> + <field name="model">hr.employee</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Employee"> + <group colspan="4" col="4"> + <field name="name" select="1"/> + <field name="active" select="1"/> + <field name="company_id" widget="selection" groups="base.group_multi_company"/> + <field name="user_id"/> + </group> + <notebook colspan="4"> + <page string="Personal Information"> + <group col="2" colspan="2"> + <separator colspan="2" string="Social IDs"/> + <field name="ssnid"/> + <field name="sinid"/> + <field name="otherid"/> + </group> + <group col="2" colspan="2"> + <separator string="Status" colspan="2"/> + <field name="gender"/> + <field name="marital"/> + <field name="country_id"/> + <field name="birthday"/> + </group> + + <group col="2" colspan="2"> + <separator string="Contact Information" colspan="2"/> + <field name="address_home_id" colspan="2"/> + <field name="address_id" colspan="2"/> + <field name="work_phone"/> + <field name="work_email" widget="email" /> + <field name="work_location"/> + </group> + + <group col="4" colspan="2"> + <separator string="Job Information" colspan="4"/> + <field name="parent_id" select="1" colspan="4"/> + + <field name="category_id" colspan="4" widget="selection"/> + </group> + </page> + <page string="Notes"> + <field colspan="4" nolabel="1" name="notes"/> + </page> + </notebook> + </form> + </field> + </record> + + <record id="view_employee_tree" model="ir.ui.view"> + <field name="name">hr.employee.tree</field> + <field name="model">hr.employee</field> + <field name="type">tree</field> + <field name="field_parent">child_ids</field> + <field name="arch" type="xml"> + <tree string="Employees"> + <field name="name"/> + <field name="work_phone"/> + <field name="work_email"/> + <field name="address_id"/> + <field name="parent_id"/> + </tree> + </field> + </record> + <record id="open_view_employee_tree" model="ir.actions.act_window"> + <field name="name">Employees Structure</field> + <field name="res_model">hr.employee</field> + <field name="view_type">tree</field> + <field name="view_mode">tree,form</field> + <field name="view_id" ref="view_employee_tree"/> + <field name="domain">[('parent_id','=',False)]</field> + </record> + + <record id="open_view_employee_list" model="ir.actions.act_window"> + <field name="name">Employees</field> + <field name="res_model">hr.employee</field> + <field name="view_type">form</field> + <field name="view_mode">tree,form</field> + <field name="view_id" eval="False"/> + </record> + <menuitem + id="menu_open_view_employee_list" + name="Employees" + groups="group_hr_manager" + parent="hr.menu_hr_root"/> + + <menuitem + action="open_view_employee_tree" + id="menu_open_view_employee_tree" + parent="menu_open_view_employee_list"/> + + <record id="open_view_employee_list_my" model="ir.actions.act_window"> + <field name="name">All Employees</field> + <field name="res_model">hr.employee</field> + <field name="view_type">form</field> + <field name="view_mode">tree,form</field> + <field name="domain">[]</field> + </record> + <menuitem + action="open_view_employee_list_my" + id="menu_open_view_employee_list_my" + parent="menu_open_view_employee_list"/> + + <!-- + ======================= + Employee architecture + ======================= + --> + <record id="view_partner_tree2" model="ir.ui.view"> + <field name="name">hr.employee.tree</field> + <field name="model">hr.employee</field> + <field name="type">tree</field> + <field name="field_parent">child_ids</field> + <field name="arch" type="xml"> + <tree string="Employees"> + <field name="name"/> + <field name="user_id"/> + <field name="address_id"/> + + </tree> + </field> + </record> + <record id="action2" model="ir.actions.act_window"> + <field name="name">Employee Hierarchy</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">hr.employee</field> + <field name="domain">[('id','in',active_ids)]</field> + <field name="view_type">tree</field> + <field name="view_id" ref="view_partner_tree2"/> + </record> + <ir_set> + <field eval="'action'" name="key"/> + <field eval="'client_action_multi'" name="key2"/> + <field eval="['hr.employee']" name="models"/> + <field name="name">Employees Hierarchy</field> + <field eval="'ir.actions.act_window,'+str(action2)" name="value"/> + <field eval="True" name="isobject"/> + <field eval="True" name="replace"/> + </ir_set> + + + <!-- + ============ + Working Time + ============ + --> + <record id="create_group" model="ir.ui.view"> + <field name="name">resource.calendar.form</field> + <field name="model">resource.calendar</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Working Time Category"> + <field name="name" select="1"/> + <field name="manager" select="1"/> + <newline/> + <field colspan="4" name="week_id" nolabel="1" widget="one2many_list"/> + </form> + </field> + </record> + <record id="edit_workgroup" model="ir.actions.act_window"> + <field name="name">Working Time Categories</field> + <field name="res_model">resource.calendar</field> + <field name="view_type">form</field> + <field name="view_id" eval="False"/> + </record> + <menuitem action="edit_workgroup" id="menu_edit_workgroup" parent="hr.menu_hr_configuration"/> + + <record id="view_timesheet_tree" model="ir.ui.view"> + <field name="name">resource.calendar.week.tree</field> + <field name="model">resource.calendar.week</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Working Time"> + <field name="name"/> + <field name="dayofweek"/> + <field name="hour_from" widget="float_time"/> + <field name="hour_to" widget="float_time"/> + </tree> + </field> + </record> + <record id="view_timesheet_form" model="ir.ui.view"> + <field name="name">resource.calendar.week.form</field> + <field name="model">resource.calendar.week</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Working Time"> + <field colspan="4" name="name" select="1"/> + <field name="date_from"/> + <field name="dayofweek" select="1"/> + <field name="hour_from" widget="float_time"/> + <field name="hour_to" widget="float_time"/> + </form> + </field> + </record> + + <!-- + ============ + Employee Category + ============ + --> + + <record id="view_employee_category_form" model="ir.ui.view"> + <field name="name">hr.employee.category.form</field> + <field name="model">hr.employee.category</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Employee Category"> + <field name="name" select="1"/> + <field name="parent_id" select="1"/> + </form> + </field> + </record> + <record id="view_employee_category_list" model="ir.ui.view"> + <field name="name">hr.employee.category.list</field> + <field name="model">hr.employee.category</field> + <field name="type">tree</field> + <field eval="8" name="priority"/> + <field name="arch" type="xml"> + <tree string="Employees Categories"> + <field name="name"/> + <field name="parent_id"/> + </tree> + </field> + </record> + <record id="view_employee_category_tree" model="ir.ui.view"> + <field name="name">hr.employee.category.tree</field> + <field name="model">hr.employee.category</field> + <field name="type">tree</field> + <field name="field_parent">child_ids</field> + <field name="arch" type="xml"> + <tree string="Employees Categories"> + <field name="name"/> + </tree> + </field> + </record> + <record id="open_view_categ_form" model="ir.actions.act_window"> + <field name="name">Categories of Employee</field> + <field name="res_model">hr.employee.category</field> + <field name="view_type">form</field> + <field name="view_mode">tree,form</field> + </record> + <menuitem action="open_view_categ_form" id="menu_view_employee_category_form" parent="hr.menu_hr_configuration"/> + + <record id="open_view_categ_tree" model="ir.actions.act_window"> + <field name="name">Categories structure</field> + <field name="res_model">hr.employee.category</field> + <field name="view_type">tree</field> + <field name="view_id" ref="view_employee_category_tree"/> + <field name="domain">[('parent_id','=',False)]</field> + </record> + + <record id="hr_employee_normal_action_tree" model="ir.actions.act_window"> + <field name="name">Employees</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">hr.employee</field> + <field name="view_type">form</field> + <field name="view_mode">tree,form</field> + <field name="domain">[('category_id','child_of',[active_id])]</field> + <field name="context">{'category_id':active_id}</field> + </record> + + <record id="hr_employee_category_open" model="ir.values"> + <field eval="'tree_but_open'" name="key2"/> + <field eval="'hr.employee.category'" name="model"/> + <field name="name">Employees by Categories</field> + <field eval="'ir.actions.act_window,%d'%hr_employee_normal_action_tree" name="value"/> + <field eval="True" name="object"/> + </record> + + <menuitem action="open_view_categ_tree" id="menu_view_employee_category_tree" parent="hr.menu_view_employee_category_form"/> + + </data> +</openerp> diff --git a/addons/resource/resource.py b/addons/resource/resource.py new file mode 100755 index 00000000000..7ac36e5e7bd --- /dev/null +++ b/addons/resource/resource.py @@ -0,0 +1,191 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). +# +# 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 <http://www.gnu.org/licenses/>. +# +############################################################################## +import mx.DateTime +import time +import math +from osv import fields, osv +from tools.translate import _ + +class resource_calendar(osv.osv): + _name = "resource.calendar" + _description = "Resource Calendar" + _columns = { + 'name' : fields.char("Name", size=64, required=True), + 'company_id' : fields.many2one('res.company', 'Company', required=True), + 'week_id' : fields.one2many('resource.calendar.week', 'calendar_id', 'Working Time'), + 'manager' : fields.many2one('res.users', 'Workgroup manager'), + } + _defaults = { + 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.calendar', c) + } + def interval_min_get(self, cr, uid, id, dt_from, hours , resource=0): + dt_leave = [] + if not id: + return [(dt_from-mx.DateTime.RelativeDateTime(hours=int(hours)*3), dt_from)] + if resource: + resource_leave_ids = self.pool.get('resource.calendar.leaves').search(cr,uid,[('resource_id','=',resource)]) + if resource_leave_ids: + res_leaves = self.pool.get('resource.calendar.leaves').read(cr,uid,resource_leave_ids,['date_from','date_to']) + for i in range(len(res_leaves)): + dtf = mx.DateTime.strptime(res_leaves[i]['date_from'],'%Y-%m-%d %H:%M:%S') + dtt = mx.DateTime.strptime(res_leaves[i]['date_to'],'%Y-%m-%d %H:%M:%S') + leave_days = ((dtt - dtf).days) + 1 + for x in range(int(leave_days)): + dt_leave.append((dtf + mx.DateTime.RelativeDateTime(days=x)).strftime('%Y-%m-%d')) + dt_leave.sort() + todo = hours + cycle = 0 + result = [] + maxrecur = 100 + current_hour = dt_from.hour + while (todo>0) and maxrecur: + cr.execute("select hour_from,hour_to from resource_calendar_week where dayofweek='%s' and calendar_id=%s order by hour_from", (dt_from.day_of_week,id)) + for (hour_from,hour_to) in cr.fetchall(): + if (hour_to>current_hour) and (todo>0): + m = max(hour_from, current_hour) + if (hour_to-m)>todo: + hour_to = m+todo + d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) + d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60)) + dt1 = d1.strftime('%Y-%m-%d') + dt2 = d2.strftime('%Y-%m-%d') + for i in range(len(dt_leave)): + if dt1 == dt_leave[i]: + dt_from += mx.DateTime.RelativeDateTime(days=1) + d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) + d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60)) + dt1 = d1.strftime('%Y-%m-%d') + dt2 = d2.strftime('%Y-%m-%d') + result.append((d1, d2)) + current_hour = hour_to + todo -= (hour_to - m) + dt_from += mx.DateTime.RelativeDateTime(days=1) + current_hour = 0 + maxrecur -= 1 + return result + + def interval_get(self, cr, uid, id, dt_from, hours, resource=0, byday=True): + dt_leave = [] + if not id: + return [(dt_from,dt_from+mx.DateTime.RelativeDateTime(hours=int(hours)*3))] + if resource: + resource_leave_ids = self.pool.get('resource.calendar.leaves').search(cr,uid,[('resource_id','=',resource)]) + if resource_leave_ids: + res_leaves = self.pool.get('resource.calendar.leaves').read(cr,uid,resource_leave_ids,['date_from','date_to']) + for i in range(len(res_leaves)): + dtf = mx.DateTime.strptime(res_leaves[i]['date_from'],'%Y-%m-%d %H:%M:%S') + dtt = mx.DateTime.strptime(res_leaves[i]['date_to'],'%Y-%m-%d %H:%M:%S') + no = dtt - dtf + leave_days = no.days + 1 + for x in range(int(leave_days)): + dt_leave.append((dtf + mx.DateTime.RelativeDateTime(days=x)).strftime('%Y-%m-%d')) + dt_leave.sort() + todo = hours + cycle = 0 + result = [] + maxrecur = 100 + current_hour = dt_from.hour + while (todo>0) and maxrecur: + cr.execute("select hour_from,hour_to from resource_calendar_week where dayofweek='%s' and calendar_id=%s order by hour_from", (dt_from.day_of_week,id)) + for (hour_from,hour_to) in cr.fetchall(): + if (hour_to>current_hour) and (todo>0): + m = max(hour_from, current_hour) + if (hour_to-m)>todo: + hour_to = m+todo + d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) + d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60)) + dt1 = d1.strftime('%Y-%m-%d') + dt2 = d2.strftime('%Y-%m-%d') + for i in range(len(dt_leave)): + if dt1 == dt_leave[i]: + dt_from += mx.DateTime.RelativeDateTime(days=1) + d1 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(m)),int((m%1) * 60)) + d2 = mx.DateTime.DateTime(dt_from.year,dt_from.month,dt_from.day,int(math.floor(hour_to)),int((hour_to%1) * 60)) + dt1 = d1.strftime('%Y-%m-%d') + dt2 = d2.strftime('%Y-%m-%d') + result.append((d1, d2)) + current_hour = hour_to + todo -= (hour_to - m) + dt_from += mx.DateTime.RelativeDateTime(days=1) + current_hour = 0 + maxrecur -= 1 + return result + +resource_calendar() + +class resource_calendar_week(osv.osv): + _name = "resource.calendar.week" + _description = "Work Detail" + _columns = { + 'name' : fields.char("Name", size=64, required=True), + 'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of week'), + 'date_from' : fields.date('Starting date'), + 'hour_from' : fields.float('Work from', size=8, required=True), + 'hour_to' : fields.float("Work to", size=8, required=True), + 'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True), + } + _order = 'dayofweek, hour_from' +resource_calendar_week() + +class resource_resource(osv.osv): + _name = "resource.resource" + _description = "Resource Detail" + _columns = { + 'name' : fields.char("Name", size=64, required=True ), + 'code': fields.char('Code', size=16), + 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the resource record without removing it."), + 'company_id' : fields.many2one('res.company', 'Company', required=True), + 'resource_type': fields.selection([('user','Human'),('material','Material')], 'Resource Type', required=True), + 'user_id' : fields.many2one('res.users', 'User',help='Related user name for the resource to manage its access.'), + 'time_efficiency' : fields.float('Efficiency factor', size=8, help="This field depict the efficiency of the resource to complete tasks. e.g resource put alone on a phase of 5 days with 5 tasks assigned to him, will show a load of 100% for this phase by default, but if we put a efficency of 200%, then his load will only be 50%."), + 'calendar_id' : fields.many2one("resource.calendar", "Working time", help="Define the schedule of resource"), + } + _defaults = { + 'resource_type' : lambda *a: 'user', + 'time_efficiency' : lambda *a: 1, + 'active' : lambda *a: True, + 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.resource', c) + } +resource_resource() + +class resource_calendar_leaves(osv.osv): + _name = "resource.calendar.leaves" + _description = "Leave Detail" + _columns = { + 'name' : fields.char("Name", size=64), + 'company_id' : fields.related('calendar_id','company_id',type='many2one',relation='res.company',string="Company",readonly=True), + 'calendar_id' : fields.many2one("resource.calendar", "Working time"), + 'date_from' : fields.datetime('Start Date', required=True), + 'date_to' : fields.datetime('End Date', required=True), + 'resource_id' : fields.many2one("resource.resource", "Resource", help="If empty, this is a generic holiday for the company. If a resource is set, the holiday/leave is only for this resource"), + } + def check_dates(self, cr, uid, ids): + leave = self.read(cr, uid, ids[0],['date_from','date_to']) + if leave['date_from'] and leave['date_to']: + if leave['date_from'] > leave['date_to']: + return False + return True + + _constraints = [ + (check_dates, 'Error! leave start-date must be lower then leave end-date.', ['date_from', 'date_to']) + ] +resource_calendar_leaves() +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/resource/resource_view.xml b/addons/resource/resource_view.xml new file mode 100755 index 00000000000..80d0650e0c8 --- /dev/null +++ b/addons/resource/resource_view.xml @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + <menuitem icon="terp-hr" id="menu_resource_root" name="Resources Management"/> + <menuitem + id="menu_resource_reporting" + name="Reporting" + parent="menu_resource_root" + sequence="40" /> + <menuitem + id="menu_resource_configuration" + name="Configuration" + parent="menu_resource_root" + sequence="5"/> + + + <record id="resource_calendar_form" model="ir.ui.view"> + <field name="name">resource.calendar.form</field> + <field name="model">resource.calendar</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Resource Calendar"> + <field name="name" select="1"/> + <field name="manager" select="1"/> + <field name="company_id" select="1"/> + <newline/> + <field colspan="4" name="week_id" nolabel="1" widget="one2many_list"/> + </form> + </field> + </record> + <record id="action_resource_calendar_form" model="ir.actions.act_window"> + <field name="name">Resource Calendar</field> + <field name="res_model">resource.calendar</field> + <field name="view_type">form</field> + <field name="view_id" eval="False"/> + </record> + <menuitem string="Resource Calendar" action="action_resource_calendar_form" id="menu_resource_calendar_form" parent="menu_resource_configuration"/> + + <record id="view_resource_calendar_week_tree" model="ir.ui.view"> + <field name="name">resource.calendar.week.tree</field> + <field name="model">resource.calendar.week</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Working Time"> + <field name="name"/> + <field name="dayofweek"/> + <field name="hour_from" widget="float_time"/> + <field name="hour_to" widget="float_time"/> + </tree> + </field> + </record> + <record id="view_resource_calendar_week_form" model="ir.ui.view"> + <field name="name">resource.calendar.week.form</field> + <field name="model">resource.calendar.week</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Working Time"> + <field colspan="4" name="name" select="1"/> + <field name="date_from"/> + <field name="dayofweek" select="1"/> + <field name="hour_from" widget="float_time"/> + <field name="hour_to" widget="float_time"/> + </form> + </field> + </record> + + <record id="view_resource_calendar" model="ir.ui.view"> + <field name="name">resource.calendar.leaves.calendar</field> + <field name="model">resource.calendar.leaves</field> + <field name="type">calendar</field> + <field name="arch" type="xml"> + <calendar color="resource_id" date_start="date_from" string="Resource"> + <field name="name"/> + + </calendar> + </field> + </record> + + + <act_window + id="resource_calendar_closing_days" + name="Closing Days" + res_model="resource.calendar.leaves" + src_model="resource.calendar" + view_mode="calendar,tree,form" + domain="[('calendar_id','=',active_id), ('resource_id','=',False)]"/> + + <act_window + id="resource_calendar_resources_leaves" + name="Resources Leaves" + res_model="resource.calendar.leaves" + src_model="resource.calendar" + view_mode="calendar,tree,form" + domain="[('calendar_id','=',active_id), ('resource_id','!=',False)]"/> + + + <record id="resource_resource_form" model="ir.ui.view"> + <field name="name">resource.resource.form</field> + <field name="model">resource.resource</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Resource"> + <field name="name" /> + <field name="active"/> + <field name="company_id" /> + <field name="calendar_id" /> + <field name="resource_type" /> + <field name="user_id" attrs="{'required':[('resource_type','=','user')]}"/> + <field name="time_efficiency" /> + </form> + </field> + </record> + <record id="resource_resource_tree" model="ir.ui.view"> + <field name="name">resource.resource.tree</field> + <field name="model">resource.resource</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Resource"> + <field name="name" /> + <field name="company_id" /> + <field name="calendar_id" /> + <field name="resource_type" /> + <field name="user_id" /> + <field name="time_efficiency" /> + </tree> + </field> + </record> + <record id="action_resource_resource_tree" model="ir.actions.act_window"> + <field name="name">Resources</field> + <field name="res_model">resource.resource</field> + <field name="view_mode">tree,form</field> + </record> + <menuitem action="action_resource_resource_tree" id="menu_resource_resource_tree" parent="menu_resource_root"/> + + <record id="resource_calendar_leave_form" model="ir.ui.view"> + <field name="name">resource.calendar.leaves.form</field> + <field name="model">resource.calendar.leaves</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Leave Detail"> + <field name="name" /> + <field name="company_id" /> + <field name="calendar_id" /> + <field name="date_from" /> + <field name="date_to" /> + <field name="resource_id" /> + </form> + </field> + </record> + <record id="resource_calendar_leave_tree" model="ir.ui.view"> + <field name="name">resource.calendar.leaves.tree</field> + <field name="model">resource.calendar.leaves</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Leave Detail"> + <field name="name" /> + <field name="company_id" /> + <field name="calendar_id" /> + <field name="date_from" /> + <field name="date_to" /> + <field name="resource_id" /> + </tree> + </field> + </record> + <record id="action_resource_calendar_leave_tree" model="ir.actions.act_window"> + <field name="name">Leaves</field> + <field name="res_model">resource.calendar.leaves</field> + <field name="view_mode">tree,form,calendar</field> + </record> + <menuitem action="action_resource_calendar_leave_tree" id="menu_resource_calendar_leave_tree" parent="menu_resource_root"/> + + + </data> +</openerp> diff --git a/addons/resource/security/ir.model.access.csv b/addons/resource/security/ir.model.access.csv new file mode 100644 index 00000000000..0874bf97235 --- /dev/null +++ b/addons/resource/security/ir.model.access.csv @@ -0,0 +1,5 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_hr_timesheet_group","resource.calendar","model_resource_calendar","hr.group_hr_user",1,0,0,0 +"access_hr_timesheet","hr.timesheet","model_hr_timesheet","hr.group_hr_user",1,1,1,1 +"access_hr_timesheet_manager","hr.timesheet manager","model_hr_timesheet","hr.group_hr_manager",1,1,1,1 +"access_hr_timesheet_group_manager","hr.timesheet.group.manager","model_hr_timesheet_group","hr.group_hr_manager",1,1,1,1 diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 28952ba9ffe..49ba125a0a0 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -134,6 +134,7 @@ on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order, product_packaging, parent.fiscal_position)" domain="[('product_id','=',product_id)]" groups="base.group_extended"/> + <field name="company_id" groups="base.group_multi_company" widget="selection"/> <separator colspan="4" string="Manual Description"/> <field colspan="4" name="name" select="2"/> diff --git a/addons/stock/product.py b/addons/stock/product.py index 6aca67d761a..13131583a1c 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -175,6 +175,8 @@ class product_product(osv.osv): } def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): res = super(product_product,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) + if context == None: + context = {} if ('location' in context) and context['location']: location_info = self.pool.get('stock.location').browse(cr, uid, context['location']) fields=res.get('fields',{}) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index a8a497e574d..04a044077ac 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1468,7 +1468,7 @@ class stock_inventory(osv.osv): 'name': fields.char('Inventory', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}), 'date': fields.datetime('Date create', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'date_done': fields.datetime('Date done'), - 'inventory_line_id': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', states={'draft': [('readonly', False)]}), + 'inventory_line_id': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', states={'done': [('readonly', True)]}), 'move_ids': fields.many2many('stock.move', 'stock_inventory_move_rel', 'inventory_id', 'move_id', 'Created Moves'), 'state': fields.selection( (('draft', 'Draft'), ('done', 'Done'), ('cancel','Cancelled')), 'State', readonly=True), 'company_id': fields.many2one('res.company','Company',required=True,select=1), @@ -1491,12 +1491,14 @@ class stock_inventory(osv.osv): price = line.product_id.standard_price or 0.0 amount = self.pool.get('stock.location')._product_get(cr, uid, line.location_id.id, [pid], {'uom': line.product_uom.id})[pid] change = line.product_qty - amount + lot_id = line.prod_lot_id.id if change: location_id = line.product_id.product_tmpl_id.property_stock_inventory.id value = { 'name': 'INV:' + str(line.inventory_id.id) + ':' + line.inventory_id.name, 'product_id': line.product_id.id, 'product_uom': line.product_uom.id, + 'prodlot_id': lot_id, 'date': inv.date, 'date_planned': inv.date, 'state': 'assigned' @@ -1513,6 +1515,11 @@ class stock_inventory(osv.osv): 'location_id': line.location_id.id, 'location_dest_id': location_id, }) + if lot_id: + value.update({ + 'prodlot_id': lot_id, + 'product_qty': line.product_qty + }) move_ids.append(self.pool.get('stock.move').create(cr, uid, value)) if len(move_ids): self.pool.get('stock.move').action_done(cr, uid, move_ids, @@ -1544,7 +1551,8 @@ class stock_inventory_line(osv.osv): 'product_id': fields.many2one('product.product', 'Product', required=True), 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True), 'product_qty': fields.float('Quantity'), - 'company_id': fields.related('inventory_id','company_id',type='many2one',relation='res.company',string='Company',store=True) + 'company_id': fields.related('inventory_id','company_id',type='many2one',relation='res.company',string='Company',store=True), + 'prod_lot_id': fields.many2one('stock.production.lot', 'Production Lot', domain="[('product_id','=',product_id)]") } def on_change_product_id(self, cr, uid, ids, location_id, product, uom=False): if not product: diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 880153578d5..0d0de9525b4 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -20,6 +20,7 @@ <field name="product_id"/> <field name="product_qty"/> <field name="product_uom"/> + <field name="prod_lot_id"/> <field name="location_id"/> </tree> </field> @@ -33,7 +34,9 @@ <field context="location=location_id,uom=product_uom" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom)" select="1" domain="[('type','<>','service')]"/> <field name="product_qty"/> <field name="product_uom"/> + <field name="prod_lot_id"/> <field colspan="4" domain="[('usage','=','internal')]" name="location_id" select="1"/> + <button name="%(split_inventory_lots)d" string="Split Inventory Lines" type="action" icon="gtk-justify-fill"/> </form> </field> </record> @@ -68,14 +71,20 @@ <tree string="Inventory Lines" editable="bottom"> <field context="location=location_id,uom=product_uom" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom)" select="1" domain="[('type','<>','service')]"/> <field name="product_qty"/> - <field name="product_uom"/> + <field name="product_uom"/> + <field name="prod_lot_id"/> <field colspan="4" domain="[('usage','=','internal')]" name="location_id" select="1"/> </tree> <form string="Inventory Lines"> - <field context="location=location_id,uom=product_uom" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom)" select="1" domain="[('type','<>','service')]"/> + <field colspan="4" context="location=location_id,uom=product_uom" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom)" select="1" domain="[('type','<>','service')]"/> <field name="product_qty"/> <field name="product_uom"/> - <field colspan="4" domain="[('usage','=','internal')]" name="location_id" select="1"/> + <field domain="[('usage','=','internal')]" name="location_id" select="1"/> + <group colspan="2" col="3"> + <field name="prod_lot_id"/> + <button name="%(split_inventory_lots)d" string="Split in Production Lots" type="action" icon="gtk-justify-fill"/> + </group> + </form> </field> </page><page string="Posted Inventory"> diff --git a/addons/stock/stock_wizard.xml b/addons/stock/stock_wizard.xml index 2c1fc950f34..b5b0d7ce303 100644 --- a/addons/stock/stock_wizard.xml +++ b/addons/stock/stock_wizard.xml @@ -34,6 +34,13 @@ multi="True" name="stock.move.track" string="Track line"/> + + <wizard + id="split_inventory_lots" + model="stock.inventory.line" + multi="True" + name="stock.inventory.line.split" + string="Split inventory lines"/> <wizard id="make_picking" model="stock.picking" multi="True" name="stock.picking.make" string="Make picking"/> diff --git a/addons/stock/wizard/__init__.py b/addons/stock/wizard/__init__.py index 4f748525d43..e918e030721 100644 --- a/addons/stock/wizard/__init__.py +++ b/addons/stock/wizard/__init__.py @@ -31,6 +31,7 @@ import wizard_ups import wizard_invoice_onshipping import wizard_location_product import wizard_inventory +import wizard_split_inventory_lots import inventory_merge_zero import inventory_merge # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/wizard/wizard_split_inventory_lots.py b/addons/stock/wizard/wizard_split_inventory_lots.py new file mode 100644 index 00000000000..138419f45eb --- /dev/null +++ b/addons/stock/wizard/wizard_split_inventory_lots.py @@ -0,0 +1,98 @@ +import wizard +import netsvc +import pooler + +import time +from osv import osv +from tools.translate import _ + +inv_form = '''<?xml version="1.0"?> +<form string="Split Inventory Line"> + <field name="prefix"/> + <newline/> + <field name="quantity"/> +</form> +''' +inv_fields = { + 'prefix': { + 'string': 'Prefix', + 'type': 'char', + 'size': 64, + }, + 'quantity': { + 'string': 'Quantity per lot', + 'type': 'float', + 'default': 1, + } +} + +def _check_production_lot(self, cr, uid, data, context): + pool = pooler.get_pool(cr.dbname) + inv_obj = pool.get('stock.inventory.line').browse(cr, uid, data['id']) + if not inv_obj.prod_lot_id: + raise wizard.except_wizard(_('Caution!'), _('Before splitting the inventory lines, make sure the production lot is assigned to this product.')) + return data['form'] + +def _split_lines(self, cr, uid, data, context): + inv_id = data['id'] + + pool = pooler.get_pool(cr.dbname) + inv_line_obj = pool.get('stock.inventory.line') + prodlot_obj = pool.get('stock.production.lot') + + ir_sequence_obj = pool.get('ir.sequence') + + sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial') + if not sequence: + raise wizard.except_wizard(_('Error!'), _('No production sequence defined')) + if data['form']['prefix']: + sequence=data['form']['prefix']+'/'+(sequence or '') + + inv = inv_line_obj.browse(cr, uid, [inv_id])[0] + quantity=data['form']['quantity'] + prodlot_obj.write(cr, uid, inv.prod_lot_id.id, {'name':sequence}) + + if quantity <= 0 or inv.product_qty == 0: + return {} + + quantity_rest = inv.product_qty%quantity + + update_val = { + 'product_qty': quantity, + } + + new_line = [] + for idx in range(int(inv.product_qty//quantity)): + if idx: + current_line = inv_line_obj.copy(cr, uid, inv.id, {'prod_lot_id': inv.prod_lot_id.id}) + new_line.append(current_line) + else: + current_line = inv.id + inv_line_obj.write(cr, uid, [current_line], update_val) + + if quantity_rest > 0: + idx = int(inv.product_qty//quantity) + update_val['product_qty']=quantity_rest + + if idx: + current_line = inv_line_obj.copy(cr, uid, inv.id, {'prod_lot_id': inv.prod_lot_id.id}) + new_line.append(current_line) + else: + current_line = inv.id + inv_line_obj.write(cr, uid, [current_line], update_val) + + return {} + +class wizard_split_inventory_lots(wizard.interface): + states = { + 'init': { + 'actions': [_check_production_lot], + 'result': {'type': 'form', 'arch': inv_form, 'fields': inv_fields, 'state': [('end', 'Cancel', 'gtk-cancel'), ('split', 'Ok', 'gtk-ok')]}, + }, + 'split': { + 'actions': [_split_lines], + 'result': {'type':'state', 'state':'end'} + } + } + +wizard_split_inventory_lots('stock.inventory.line.split')
\ No newline at end of file |
