Merge with trunk addons

bzr revid: vir@tinyerp.com-20100120065611-inrbplhiwq2p5tg5
This commit is contained in:
Vir (Open ERP)
2010-01-20 12:26:11 +05:30
134 changed files with 4655 additions and 2815 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
{
"name" : "Accounting and financial management",
"name" : "Accounting and Financial Management",
"version" : "1.1",
"depends" : ["product", "base", "process"],
"author" : "Tiny",
+11 -11
View File
@@ -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):
+23 -20
View File
@@ -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):
+1 -1
View File
@@ -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"/>
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
82 access_account_fiscal_position account.fiscal.position all model_account_fiscal_position base.group_user 1 0 0 0
83 access_account_fiscal_position_tax account.fiscal.position.tax all model_account_fiscal_position_tax base.group_user 1 0 0 0
84 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
85 access_account_fiscal_position_template account.fiscal.position.template model_account_fiscal_position_template account.group_account_manager 1 1 1 1
86 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
87 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
+7 -7
View File
@@ -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
+4 -4
View File
@@ -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
+44 -44
View File
@@ -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
+13 -11
View File
@@ -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 -->
@@ -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},
}
+1 -1
View File
@@ -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',
}
+1
View File
@@ -21,5 +21,6 @@
import calendar
import common
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+2 -1
View File
@@ -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,
+7 -7
View File
@@ -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" />
+19
View File
@@ -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>
+21 -11
View File
@@ -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()
+506 -30
View File
@@ -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']):
+9 -5
View File
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 basic_calendar_all access_basic_calendar_all basic.calendar model_basic_calendar 1 1 1 1
3 basic_calendar_event_all access_basic_calendar_event_all basic.calendar.event model_basic_calendar_event 1 1 1 1
4 basic_calendar_attendee_all access_basic_calendar_attendee_all basic.calendar.attendee model_basic_calendar_attendee 1 1 1 1
5 access_basic_calendar_attendee access_calendar_todo_all calendar.attendee basic.calendar.todo model_basic_calendar_attendee model_basic_calendar_todo 1 1 1 1
6 access_basic_calendar_alarm access_calendar_todo_all calendar.alarm basic.calendar.todo model_basic_calendar_alarm model_basic_calendar_todo 1 1 1 1
7 access_calendar_attendee calendar.attendee model_calendar_attendee 1 1 1 1
8 access_calendar_alarm calendar.alarm model_calendar_alarm 1 1 1 1
9 access_res_alarm res.alarm model_res_alarm 1 1 1 1
10 access_calendar_event_all calendar.event model_calendar_event 1 1 1 1
+4 -2
View File
@@ -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:
@@ -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:
@@ -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:
@@ -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:
@@ -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:
+2 -2
View File
@@ -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',
+62 -1
View File
@@ -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):
+5 -42
View File
@@ -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()
+20 -10
View File
@@ -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>
+3 -3
View File
@@ -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>
+11 -59
View File
@@ -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"/>
+17 -9
View File
@@ -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>
+3 -3
View File
@@ -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>
+8 -53
View File
@@ -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"/>
+5 -43
View File
@@ -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}}
+3 -14
View File
@@ -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()
+4 -5
View File
@@ -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>
+4 -27
View File
@@ -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"/>
# ------------------------------------------------------
+5 -40
View File
@@ -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()
+42 -21
View File
@@ -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>
+9 -54
View File
@@ -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">
+10 -387
View File
@@ -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'),
'attendee_ids': fields.many2many('calendar.attendee', 'event_attendee_rel', 'event_id', 'attendee_id', 'Attendees'),
}
_defaults = {
'class': lambda *a: 'public',
'show_as': lambda *a: 'busy',
}
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:
+7 -3
View File
@@ -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>
+12 -5
View File
@@ -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>
+12 -11
View File
@@ -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>
+4 -41
View File
@@ -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()
+35 -18
View File
@@ -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>
+9 -56
View File
@@ -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">
+2 -29
View File
@@ -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()
+11 -5
View File
@@ -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>
+13 -58
View File
@@ -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"/>
+70 -2
View File
@@ -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"/>
+443 -200
View File
File diff suppressed because it is too large Load Diff
-4
View File
@@ -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
+3 -1
View File
@@ -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'),
+26 -7
View File
@@ -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')
+15
View File
@@ -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'])
+5 -41
View File
@@ -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()
+25 -13
View File
@@ -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>
+13 -56
View File
@@ -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">
+25 -4
View File
@@ -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'])
+25 -13
View File
@@ -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>
+12 -6
View File
@@ -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>
+8 -53
View File
@@ -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"/>
+6 -3
View File
@@ -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>
+4 -42
View File
@@ -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}}
+9 -3
View File
@@ -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()
+11
View File
@@ -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,
+3 -2
View File
@@ -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',
Regular → Executable
+13 -95
View File
@@ -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()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+26 -26
View File
@@ -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>
+7 -59
View File
@@ -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>
-4
View File
@@ -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
1 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
2 access_hr_employee_category hr.employee.category model_hr_employee_category hr.group_hr_user 1 0 0 0
3 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
4 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
5 access_hr_employee_category_manager hr.employee.category.manager model_hr_employee_category hr.group_hr_manager 1 1 1 1
6 access_hr_department_manager hr.department.manager model_hr_department hr.group_hr_manager 1 1 1 1
+6 -2
View File
@@ -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
+4 -4
View File
@@ -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>
+3 -3
View File
@@ -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'),
Regular → Executable
+17 -9
View File
@@ -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,
+2 -1
View File
@@ -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"
@@ -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)
@@ -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"/>
+383
View File
@@ -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 ""
+9 -19
View File
@@ -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,
+2 -2
View File
@@ -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"/>
+1 -1
View File
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
27 access_account_account account.account mrp_worker account.model_account_account mrp.group_mrp_user 1 0 0 0
28 access_purchase_order_mrp_worker purchase.order mrp_worker purchase.model_purchase_order mrp.group_mrp_user 1 0 0 0
29 access_purchase_order_line_mrp_worker purchase.order.line mrp_worker purchase.model_purchase_order_line mrp.group_mrp_user 1 0 0 0
30 access_hr_timesheet_group_mrp_worker hr.timesheet.group mrp_worker resource.calendar mrp_worker hr.model_hr_timesheet_group resource.model_resource_calendar mrp.group_mrp_user 1 0 0 0
31 access_mrp_procurement_stock_worker mrp.procurement stock_worker model_mrp_procurement stock.group_stock_user 1 1 1 1
32 access_mrp_production_stock_worker mrp.production stock_worker model_mrp_production stock.group_stock_user 1 0 0 0
+5 -5
View File
@@ -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]
+198
View File
@@ -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 ""
+1 -1
View File
@@ -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."),
+6 -6
View File
@@ -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
+3 -1
View File
@@ -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',
+137 -58
View File
@@ -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:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+26 -15
View File
@@ -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>
+59 -131
View File
@@ -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&lt;0;red:bool(date_deadline) and (date_deadline&lt;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="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
<field name="active" select="2"/>
<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"/>
<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&lt;0;red:bool(date_deadline) and (date_deadline&lt;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"
-1
View File
@@ -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>
+4 -4
View File
@@ -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
-1
View File
@@ -21,7 +21,6 @@
import close_task
import task_delegate
import task_attachment
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-49
View File
@@ -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')
-1
View File
@@ -20,6 +20,5 @@
##############################################################################
import project_calendar
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+4 -291
View File
@@ -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()
@@ -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>
@@ -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>
@@ -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:
@@ -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:

Some files were not shown because too many files have changed in this diff Show More