[MERGE]: Merge with lp:openobject-addons
bzr revid: atp@tinyerp.com-20120604050122-6g8ba2hvjugobb2u
This commit is contained in:
commit
ee0745115d
|
@ -127,6 +127,7 @@ class account_bank_statement(osv.osv):
|
|||
_order = "date desc, id desc"
|
||||
_name = "account.bank.statement"
|
||||
_description = "Bank Statement"
|
||||
_inherit = ['mail.thread']
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, states={'draft': [('readonly', False)]}, readonly=True, help='if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'), # readonly for account_cash_statement
|
||||
'date': fields.date('Date', required=True, states={'confirm': [('readonly', True)]}, select=True),
|
||||
|
@ -364,7 +365,7 @@ class account_bank_statement(osv.osv):
|
|||
'name': st_number,
|
||||
'balance_end_real': st.balance_end
|
||||
}, context=context)
|
||||
self.log(cr, uid, st.id, _('Statement %s is confirmed, journal items are created.') % (st_number,))
|
||||
self.message_append_note(cr, uid, [st.id], body=_('Statement %s is confirmed, journal items are created.') % (st_number,), context=context)
|
||||
return self.write(cr, uid, ids, {'state':'confirm'}, context=context)
|
||||
|
||||
def button_cancel(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -982,7 +982,6 @@ class account_invoice(osv.osv):
|
|||
|
||||
def invoice_validate(self, cr, uid, ids, context=None):
|
||||
self.write(cr, uid, ids, {'state':'open'}, context=context)
|
||||
self.invoice_validate_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def line_get_convert(self, cr, uid, x, part, date, context=None):
|
||||
|
@ -1046,7 +1045,7 @@ class account_invoice(osv.osv):
|
|||
if obj_inv.type in ('out_invoice', 'out_refund'):
|
||||
ctx = self.get_log_context(cr, uid, context=ctx)
|
||||
message = _("Invoice '%s' is validated.") % name
|
||||
self.log(cr, uid, inv_id, message, context=ctx)
|
||||
self.message_append_note(cr, uid, [inv_id], body=message, context=context)
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, *args):
|
||||
|
@ -1276,7 +1275,7 @@ class account_invoice(osv.osv):
|
|||
# TODO: use currency's formatting function
|
||||
msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining)") % \
|
||||
(name, pay_amount, code, invoice.amount_total, code, total, code)
|
||||
self.log(cr, uid, inv_id, msg)
|
||||
self.message_append_note(cr, uid, [inv_id], body=msg, context=context)
|
||||
self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context)
|
||||
|
||||
# Update the stored value (fields.function), so we write to trigger recompute
|
||||
|
@ -1300,10 +1299,6 @@ class account_invoice(osv.osv):
|
|||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_append_note(cr, uid, [obj.id],body=_("%s <b>created</b>.") % (self._get_document_type(obj.type)), context=context)
|
||||
|
||||
def invoice_validate_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_append_note(cr, uid, [obj.id], body=_("%s <b>validated</b>.") % (self._get_document_type(obj.type)), context=context)
|
||||
|
||||
def confirm_paid_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_append_note(cr, uid, [obj.id], body=_("%s <b>paid</b>.") % (self._get_document_type(obj.type)), context=context)
|
||||
|
|
|
@ -132,8 +132,6 @@
|
|||
<field name="amount_untaxed" sum="Untaxed Amount"/>
|
||||
<field name="amount_total" sum="Total Amount"/>
|
||||
<field name="state"/>
|
||||
|
||||
<button name="invoice_open" states="draft,proforma2" string="Approve" icon="terp-camera_test"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -249,7 +247,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -354,7 +352,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -131,8 +131,6 @@
|
|||
<field name="special"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="state"/>
|
||||
<button name="action_draft" states="done" string="Set to Draft" type="object" icon="terp-document-new" groups="account.group_account_manager"/>
|
||||
<button name="%(action_account_period_close)d" states="draft" string="Close Period" type="action" icon="terp-camera_test"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -569,8 +567,6 @@
|
|||
<field name="balance_end_real"/>
|
||||
<field name="balance_end" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button type="object" string="Cancel" name="button_cancel" states="confirm" icon="gtk-cancel"/>
|
||||
<button type="object" string="Confirm" name="button_confirm_bank" states="draft" icon="terp-camera_test"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -1356,7 +1352,6 @@
|
|||
<field name="amount" sum="Total Amount"/>
|
||||
<field name="to_check"/>
|
||||
<field name="state"/>
|
||||
<button name="button_validate" states="draft" string="Approve" type="object" icon="terp-camera_test"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -2627,9 +2622,6 @@ action = pool.get('res.config').next(cr, uid, [], context)
|
|||
<field name="balance_end_real"/>
|
||||
<field name="balance_end"/>
|
||||
<field name="state"/>
|
||||
<button type="object" string="Cancel" name="button_cancel" states="confirm" icon="gtk-cancel"/>
|
||||
<button type="object" string="Open" name="button_open" states="draft" icon="terp-camera_test"/>
|
||||
<button type="object" string="Confirm" name="button_confirm_bank" states="open" icon="terp-gtk-go-back-rtl"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-01 05:33+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: account
|
||||
|
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-01 05:33+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: account_bank_statement_extensions
|
||||
|
|
|
@ -8,14 +8,14 @@ msgstr ""
|
|||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:35+0000\n"
|
||||
"PO-Revision-Date: 2012-05-10 18:14+0000\n"
|
||||
"Last-Translator: Raphael Collet (OpenERP) <Unknown>\n"
|
||||
"PO-Revision-Date: 2012-06-01 06:41+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-05-11 05:15+0000\n"
|
||||
"X-Generator: Launchpad (build 15225)\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: account_check_writing
|
||||
#: selection:res.company,check_layout:0
|
||||
|
@ -100,7 +100,7 @@ msgstr "小切手の振出"
|
|||
#: report:account.print.check.middle:0
|
||||
#: report:account.print.check.top:0
|
||||
msgid "Discount"
|
||||
msgstr "割引き"
|
||||
msgstr "割引"
|
||||
|
||||
#. module: account_check_writing
|
||||
#: report:account.print.check.bottom:0
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
<field name="balance" sum="Balance"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="blocked" invisible="1" />
|
||||
<field name="period_id" invisible="1" />
|
||||
|
||||
<field name="period_id" invisible="1" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -193,9 +193,6 @@
|
|||
<field name="date_done"/>
|
||||
<field name="total"/>
|
||||
<field name="state"/>
|
||||
<button name="cancel" states="draft,open" string="Cancel" icon="gtk-cancel"/>
|
||||
<button name="open" states="draft" string="Confirm Payments" icon="gtk-apply"/>
|
||||
<button name="set_done" states="open" string="Make Payments" type ="object" icon="gtk-execute"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
<field name="amount" sum="Total Amount"/>
|
||||
<field name="audit"/>
|
||||
<field name="state"/>
|
||||
<button name="proforma_voucher" string="Post" states="draft" icon="terp-document-new"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -814,7 +814,6 @@ class calendar_alarm(osv.osv):
|
|||
context = {}
|
||||
mail_message = self.pool.get('mail.message')
|
||||
current_datetime = datetime.now()
|
||||
request_obj = self.pool.get('res.request')
|
||||
alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context)
|
||||
|
||||
mail_to = []
|
||||
|
@ -854,26 +853,28 @@ class calendar_alarm(osv.osv):
|
|||
ref = alarm.model_id.model + ',' + str(alarm.res_id)
|
||||
|
||||
# search for alreay sent requests
|
||||
if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
|
||||
continue
|
||||
#if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
|
||||
#continue
|
||||
|
||||
if alarm.action == 'display':
|
||||
value = {
|
||||
'name': alarm.name,
|
||||
'act_from': alarm.user_id.id,
|
||||
'act_to': alarm.user_id.id,
|
||||
'body': alarm.description,
|
||||
'trigger_date': r_date,
|
||||
'ref_doc1': ref
|
||||
}
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids = [request_id]
|
||||
for attendee in res_obj.attendee_ids:
|
||||
if attendee.user_id:
|
||||
value['act_to'] = attendee.user_id.id
|
||||
request_id = request_obj.create(cr, uid, value)
|
||||
request_ids.append(request_id)
|
||||
request_obj.request_send(cr, uid, request_ids)
|
||||
# Deactivated because of the removing of res.request
|
||||
# TODO: when cleaning calendar module, re-add this in a new mechanism
|
||||
#if alarm.action == 'display':
|
||||
#value = {
|
||||
#'name': alarm.name,
|
||||
#'act_from': alarm.user_id.id,
|
||||
#'act_to': alarm.user_id.id,
|
||||
#'body': alarm.description,
|
||||
#'trigger_date': r_date,
|
||||
#'ref_doc1': ref
|
||||
#}
|
||||
#request_id = request_obj.create(cr, uid, value)
|
||||
#request_ids = [request_id]
|
||||
#for attendee in res_obj.attendee_ids:
|
||||
#if attendee.user_id:
|
||||
#value['act_to'] = attendee.user_id.id
|
||||
#request_id = request_obj.create(cr, uid, value)
|
||||
#request_ids.append(request_id)
|
||||
#request_obj.request_send(cr, uid, request_ids)
|
||||
|
||||
if alarm.action == 'email':
|
||||
sub = '[Openobject Reminder] %s' % (alarm.name)
|
||||
|
|
|
@ -85,21 +85,6 @@
|
|||
<field name="cutype" string="Invitation Type"/>
|
||||
<field name="state" />
|
||||
<field name="rsvp" string="Required to Join"/>
|
||||
<button name="do_tentative" states="needs-action,declined,accepted"
|
||||
string="Uncertain" type="object"
|
||||
icon="terp-crm" />
|
||||
<button name="do_accept" string="Accept"
|
||||
states="needs-action,tentative,declined"
|
||||
type="object" icon="gtk-apply" />
|
||||
<button name="do_decline" string="Decline"
|
||||
states="needs-action,tentative,accepted"
|
||||
type="object" icon="gtk-cancel" />
|
||||
<button
|
||||
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
|
||||
string="Delegate" type="action"
|
||||
icon="gtk-sort-descending"
|
||||
states="needs-action,tentative,declined,accepted"
|
||||
context="{'model' : 'calendar.attendee', 'attendee_field' : 'child_ids'}" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2012-today OpenERP SA (<http://openerp.com>)
|
||||
#
|
||||
# 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 base_state
|
||||
import base_stage
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2012-today OpenERP SA (<http://openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'State/Stage Management',
|
||||
'version': '1.0',
|
||||
'category': 'Hidden',
|
||||
'description': """
|
||||
This module handles state and stage. It is derived from the crm_base and
|
||||
crm_case classes from crm.
|
||||
|
||||
* ``base_state``: state management
|
||||
* ``base_stage``: stage management
|
||||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['base'],
|
||||
'init_xml': [],
|
||||
'update_xml': [],
|
||||
'demo_xml': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,432 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields
|
||||
from tools.translate import _
|
||||
|
||||
class base_stage(object):
|
||||
""" Base utility mixin class for objects willing to manage their stages.
|
||||
Object that inherit from this class should inherit from mailgate.thread
|
||||
to have access to the mail gateway, as well as Chatter. Objects
|
||||
subclassing this class should define the following colums:
|
||||
- ``date_open`` (datetime field)
|
||||
- ``date_closed`` (datetime field)
|
||||
- ``user_id`` (many2one to res.users)
|
||||
- ``partner_id`` (many2one to res.partner)
|
||||
- ``stage_id`` (many2one to a stage definition model)
|
||||
- ``state`` (selection field, related to the stage_id.state)
|
||||
"""
|
||||
|
||||
def _get_default_partner(self, cr, uid, context=None):
|
||||
""" Gives id of partner for current user
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if hasattr(user, 'partner_address_id') and user.partner_address_id:
|
||||
return user.partner_address_id
|
||||
return user.company_id.partner_id.id
|
||||
|
||||
def _get_default_email(self, cr, uid, context=None):
|
||||
""" Gives default email address for current user
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.user_email
|
||||
|
||||
def _get_default_user(self, cr, uid, context=None):
|
||||
""" Gives current user id
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
return uid
|
||||
|
||||
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
|
||||
""" This function returns value of partner email based on Partner Address
|
||||
:param add: Id of Partner's address
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data = {'value': {'email_from': False, 'phone':False}}
|
||||
if add:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, add)
|
||||
data['value'] = {'email_from': address and address.email or False ,
|
||||
'phone': address and address.phone or False}
|
||||
if 'phone' not in self._columns:
|
||||
del data['value']['phone']
|
||||
return data
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part, email=False):
|
||||
""" This function returns value of partner address based on partner
|
||||
:param part: Partner's id
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data={}
|
||||
if part:
|
||||
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
|
||||
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
|
||||
return {'value': data}
|
||||
|
||||
def _get_default_section_id(self, cr, uid, context=None):
|
||||
""" Gives default section """
|
||||
return False
|
||||
|
||||
def _get_default_stage_id(self, cr, uid, context=None):
|
||||
""" Gives default stage_id """
|
||||
return self.stage_find(cr, uid, [], None, [('state', '=', 'draft')], context=context)
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Find stage, with a given (optional) domain on the search,
|
||||
ordered by the order parameter. If several stages match the
|
||||
search criterions, the first one will be returned, according
|
||||
to the requested search order.
|
||||
This method is meant to be overriden by subclasses. That way
|
||||
specific behaviors can be achieved for every class inheriting
|
||||
from base_stage.
|
||||
|
||||
:param cases: browse_record of cases
|
||||
:param section_id: section limitating the search, given for
|
||||
a generic search (for example default search).
|
||||
A section models concepts such as Sales team
|
||||
(for CRM), ou departments (for HR).
|
||||
:param domain: a domain on the search of stages
|
||||
:param order: order of the search
|
||||
"""
|
||||
return False
|
||||
|
||||
def stage_set_with_state_name(self, cr, uid, cases, state_name, context=None):
|
||||
""" Set a new stage, with a state_name instead of a stage_id
|
||||
:param cases: browse_record of cases
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
for case in cases:
|
||||
stage_id = self.stage_find(cr, uid, [case], None, [('state', '=', state_name)], context=context)
|
||||
if stage_id:
|
||||
self.stage_set(cr, uid, [case.id], stage_id, context=context)
|
||||
return True
|
||||
|
||||
def stage_set(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Set the new stage. This methods is the right method to call
|
||||
when changing states. It also checks whether an onchange is
|
||||
defined, and execute it.
|
||||
"""
|
||||
value = {}
|
||||
if hasattr(self, 'onchange_stage_id'):
|
||||
value = self.onchange_stage_id(cr, uid, ids, stage_id, context=context)['value']
|
||||
value['stage_id'] = stage_id
|
||||
self.stage_set_send_note(cr, uid, ids, stage_id, context=context)
|
||||
return self.write(cr, uid, ids, value, context=context)
|
||||
|
||||
def stage_change(self, cr, uid, ids, op, order, context=None):
|
||||
""" Change the stage and take the next one, based on a condition
|
||||
writen for the 'sequence' field and an operator. This methods
|
||||
checks whether the case has a current stage, and takes its
|
||||
sequence. Otherwise, a default 0 sequence is chosen and this
|
||||
method will therefore choose the first available stage.
|
||||
For example if op is '>' and current stage has a sequence of
|
||||
10, this will call stage_find, with [('sequence', '>', '10')].
|
||||
"""
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
seq = 0
|
||||
if case.stage_id:
|
||||
seq = case.stage_id.sequence or 0
|
||||
section_id = None
|
||||
next_stage_id = self.stage_find(cr, uid, [case], None, [('sequence', op, seq)],order, context=context)
|
||||
if next_stage_id:
|
||||
return self.stage_set(cr, uid, [case.id], next_stage_id, context=context)
|
||||
return False
|
||||
|
||||
def stage_next(self, cr, uid, ids, context=None):
|
||||
""" This function computes next stage for case from its current stage
|
||||
using available stage for that case type
|
||||
"""
|
||||
return self.stage_change(cr, uid, ids, '>','sequence', context)
|
||||
|
||||
def stage_previous(self, cr, uid, ids, context=None):
|
||||
""" This function computes previous stage for case from its current
|
||||
stage using available stage for that case type
|
||||
"""
|
||||
return self.stage_change(cr, uid, ids, '<', 'sequence desc', context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
""" Overrides orm copy method to avoid copying messages,
|
||||
as well as date_closed and date_open columns if they
|
||||
exist."""
|
||||
if default is None:
|
||||
default = {}
|
||||
|
||||
if hasattr(self, '_columns'):
|
||||
if self._columns.get('date_closed'):
|
||||
default.update({ 'date_closed': False, })
|
||||
if self._columns.get('date_open'):
|
||||
default.update({ 'date_open': False })
|
||||
return super(base_stage, self).copy(cr, uid, id, default, context=context)
|
||||
|
||||
def case_escalate(self, cr, uid, ids, context=None):
|
||||
""" Escalates case to parent level """
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
cases[0].state # fill browse record cache, for _action having old and new values
|
||||
for case in cases:
|
||||
data = {'active': True}
|
||||
if case.section_id.parent_id:
|
||||
data['section_id'] = case.section_id.parent_id.id
|
||||
if case.section_id.parent_id.change_responsible:
|
||||
if case.section_id.parent_id.user_id:
|
||||
data['user_id'] = case.section_id.parent_id.user_id.id
|
||||
else:
|
||||
raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
self.write(cr, uid, [case.id], data, context=context)
|
||||
case.case_escalate_send_note(case.section_id.parent_id, context=context)
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'escalate', context=context)
|
||||
return True
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
""" Opens case """
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
for case in cases:
|
||||
data = {'active': True}
|
||||
if case.stage_id and case.stage_id.state == 'draft':
|
||||
data['date_open'] = fields.datetime.now()
|
||||
if not case.user_id:
|
||||
data['user_id'] = uid
|
||||
self.case_set(cr, uid, [case.id], 'open', data, context=context)
|
||||
self.case_open_send_note(cr, uid, [case.id], context=context)
|
||||
return True
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
""" Closes case """
|
||||
self.case_set(cr, uid, ids, 'done', {'active': True, 'date_closed': fields.datetime.now()}, context=context)
|
||||
self.case_close_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
""" Cancels case """
|
||||
self.case_set(cr, uid, ids, 'cancel', {'active': True}, context=context)
|
||||
self.case_cancel_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_pending(self, cr, uid, ids, context=None):
|
||||
""" Set case as pending """
|
||||
self.case_set(cr, uid, ids, 'pending', {'active': True}, context=context)
|
||||
self.case_pending_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
""" Resets case as draft """
|
||||
self.case_set(cr, uid, ids, 'draft', {'active': True}, context=context)
|
||||
self.case_reset_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_set(self, cr, uid, ids, new_state_name=None, values_to_update=None, new_stage_id=None, context=None):
|
||||
""" Generic method for setting case. This methods wraps the update
|
||||
of the record, as well as call to _action and browse_record
|
||||
case setting to fill the cache.
|
||||
|
||||
:params new_state_name: the new state of the record; this method
|
||||
will call ``stage_set_with_state_name``
|
||||
that will find the stage matching the
|
||||
new state, using the ``stage_find`` method.
|
||||
:params new_stage_id: alternatively, you may directly give the
|
||||
new stage of the record
|
||||
:params state_name: the new value of the state, such as
|
||||
'draft' or 'close'.
|
||||
:params update_values: values that will be added with the state
|
||||
update when writing values to the record.
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
cases[0].state # fill browse record cache, for _action having old and new values
|
||||
# 1. update the stage
|
||||
if new_state_name:
|
||||
self.stage_set_with_state_name(cr, uid, cases, new_state_name, context=context)
|
||||
elif not (new_stage_id is None):
|
||||
self.stage_set(cr, uid, ids, new_stage_id, context=context)
|
||||
# 2. update values
|
||||
if values_to_update:
|
||||
self.write(cr, uid, ids, values_to_update, context=context)
|
||||
# 3. call _action for base action rule
|
||||
if new_state_name:
|
||||
self._action(cr, uid, cases, new_state_name, context=context)
|
||||
elif not (new_stage_id is None):
|
||||
new_state_name = self.read(cr, uid, ids, ['state'], context=context)[0]['state']
|
||||
self._action(cr, uid, cases, new_state_name, context=context)
|
||||
return True
|
||||
|
||||
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
context['state_to'] = state_to
|
||||
rule_obj = self.pool.get('base.action.rule')
|
||||
if not rule_obj:
|
||||
return True
|
||||
model_obj = self.pool.get('ir.model')
|
||||
model_ids = model_obj.search(cr, uid, [('model','=',self._name)], context=context)
|
||||
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])], context=context)
|
||||
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
|
||||
|
||||
def remind_partner(self, cr, uid, ids, context=None, attach=False):
|
||||
return self.remind_user(cr, uid, ids, context, attach,
|
||||
destination=False)
|
||||
|
||||
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
|
||||
mail_message = self.pool.get('mail.message')
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
if not destination and not case.email_from:
|
||||
return False
|
||||
if not case.user_id.user_email:
|
||||
return False
|
||||
if destination and case.section_id.user_id:
|
||||
case_email = case.section_id.user_id.user_email
|
||||
else:
|
||||
case_email = case.user_id.user_email
|
||||
|
||||
src = case_email
|
||||
dest = case.user_id.user_email or ""
|
||||
body = case.description or ""
|
||||
for message in case.message_ids:
|
||||
if message.email_from and message.body_text:
|
||||
body = message.body_text
|
||||
break
|
||||
|
||||
if not destination:
|
||||
src, dest = dest, case.email_from
|
||||
if body and case.user_id.signature:
|
||||
if body:
|
||||
body += '\n\n%s' % (case.user_id.signature)
|
||||
else:
|
||||
body = '\n\n%s' % (case.user_id.signature)
|
||||
|
||||
body = self.format_body(body)
|
||||
|
||||
attach_to_send = {}
|
||||
|
||||
if attach:
|
||||
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
|
||||
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
|
||||
attach_to_send = dict(map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send))
|
||||
|
||||
# Send an email
|
||||
subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
|
||||
mail_message.schedule_with_attach(cr, uid,
|
||||
src,
|
||||
[dest],
|
||||
subject,
|
||||
body,
|
||||
model=self._name,
|
||||
reply_to=case.section_id.reply_to,
|
||||
res_id=case.id,
|
||||
attachments=attach_to_send,
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
def _check(self, cr, uid, ids=False, context=None):
|
||||
""" Function called by the scheduler to process cases for date actions.
|
||||
Must be overriden by inheriting classes.
|
||||
"""
|
||||
return True
|
||||
|
||||
def format_body(self, body):
|
||||
return self.pool.get('base.action.rule').format_body(body)
|
||||
|
||||
def format_mail(self, obj, body):
|
||||
return self.pool.get('base.action.rule').format_mail(obj, body)
|
||||
|
||||
def message_thread_followers(self, cr, uid, ids, context=None):
|
||||
res = {}
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
l=[]
|
||||
if case.email_cc:
|
||||
l.append(case.email_cc)
|
||||
if case.user_id and case.user_id.user_email:
|
||||
l.append(case.user_id.user_email)
|
||||
res[case.id] = l
|
||||
return res
|
||||
|
||||
# ******************************
|
||||
# Notifications
|
||||
# ******************************
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
""" Default prefix for notifications. For example: "%s has been
|
||||
<b>closed</b>.". As several models will inherit from base_stage,
|
||||
this method returns a void string. Class using base_stage
|
||||
will have to override this method to define the prefix they
|
||||
want to display.
|
||||
"""
|
||||
return ''
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Send a notification when the stage changes. This method has
|
||||
to be overriden, because each document will have its particular
|
||||
behavior and/or stage model (such as project.task.type or
|
||||
crm.case.stage).
|
||||
"""
|
||||
return True
|
||||
|
||||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>opened</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_close_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>closed</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_cancel_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>canceled</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_pending_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s is now <b>pending</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_reset_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>renewed</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_escalate_send_note(self, cr, uid, ids, new_section=None, context=None):
|
||||
for id in ids:
|
||||
if new_section:
|
||||
msg = '%s has been <b>escalated</b> to <b>%s</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context), new_section.name)
|
||||
else:
|
||||
msg = '%s has been <b>escalated</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], 'System Notification', msg, context=context)
|
||||
return True
|
|
@ -0,0 +1,194 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields
|
||||
from tools.translate import _
|
||||
|
||||
class base_state(object):
|
||||
""" Base utility mixin class for objects willing to manage their state.
|
||||
Object subclassing this class should define the following colums:
|
||||
- ``date_open`` (datetime field)
|
||||
- ``date_closed`` (datetime field)
|
||||
- ``user_id`` (many2one to res.users)
|
||||
- ``partner_id`` (many2one to res.partner)
|
||||
- ``state`` (selection field)
|
||||
"""
|
||||
|
||||
def _get_default_partner(self, cr, uid, context=None):
|
||||
""" Gives id of partner for current user
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if hasattr(user, 'partner_address_id') and user.partner_address_id:
|
||||
return user.partner_address_id
|
||||
return user.company_id.partner_id.id
|
||||
|
||||
def _get_default_email(self, cr, uid, context=None):
|
||||
""" Gives default email address for current user
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.user_email
|
||||
|
||||
def _get_default_user(self, cr, uid, context=None):
|
||||
""" Gives current user id
|
||||
:param context: if portal not in context returns False
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context or not context.get('portal'):
|
||||
return False
|
||||
return uid
|
||||
|
||||
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
|
||||
""" This function returns value of partner email based on Partner Address
|
||||
:param add: Id of Partner's address
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data = {'value': {'email_from': False, 'phone':False}}
|
||||
if add:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, add)
|
||||
data['value'] = {'email_from': address and address.email or False ,
|
||||
'phone': address and address.phone or False}
|
||||
if 'phone' not in self._columns:
|
||||
del data['value']['phone']
|
||||
return data
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part, email=False):
|
||||
""" This function returns value of partner address based on partner
|
||||
:param part: Partner's id
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data={}
|
||||
if part:
|
||||
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
|
||||
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
|
||||
return {'value': data}
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
""" Opens case """
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
for case in cases:
|
||||
values = {'active': True}
|
||||
if case.state == 'draft':
|
||||
values['date_open'] = fields.datetime.now()
|
||||
if not case.user_id:
|
||||
values['user_id'] = uid
|
||||
self.case_set(cr, uid, [case.id], 'open', values, context=context)
|
||||
self.case_open_send_note(cr, uid, [case.id], context=context)
|
||||
return True
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
""" Closes case """
|
||||
self.case_set(cr, uid, ids, 'done', {'date_closed': fields.datetime.now()}, context=context)
|
||||
self.case_close_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
""" Cancels case """
|
||||
self.case_set(cr, uid, ids, 'cancel', {'active': True}, context=context)
|
||||
self.case_cancel_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_pending(self, cr, uid, ids, context=None):
|
||||
""" Sets case as pending """
|
||||
self.case_set(cr, uid, ids, 'pending', {'active': True}, context=context)
|
||||
self.case_pending_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
""" Resets case as draft """
|
||||
self.case_set(cr, uid, ids, 'draft', {'active': True}, context=context)
|
||||
self.case_reset_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_set(self, cr, uid, ids, state_name, update_values=None, context=None):
|
||||
""" Generic method for setting case. This methods wraps the update
|
||||
of the record, as well as call to _action and browse_record
|
||||
case setting to fill the cache.
|
||||
|
||||
:params: state_name: the new value of the state, such as
|
||||
'draft' or 'close'.
|
||||
:params: update_values: values that will be added with the state
|
||||
update when writing values to the record.
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids, context=context)
|
||||
cases[0].state # fill browse record cache, for _action having old and new values
|
||||
if update_values is None:
|
||||
update_values = {}
|
||||
update_values['state'] = state_name
|
||||
self.write(cr, uid, ids, update_values, context=context)
|
||||
self._action(cr, uid, cases, state_name, context=context)
|
||||
|
||||
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
context['state_to'] = state_to
|
||||
rule_obj = self.pool.get('base.action.rule')
|
||||
model_obj = self.pool.get('ir.model')
|
||||
model_ids = model_obj.search(cr, uid, [('model','=',self._name)])
|
||||
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])])
|
||||
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
|
||||
|
||||
# ******************************
|
||||
# Notifications
|
||||
# ******************************
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return ''
|
||||
|
||||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>opened</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_close_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>closed</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_cancel_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>canceled</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_pending_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s is now <b>pending</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_reset_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = _('%s has been <b>renewed</b>.') % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
|
@ -30,7 +30,7 @@ Synchronization with all objects.
|
|||
|
||||
Configure servers and trigger synchronization with its database objects.
|
||||
""",
|
||||
"depends": ["base"],
|
||||
"depends": ["base", "mail"],
|
||||
"demo_xml": [],
|
||||
"update_xml": [
|
||||
"wizard/base_synchro_view.xml",
|
||||
|
|
|
@ -234,7 +234,6 @@ class base_synchro(osv.osv_memory):
|
|||
self.pool.get('base.synchro.obj').write(cr, uid, [object.id], {'synchronize_date': dt})
|
||||
end_date = time.strftime('%Y-%m-%d, %Hh %Mm %Ss')
|
||||
if syn_obj.user_id:
|
||||
request = pooler.get_pool(cr.dbname).get('res.request')
|
||||
if not self.report:
|
||||
self.report.append('No exception.')
|
||||
summary = '''Here is the synchronization report:
|
||||
|
@ -249,12 +248,8 @@ Records created: %d
|
|||
Exceptions:
|
||||
'''% (start_date,end_date,self.report_total, self.report_write,self.report_create)
|
||||
summary += '\n'.join(self.report)
|
||||
request.create(cr, uid, {
|
||||
'name' : "Synchronization report",
|
||||
'act_from' : uid,
|
||||
'act_to' : syn_obj.user_id.id,
|
||||
'body': summary,
|
||||
})
|
||||
# Chatter: old res.request transformed into a message added to the destination user
|
||||
self.pool.get('res.users').message_append_note(cr, uid, [syn_obj.user_id.id], body=summary, subject=_('Synchronization Report'), context=context)
|
||||
return True
|
||||
|
||||
def upload_download_multi_thread(self, cr, uid, data, context=None):
|
||||
|
|
|
@ -57,6 +57,7 @@ Creates a dashboard for CRM that includes:
|
|||
'depends': [
|
||||
'base_action_rule',
|
||||
'base_setup',
|
||||
'base_status',
|
||||
'process',
|
||||
'mail',
|
||||
'base_calendar',
|
||||
|
@ -66,7 +67,6 @@ Creates a dashboard for CRM that includes:
|
|||
],
|
||||
'init_xml': [
|
||||
'crm_data.xml',
|
||||
'crm_meeting_data.xml',
|
||||
'crm_lead_data.xml',
|
||||
'crm_meeting_data.xml',
|
||||
'crm_phonecall_data.xml',
|
||||
|
|
|
@ -11,27 +11,10 @@
|
|||
<field name="name" string="Opportunity"/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next Stage"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="planned_revenue" sum="Total of Planned Revenue"/>
|
||||
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="open,draft" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_mark_lost" string="Lost"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
<button name="case_close" string="Won"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-apply" />
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,12 +19,11 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
import base64
|
||||
import tools
|
||||
|
||||
import time
|
||||
from osv import fields
|
||||
from osv import osv
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
MAX_LEVEL = 15
|
||||
|
@ -57,8 +56,11 @@ class crm_case_channel(osv.osv):
|
|||
}
|
||||
|
||||
class crm_case_stage(osv.osv):
|
||||
""" Stage of case """
|
||||
|
||||
""" Model for case stages. This models the main stages of a document
|
||||
management flow. Main CRM objects (leads, opportunities, project
|
||||
issues, ...) will now use only stages, instead of state and stages.
|
||||
Stages are for example used to display the kanban view of records.
|
||||
"""
|
||||
_name = "crm.case.stage"
|
||||
_description = "Stage of case"
|
||||
_rec_name = 'name'
|
||||
|
@ -66,22 +68,34 @@ class crm_case_stage(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.char('Stage Name', size=64, required=True, translate=True),
|
||||
'sequence': fields.integer('Sequence', help="Used to order stages."),
|
||||
'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
|
||||
'probability': fields.float('Probability (%)', required=True, help="This percentage depicts the default/average probability of the Case for this stage to be a success"),
|
||||
'on_change': fields.boolean('Change Probability Automatically', help="Setting this stage will change the probability automatically on the opportunity."),
|
||||
'requirements': fields.text('Requirements'),
|
||||
'section_ids':fields.many2many('crm.case.section', 'section_stage_rel', 'stage_id', 'section_id', 'Sections'),
|
||||
'case_default': fields.boolean('Common to All Teams', help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
|
||||
'section_ids':fields.many2many('crm.case.section', 'section_stage_rel', 'stage_id', 'section_id', string='Sections',
|
||||
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
|
||||
'state': fields.selection(AVAILABLE_STATES, 'State', required=True, help="The related state for the stage. The state of your document will automatically change regarding the selected stage. For example, if a stage is related to the state 'Close', when your document reaches this stage, it will be automatically have the 'closed' state."),
|
||||
'case_default': fields.boolean('Common to All Teams',
|
||||
help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
|
||||
'fold': fields.boolean('Hide in Views when Empty',
|
||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
'type': fields.selection([ ('lead','Lead'),
|
||||
('opportunity', 'Opportunity'),
|
||||
('both', 'Both')],
|
||||
string='Type', size=16, required=True,
|
||||
help="This field is used to distinguish stages related to Leads from stages related to Opportunities, or to specify stages available for both types."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'sequence': lambda *args: 1,
|
||||
'probability': lambda *args: 0.0,
|
||||
'state': 'draft',
|
||||
'fold': False,
|
||||
'type': 'both',
|
||||
}
|
||||
|
||||
class crm_case_section(osv.osv):
|
||||
"""Sales Team"""
|
||||
|
||||
""" Model for sales teams. """
|
||||
_name = "crm.case.section"
|
||||
_description = "Sales Teams"
|
||||
_order = "complete_name"
|
||||
|
@ -107,6 +121,7 @@ class crm_case_section(osv.osv):
|
|||
'working_hours': fields.float('Working Hours', digits=(16,2 )),
|
||||
'stage_ids': fields.many2many('crm.case.stage', 'section_stage_rel', 'section_id', 'stage_id', 'Stages'),
|
||||
}
|
||||
|
||||
def _get_stage_common(self, cr, uid, context):
|
||||
ids = self.pool.get('crm.case.stage').search(cr, uid, [('case_default','=',1)], context=context)
|
||||
return ids
|
||||
|
@ -171,429 +186,6 @@ class crm_case_resource_type(osv.osv):
|
|||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
}
|
||||
|
||||
class crm_base(object):
|
||||
""" Base utility mixin class for crm objects,
|
||||
Object subclassing this should define colums:
|
||||
date_open
|
||||
date_closed
|
||||
user_id
|
||||
partner_id
|
||||
"""
|
||||
def _get_default_partner_address(self, cr, uid, context=None):
|
||||
"""Gives id of default address for current user
|
||||
:param context: if portal in context is false return false anyway
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context.get('portal'):
|
||||
return False
|
||||
# was user.address_id.id, but address_id has been removed
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if hasattr(user, 'partner_address_id') and user.partner_address_id:
|
||||
return user.partner_address_id
|
||||
return False
|
||||
|
||||
def _get_default_partner(self, cr, uid, context=None):
|
||||
"""Gives id of partner for current user
|
||||
:param context: if portal in context is false return false anyway
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context.get('portal', False):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if hasattr(user, 'partner_address_id') and user.partner_address_id:
|
||||
return user.partner_address_id
|
||||
return user.company_id.partner_id.id
|
||||
|
||||
def _get_default_email(self, cr, uid, context=None):
|
||||
"""Gives default email address for current user
|
||||
:param context: if portal in context is false return false anyway
|
||||
"""
|
||||
if not context.get('portal', False):
|
||||
return False
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.user_email
|
||||
|
||||
def _get_default_user(self, cr, uid, context=None):
|
||||
"""Gives current user id
|
||||
:param context: if portal in context is false return false anyway
|
||||
"""
|
||||
if context and context.get('portal', False):
|
||||
return False
|
||||
return uid
|
||||
|
||||
def _get_section(self, cr, uid, context=None):
|
||||
return False
|
||||
|
||||
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
|
||||
"""This function returns value of partner email based on Partner Address
|
||||
:param ids: List of case IDs
|
||||
:param add: Id of Partner's address
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data = {'value': {'email_from': False, 'phone':False}}
|
||||
if add:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, add)
|
||||
data['value'] = {'email_from': address and address.email or False ,
|
||||
'phone': address and address.phone or False}
|
||||
if 'phone' not in self._columns:
|
||||
del data['value']['phone']
|
||||
return data
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part, email=False):
|
||||
"""This function returns value of partner address based on partner
|
||||
:param ids: List of case IDs
|
||||
:param part: Partner's id
|
||||
:param email: Partner's email ID
|
||||
"""
|
||||
data={}
|
||||
if part:
|
||||
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
|
||||
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
|
||||
return {'value': data}
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return ''
|
||||
|
||||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = '%s has been <b>opened</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_close_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = '%s has been <b>closed</b>.'% (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_cancel_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = '%s has been <b>canceled</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_pending_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = '%s is now <b>pending</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_reset_send_note(self, cr, uid, ids, context=None):
|
||||
for id in ids:
|
||||
msg = '%s has been <b>renewed</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
"""Opens Case
|
||||
:param ids: List of case Ids
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
for case in cases:
|
||||
data = {'state': 'open', 'active': True}
|
||||
if not case.user_id:
|
||||
data['user_id'] = uid
|
||||
self.write(cr, uid, [case.id], data)
|
||||
self.case_open_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'open')
|
||||
|
||||
return True
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
"""Closes Case
|
||||
:param ids: List of case Ids
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'), })
|
||||
# We use the cache of cases to keep the old case state
|
||||
self.case_close_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'done')
|
||||
return True
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
"""Cancels Case
|
||||
:param ids: List of case Ids
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'cancel', 'active': True})
|
||||
# We use the cache of cases to keep the old case state
|
||||
self.case_cancel_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'cancel')
|
||||
return True
|
||||
|
||||
def case_pending(self, cr, uid, ids, context=None):
|
||||
"""Marks case as pending
|
||||
:param ids: List of case Ids
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
|
||||
self.case_pending_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'pending')
|
||||
return True
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
"""Resets case as draft
|
||||
:param ids: List of case Ids
|
||||
"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'draft', 'active': True})
|
||||
self.case_reset_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'draft')
|
||||
return True
|
||||
|
||||
def _action(self, cr, uid, cases, state_to, scrit=None, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
context['state_to'] = state_to
|
||||
rule_obj = self.pool.get('base.action.rule')
|
||||
model_obj = self.pool.get('ir.model')
|
||||
model_ids = model_obj.search(cr, uid, [('model','=',self._name)])
|
||||
rule_ids = rule_obj.search(cr, uid, [('model_id','=',model_ids[0])])
|
||||
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
|
||||
|
||||
class crm_case(crm_base):
|
||||
""" A simple python class to be used for common functions
|
||||
Object that inherit from this class should inherit from mailgate.thread
|
||||
And need a stage_id field
|
||||
And object that inherit (orm inheritance) from a class the overwrite copy
|
||||
"""
|
||||
|
||||
def stage_find(self, cr, uid, section_id, domain=[], order='sequence'):
|
||||
domain = list(domain)
|
||||
if section_id:
|
||||
domain.append(('section_ids', '=', section_id))
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, domain, order=order)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def stage_set(self, cr, uid, ids, stage_id, context=None):
|
||||
value = {}
|
||||
if hasattr(self,'onchange_stage_id'):
|
||||
value = self.onchange_stage_id(cr, uid, ids, stage_id)['value']
|
||||
value['stage_id'] = stage_id
|
||||
return self.write(cr, uid, ids, value, context=context)
|
||||
|
||||
def stage_change(self, cr, uid, ids, op, order, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
seq = 0
|
||||
if case.stage_id:
|
||||
seq = case.stage_id.sequence
|
||||
section_id = None
|
||||
if case.section_id:
|
||||
section_id = case.section_id.id
|
||||
next_stage_id = self.stage_find(cr, uid, section_id, [('sequence',op,seq)],order)
|
||||
if next_stage_id:
|
||||
return self.stage_set(cr, uid, [case.id], next_stage_id, context=context)
|
||||
return False
|
||||
|
||||
def stage_next(self, cr, uid, ids, context=None):
|
||||
"""This function computes next stage for case from its current stage
|
||||
using available stage for that case type
|
||||
"""
|
||||
return self.stage_change(cr, uid, ids, '>','sequence', context)
|
||||
|
||||
def stage_previous(self, cr, uid, ids, context=None):
|
||||
"""This function computes previous stage for case from its current
|
||||
stage using available stage for that case type
|
||||
"""
|
||||
return self.stage_change(cr, uid, ids, '<', 'sequence desc', context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
"""Overrides orm copy method to avoid copying messages,
|
||||
as well as date_closed and date_open columns if they
|
||||
exist."""
|
||||
if default is None:
|
||||
default = {}
|
||||
|
||||
default.update({ 'message_ids': [], })
|
||||
if hasattr(self, '_columns'):
|
||||
if self._columns.get('date_closed'):
|
||||
default.update({ 'date_closed': False, })
|
||||
if self._columns.get('date_open'):
|
||||
default.update({ 'date_open': False })
|
||||
return super(crm_case, self).copy(cr, uid, id, default, context=context)
|
||||
|
||||
def case_escalate_send_note(self, cr, uid, ids, new_section=None, context=None):
|
||||
for id in ids:
|
||||
if new_section:
|
||||
msg = '%s has been <b>escalated</b> to <b>%s</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context), new_section.name)
|
||||
else:
|
||||
msg = '%s has been <b>escalated</b>.' % (self.case_get_note_msg_prefix(cr, uid, id, context=context))
|
||||
self.message_append_note(cr, uid, [id], 'System Notification', msg, context=context)
|
||||
return True
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return ''
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
"""Opens Case"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
for case in cases:
|
||||
data = {'state': 'open', 'active': True }
|
||||
if not case.user_id:
|
||||
data['user_id'] = uid
|
||||
self.write(cr, uid, [case.id], data)
|
||||
self.case_open_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'open')
|
||||
return True
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
"""Closes Case"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'done',
|
||||
'date_closed': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
})
|
||||
#
|
||||
# We use the cache of cases to keep the old case state
|
||||
#
|
||||
self.case_close_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'done')
|
||||
return True
|
||||
|
||||
def case_escalate(self, cr, uid, ids, context=None):
|
||||
"""Escalates case to parent level"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
for case in cases:
|
||||
data = {'active': True}
|
||||
if case.section_id.parent_id:
|
||||
data['section_id'] = case.section_id.parent_id.id
|
||||
if case.section_id.parent_id.change_responsible:
|
||||
if case.section_id.parent_id.user_id:
|
||||
data['user_id'] = case.section_id.parent_id.user_id.id
|
||||
else:
|
||||
raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
self.write(cr, uid, [case.id], data)
|
||||
case.case_escalate_send_note(case.section_id.parent_id)
|
||||
cases = self.browse(cr, uid, ids)
|
||||
self._action(cr, uid, cases, 'escalate')
|
||||
return True
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
"""Cancels Case"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'cancel',
|
||||
'active': True})
|
||||
self.case_cancel_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'cancel')
|
||||
return True
|
||||
|
||||
def case_pending(self, cr, uid, ids, context=None):
|
||||
"""Marks case as pending"""
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': 'pending', 'active': True})
|
||||
self.case_pending_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, 'pending')
|
||||
return True
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
"""Resets case as draft"""
|
||||
state = 'draft'
|
||||
cases = self.browse(cr, uid, ids)
|
||||
cases[0].state # to fill the browse record cache
|
||||
self.write(cr, uid, ids, {'state': state, 'active': True})
|
||||
self.case_reset_send_note(cr, uid, ids, context=context)
|
||||
self._action(cr, uid, cases, state)
|
||||
return True
|
||||
|
||||
def remind_partner(self, cr, uid, ids, context=None, attach=False):
|
||||
return self.remind_user(cr, uid, ids, context, attach,
|
||||
destination=False)
|
||||
|
||||
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
|
||||
mail_message = self.pool.get('mail.message')
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
if not destination and not case.email_from:
|
||||
return False
|
||||
if not case.user_id.user_email:
|
||||
return False
|
||||
if destination and case.section_id.user_id:
|
||||
case_email = case.section_id.user_id.user_email
|
||||
else:
|
||||
case_email = case.user_id.user_email
|
||||
|
||||
src = case_email
|
||||
dest = case.user_id.user_email or ""
|
||||
body = case.description or ""
|
||||
for message in case.message_ids:
|
||||
if message.email_from and message.body_text:
|
||||
body = message.body_text
|
||||
break
|
||||
|
||||
if not destination:
|
||||
src, dest = dest, case.email_from
|
||||
if body and case.user_id.signature:
|
||||
if body:
|
||||
body += '\n\n%s' % (case.user_id.signature)
|
||||
else:
|
||||
body = '\n\n%s' % (case.user_id.signature)
|
||||
|
||||
body = self.format_body(body)
|
||||
|
||||
attach_to_send = {}
|
||||
|
||||
if attach:
|
||||
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
|
||||
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
|
||||
attach_to_send = dict(map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send))
|
||||
|
||||
# Send an email
|
||||
subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
|
||||
mail_message.schedule_with_attach(cr, uid,
|
||||
src,
|
||||
[dest],
|
||||
subject,
|
||||
body,
|
||||
model=self._name,
|
||||
reply_to=case.section_id.reply_to,
|
||||
res_id=case.id,
|
||||
attachments=attach_to_send,
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
def _check(self, cr, uid, ids=False, context=None):
|
||||
"""Function called by the scheduler to process cases for date actions
|
||||
Only works on not done and cancelled cases
|
||||
"""
|
||||
cr.execute('select * from crm_case \
|
||||
where (date_action_last<%s or date_action_last is null) \
|
||||
and (date_action_next<=%s or date_action_next is null) \
|
||||
and state not in (\'cancel\',\'done\')',
|
||||
(time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
time.strftime('%Y-%m-%d %H:%M:%S')))
|
||||
|
||||
ids2 = map(lambda x: x[0], cr.fetchall() or [])
|
||||
cases = self.browse(cr, uid, ids2, context=context)
|
||||
return self._action(cr, uid, cases, False, context=context)
|
||||
|
||||
def format_body(self, body):
|
||||
return self.pool.get('base.action.rule').format_body(body)
|
||||
|
||||
def format_mail(self, obj, body):
|
||||
return self.pool.get('base.action.rule').format_mail(obj, body)
|
||||
|
||||
def message_thread_followers(self, cr, uid, ids, context=None):
|
||||
res = {}
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
l=[]
|
||||
if case.email_cc:
|
||||
l.append(case.email_cc)
|
||||
if case.user_id and case.user_id.user_email:
|
||||
l.append(case.user_id.user_email)
|
||||
res[case.id] = l
|
||||
return res
|
||||
|
||||
def _links_get(self, cr, uid, context=None):
|
||||
"""Gets links value for reference field"""
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,15 +19,15 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from datetime import datetime
|
||||
import crm
|
||||
import time
|
||||
from tools.translate import _
|
||||
from crm import crm_case
|
||||
import binascii
|
||||
import tools
|
||||
from base_status.base_stage import base_stage
|
||||
import crm
|
||||
from datetime import datetime
|
||||
from mail.mail_message import to_email
|
||||
from osv import fields, osv
|
||||
import time
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
CRM_LEAD_PENDING_STATES = (
|
||||
crm.AVAILABLE_STATES[2][0], # Cancelled
|
||||
|
@ -35,22 +35,68 @@ CRM_LEAD_PENDING_STATES = (
|
|||
crm.AVAILABLE_STATES[4][0], # Pending
|
||||
)
|
||||
|
||||
class crm_lead(crm_case, osv.osv):
|
||||
class crm_lead(base_stage, osv.osv):
|
||||
""" CRM Lead Case """
|
||||
_name = "crm.lead"
|
||||
_description = "Lead/Opportunity"
|
||||
_order = "priority,date_action,id desc"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread','res.partner']
|
||||
|
||||
def _get_default_section_id(self, cr, uid, context=None):
|
||||
""" Gives default section by checking if present in the context """
|
||||
return (self._resolve_section_id_from_context(cr, uid, context=context) or False)
|
||||
|
||||
def _get_default_stage_id(self, cr, uid, context=None):
|
||||
""" Gives default stage_id """
|
||||
section_id = self._get_default_section_id(cr, uid, context=context)
|
||||
return self.stage_find(cr, uid, [], section_id, [('state', '=', 'draft'), ('type', '=', 'both')], context=context)
|
||||
|
||||
def _resolve_section_id_from_context(self, cr, uid, context=None):
|
||||
""" Returns ID of section based on the value of 'section_id'
|
||||
context key, or None if it cannot be resolved to a single
|
||||
Sales Team.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if type(context.get('default_section_id')) in (int, long):
|
||||
return context.get('default_section_id')
|
||||
if isinstance(context.get('default_section_id'), basestring):
|
||||
section_name = context['default_section_id']
|
||||
section_ids = self.pool.get('crm.case.section').name_search(cr, uid, name=section_name, context=context)
|
||||
if len(section_ids) == 1:
|
||||
return int(section_ids[0][0])
|
||||
return None
|
||||
|
||||
def _resolve_type_from_context(self, cr, uid, context=None):
|
||||
""" Returns the type (lead or opportunity) from the type context
|
||||
key. Returns None if it cannot be resolved.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
return context.get('default_type')
|
||||
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
stage_obj = self.pool.get('crm.case.stage')
|
||||
order = stage_obj._order
|
||||
# lame hack to allow reverting search, should just work in the trivial case
|
||||
if read_group_order == 'stage_id desc':
|
||||
# lame hack to allow reverting search, should just work in the trivial case
|
||||
order = "%s desc" % order
|
||||
stage_ids = stage_obj._search(cr, uid, ['|', ('id','in',ids),('case_default','=',1)], order=order,
|
||||
access_rights_uid=access_rights_uid, context=context)
|
||||
# retrieve section_id from the context and write the domain
|
||||
# - ('id', 'in', 'ids'): add columns that should be present
|
||||
# - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
|
||||
# - OR ('section_ids', '=', section_id), ('fold', '=', False) if section_id: add section columns that are not folded
|
||||
search_domain = []
|
||||
section_id = self._resolve_section_id_from_context(cr, uid, context=context)
|
||||
if section_id:
|
||||
search_domain += ['|', '&', ('section_ids', '=', section_id), ('fold', '=', False)]
|
||||
search_domain += ['|', ('id', 'in', ids), '&', ('case_default', '=', True), ('fold', '=', False)]
|
||||
# retrieve type from the context (if set: choose 'type' or 'both')
|
||||
type = self._resolve_type_from_context(cr, uid, context=context)
|
||||
if type:
|
||||
search_domain += ['|', ('type', '=', type), ('type', '=', 'both')]
|
||||
# perform search
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
|
||||
|
@ -154,7 +200,6 @@ class crm_lead(crm_case, osv.osv):
|
|||
'email_cc': fields.text('Global CC', size=252 , help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
|
||||
'description': fields.text('Notes'),
|
||||
'write_date': fields.datetime('Update Date' , readonly=True),
|
||||
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Category', \
|
||||
domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]"),
|
||||
'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
|
||||
|
@ -167,7 +212,8 @@ class crm_lead(crm_case, osv.osv):
|
|||
'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"),
|
||||
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('section_ids', '=', section_id)]"),
|
||||
'stage_id': fields.many2one('crm.case.stage', 'Stage',
|
||||
domain="['&', '|', ('section_ids', '=', section_id), ('case_default', '=', True), '|', ('type', '=', type), ('type', '=', 'both')]"),
|
||||
'user_id': fields.many2one('res.users', 'Salesperson'),
|
||||
'referred': fields.char('Referred By', size=64),
|
||||
'date_open': fields.datetime('Opened', readonly=True),
|
||||
|
@ -175,12 +221,13 @@ class crm_lead(crm_case, osv.osv):
|
|||
multi='day_open', type="float", store=True),
|
||||
'day_close': fields.function(_compute_day, string='Days to Close', \
|
||||
multi='day_close', type="float", store=True),
|
||||
'state': fields.selection(crm.AVAILABLE_STATES, 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'In progress\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=crm.AVAILABLE_STATES, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
'subjects': fields.function(_get_email_subject, fnct_search=_history_search, string='Subject of Email', type='char', size=64),
|
||||
|
||||
# Only used for type opportunity
|
||||
|
@ -192,23 +239,21 @@ class crm_lead(crm_case, osv.osv):
|
|||
'date_deadline': fields.date('Expected Closing'),
|
||||
'date_action': fields.date('Next Action Date', select=True),
|
||||
'title_action': fields.char('Next Action', size=64),
|
||||
'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('section_ids', '=', section_id)]"),
|
||||
'color': fields.integer('Color Index'),
|
||||
'partner_address_name': fields.related('partner_id', 'name', type='char', string='Partner Contact Name', readonly=True),
|
||||
'partner_address_email': fields.related('partner_id', 'email', type='char', string='Partner Contact Email', readonly=True),
|
||||
'company_currency': fields.related('company_id', 'currency_id', 'symbol', type='char', string='Company Currency', readonly=True),
|
||||
'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True),
|
||||
'user_login': fields.related('user_id', 'login', type='char', string='User Login', readonly=True),
|
||||
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'user_id': crm_case._get_default_user,
|
||||
'email_from': crm_case._get_default_email,
|
||||
'state': lambda *a: 'draft',
|
||||
'type': lambda *a: 'lead',
|
||||
'section_id': crm_case._get_section,
|
||||
'active': 1,
|
||||
'type': 'lead',
|
||||
'user_id': lambda s, cr, uid, c: s._get_default_user(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
|
||||
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
|
||||
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'color': 0,
|
||||
|
@ -241,95 +286,104 @@ class crm_lead(crm_case, osv.osv):
|
|||
return {'value':{}}
|
||||
return {'value':{'probability': stage.probability}}
|
||||
|
||||
def stage_find_percent(self, cr, uid, percent, section_id):
|
||||
""" Return the first stage with a probability == percent
|
||||
def _check(self, cr, uid, ids=False, context=None):
|
||||
""" Override of the base.stage method.
|
||||
Function called by the scheduler to process cases for date actions
|
||||
Only works on not done and cancelled cases
|
||||
"""
|
||||
stage_pool = self.pool.get('crm.case.stage')
|
||||
if section_id :
|
||||
ids = stage_pool.search(cr, uid, [("probability", '=', percent), ("section_ids", 'in', [section_id])])
|
||||
else :
|
||||
ids = stage_pool.search(cr, uid, [("probability", '=', percent)])
|
||||
cr.execute('select * from crm_case \
|
||||
where (date_action_last<%s or date_action_last is null) \
|
||||
and (date_action_next<=%s or date_action_next is null) \
|
||||
and state not in (\'cancel\',\'done\')',
|
||||
(time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
time.strftime('%Y-%m-%d %H:%M:%S')))
|
||||
|
||||
if ids:
|
||||
return ids[0]
|
||||
ids2 = map(lambda x: x[0], cr.fetchall() or [])
|
||||
cases = self.browse(cr, uid, ids2, context=context)
|
||||
return self._action(cr, uid, cases, False, context=context)
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the lead:
|
||||
- type: stage type must be the same or 'both'
|
||||
- section_id: if set, stages must belong to this section or
|
||||
be a default stage; if not set, stages must be default
|
||||
stages
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
section_ids = []
|
||||
types = ['both']
|
||||
if section_id:
|
||||
section_ids.append(section_id)
|
||||
for lead in cases:
|
||||
if lead.section_id:
|
||||
section_ids.append(lead.section_id.id)
|
||||
if lead.type not in types:
|
||||
types.append(lead.type)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('section_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with cases types
|
||||
search_domain.append(('type', 'in', types))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def stage_find_lost(self, cr, uid, section_id):
|
||||
return self.stage_find_percent(cr, uid, 0.0, section_id)
|
||||
|
||||
def stage_find_won(self, cr, uid, section_id):
|
||||
return self.stage_find_percent(cr, uid, 100.0, section_id)
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
if lead.state == 'draft':
|
||||
value = {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
self.write(cr, uid, [lead.id], value)
|
||||
if lead.type == 'opportunity' and not lead.stage_id:
|
||||
stage_id = self.stage_find(cr, uid, lead.section_id.id or False, [('sequence','>',0)])
|
||||
if stage_id:
|
||||
self.stage_set(cr, uid, [lead.id], stage_id)
|
||||
res = super(crm_lead, self).case_open(cr, uid, ids, context)
|
||||
return res
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
res = super(crm_lead, self).case_close(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
return res
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
"""Overrides cancel for crm_case for setting probability
|
||||
"""
|
||||
res = super(crm_lead, self).case_cancel(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'probability' : 0.0})
|
||||
""" Overrides case_cancel from base_stage to set probability """
|
||||
res = super(crm_lead, self).case_cancel(cr, uid, ids, context=context)
|
||||
self.write(cr, uid, ids, {'probability' : 0.0}, context=context)
|
||||
return res
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
"""Overrides reset as draft in order to set the stage field as empty
|
||||
"""
|
||||
res = super(crm_lead, self).case_reset(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'stage_id': False, 'probability': 0.0})
|
||||
""" Overrides case_reset from base_stage to set probability """
|
||||
res = super(crm_lead, self).case_reset(cr, uid, ids, context=context)
|
||||
self.write(cr, uid, ids, {'probability': 0.0}, context=context)
|
||||
return res
|
||||
|
||||
def case_mark_lost(self, cr, uid, ids, context=None):
|
||||
"""Mark the case as lost: state = done and probability = 0%
|
||||
"""
|
||||
res = super(crm_lead, self).case_close(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'probability' : 0.0})
|
||||
""" Mark the case as lost: state=cancel and probability=0 """
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
stage_id = self.stage_find_lost(cr, uid, lead.section_id.id or False)
|
||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 0.0)], context=context)
|
||||
if stage_id:
|
||||
self.stage_set(cr, uid, [lead.id], stage_id)
|
||||
return res
|
||||
self.case_set(cr, uid, [lead.id], values_to_update={'probability': 0.0}, new_stage_id=stage_id, context=context)
|
||||
self.case_mark_lost_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_mark_won(self, cr, uid, ids, context=None):
|
||||
"""Mark the case as lost: state = done and probability = 0%
|
||||
"""
|
||||
res = super(crm_lead, self).case_close(cr, uid, ids, context=None)
|
||||
self.write(cr, uid, ids, {'probability' : 100.0})
|
||||
""" Mark the case as lost: state=done and probability=100 """
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
stage_id = self.stage_find_won(cr, uid, lead.section_id.id or False)
|
||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, [('probability', '=', 100.0)], context=context)
|
||||
if stage_id:
|
||||
self.stage_set(cr, uid, [lead.id], stage_id)
|
||||
self.case_mark_won_send_note(cr, uid, [lead.id], context=context)
|
||||
return res
|
||||
self.case_set(cr, uid, [lead.id], values_to_update={'probability': 100.0}, new_stage_id=stage_id, context=context)
|
||||
self.case_mark_won_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def set_priority(self, cr, uid, ids, priority):
|
||||
"""Set lead priority
|
||||
""" Set lead priority
|
||||
"""
|
||||
return self.write(cr, uid, ids, {'priority' : priority})
|
||||
|
||||
def set_high_priority(self, cr, uid, ids, context=None):
|
||||
"""Set lead priority to high
|
||||
""" Set lead priority to high
|
||||
"""
|
||||
return self.set_priority(cr, uid, ids, '1')
|
||||
|
||||
def set_normal_priority(self, cr, uid, ids, context=None):
|
||||
"""Set lead priority to normal
|
||||
""" Set lead priority to normal
|
||||
"""
|
||||
return self.set_priority(cr, uid, ids, '3')
|
||||
|
||||
|
||||
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
|
||||
# prepare opportunity data into dictionary for merging
|
||||
opportunities = self.browse(cr, uid, ids, context=context)
|
||||
|
@ -807,22 +861,12 @@ class crm_lead(crm_case, osv.osv):
|
|||
"You should better cancel it, instead of deleting it.") % lead.name)
|
||||
return super(crm_lead, self).unlink(cr, uid, ids, context)
|
||||
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
if 'date_closed' in vals:
|
||||
return super(crm_lead,self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
if vals.get('stage_id'):
|
||||
stage = self.pool.get('crm.case.stage').browse(cr, uid, vals['stage_id'], context=context)
|
||||
if vals.get('stage_id') and not vals.get('probability'):
|
||||
# change probability of lead(s) if required by stage
|
||||
if not vals.get('probability') and stage.on_change:
|
||||
stage = self.pool.get('crm.case.stage').browse(cr, uid, vals['stage_id'], context=context)
|
||||
if stage.on_change:
|
||||
vals['probability'] = stage.probability
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
message = _("Stage changed to <b>%s</b>.") % (stage.name)
|
||||
case.message_append_note(body=message)
|
||||
return super(crm_lead,self).write(cr, uid, ids, vals, context)
|
||||
|
||||
# ----------------------------------------
|
||||
|
@ -837,6 +881,11 @@ class crm_lead(crm_case, osv.osv):
|
|||
sub_ids.append(obj.user_id.id)
|
||||
return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
stage_name = self.pool.get('crm.case.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, lead, context=None):
|
||||
if isinstance(lead, (int, long)):
|
||||
lead = self.browse(cr, uid, [lead], context=context)[0]
|
||||
|
|
|
@ -3,47 +3,81 @@
|
|||
<data noupdate="1">
|
||||
|
||||
<!-- Crm stages -->
|
||||
<record model="crm.case.stage" id="stage_lead6">
|
||||
<field name="name">Lost</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="'0'" name="probability"/>
|
||||
<field eval="'0'" name="sequence"/>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead1">
|
||||
<field name="name">New</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field name="state">draft</field>
|
||||
<field eval="'10'" name="probability"/>
|
||||
<field eval="'11'" name="sequence"/>
|
||||
<field eval="'10'" name="sequence"/>
|
||||
<field name="type">both</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead2">
|
||||
<field name="name">Qualification</field>
|
||||
<field name="name">Opportunity</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field name="state">open</field>
|
||||
<field eval="'20'" name="probability"/>
|
||||
<field eval="'12'" name="sequence"/>
|
||||
<field eval="'11'" name="sequence"/>
|
||||
<field name="type">lead</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead3">
|
||||
<field name="name">Proposition</field>
|
||||
<field name="name">Qualification</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="'40'" name="probability"/>
|
||||
<field eval="'13'" name="sequence"/>
|
||||
<field name="state">open</field>
|
||||
<field eval="'20'" name="probability"/>
|
||||
<field eval="'12'" name="sequence"/>
|
||||
<field name="type">opportunity</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead4">
|
||||
<field name="name">Negotiation</field>
|
||||
<field name="name">Proposition</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="'60'" name="probability"/>
|
||||
<field eval="'14'" name="sequence"/>
|
||||
<field name="state">open</field>
|
||||
<field eval="'40'" name="probability"/>
|
||||
<field eval="'13'" name="sequence"/>
|
||||
<field name="type">opportunity</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead5">
|
||||
<field name="name">Negotiation</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field name="state">open</field>
|
||||
<field eval="'60'" name="probability"/>
|
||||
<field eval="'14'" name="sequence"/>
|
||||
<field name="type">opportunity</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead6">
|
||||
<field name="name">Won</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field name="state">done</field>
|
||||
<field eval="'100'" name="probability"/>
|
||||
<field eval="'15'" name="sequence"/>
|
||||
<field eval="1" name="on_change"/>
|
||||
<field name="type">opportunity</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead7">
|
||||
<field name="name">Dead</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="True" name="fold"/>
|
||||
<field name="state">cancel</field>
|
||||
<field eval="'0'" name="probability"/>
|
||||
<field eval="'16'" name="sequence"/>
|
||||
<field name="type">lead</field>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_lead8">
|
||||
<field name="name">Lost</field>
|
||||
<field eval="1" name="case_default"/>
|
||||
<field eval="True" name="fold"/>
|
||||
<field name="state">cancel</field>
|
||||
<field eval="'0'" name="probability"/>
|
||||
<field eval="'17'" name="sequence"/>
|
||||
<field name="type">opportunity</field>
|
||||
</record>
|
||||
|
||||
<record model="crm.case.section" id="section_sales_department">
|
||||
<field name="name">Sales Department</field>
|
||||
<field name="code">Sales</field>
|
||||
<field name="stage_ids" eval="[(4, ref('stage_lead1')), (4, ref('stage_lead2')), (4, ref('stage_lead3')), (4, ref('stage_lead4')), (4, ref('stage_lead5')), (4, ref('stage_lead6'))]"/>
|
||||
<field name="stage_ids" eval="[ (4, ref('stage_lead1')), (4, ref('stage_lead2')),
|
||||
(4, ref('stage_lead3')), (4, ref('stage_lead4')),
|
||||
(4, ref('stage_lead5')), (4, ref('stage_lead6')),
|
||||
(4, ref('stage_lead7')), (4, ref('stage_lead8'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Crm campain -->
|
||||
|
|
|
@ -8,14 +8,13 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'The Oil Company'" name="partner_name"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_marketing_department"/>
|
||||
<field eval="'Luc Latour'" name="contact_name"/>
|
||||
<field name="title" ref="base.res_partner_title_sir"/>
|
||||
<field eval="'Training Manager'" name="function"/>
|
||||
<field eval="'Paris'" name="city"/>
|
||||
<field name="country_id" ref="base.fr"/>
|
||||
<field eval="'luc.latour@oilcompany.fr'" name="email_from"/>
|
||||
<field eval="'Training Manager'" name="function"/>
|
||||
<field eval="'Paris'" name="city"/>
|
||||
<field name="country_id" ref="base.fr"/>
|
||||
<field eval="'luc.latour@oilcompany.fr'" name="email_from"/>
|
||||
<field eval="'0033 621 782-0636'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
|
@ -29,18 +28,17 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'Le Club SARL'" name="partner_name"/>
|
||||
<field eval="'Marc Dufour'" name="contact_name"/>
|
||||
<field eval="'Marc Dufour'" name="contact_name"/>
|
||||
<field name="title" ref="base.res_partner_title_sir"/>
|
||||
<field eval="'Purchase Manager'" name="function"/>
|
||||
<field eval="'Bordeaux'" name="city"/>
|
||||
<field name="country_id" ref="base.fr"/>
|
||||
<field eval="'md@leclub.fr'" name="email_from"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'Purchase Manager'" name="function"/>
|
||||
<field eval="'Bordeaux'" name="city"/>
|
||||
<field name="country_id" ref="base.fr"/>
|
||||
<field eval="'md@leclub.fr'" name="email_from"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'(392) 895-7917'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Interest in Your New Product'" name="name"/>
|
||||
<field eval="'(956) 293-2595'" name="phone"/>
|
||||
</record>
|
||||
|
@ -50,15 +48,14 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'The Kompany'" name="partner_name"/>
|
||||
<field eval="'John Miller'" name="contact_name"/>
|
||||
<field eval="'New-York'" name="city"/>
|
||||
<field name="country_id" ref="base.us"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'John Miller'" name="contact_name"/>
|
||||
<field eval="'New-York'" name="city"/>
|
||||
<field name="country_id" ref="base.us"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'(820) 167-3208'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor4"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Need Info about Web Design'" name="name"/>
|
||||
<field eval="'(079) 681-2139'" name="phone"/>
|
||||
<field eval="'contact@thkompany.com'" name="email_from"/>
|
||||
|
@ -68,10 +65,9 @@
|
|||
<field eval="'3'" name="priority"/>
|
||||
<field name="type">lead</field>
|
||||
<field eval="'The Gas Company'" name="partner_name"/>
|
||||
<field eval="'Henry Mc Coy'" name="contact_name"/>
|
||||
<field eval="'London'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'Henry Mc Coy'" name="contact_name"/>
|
||||
<field eval="'London'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'(077) 582-4035'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
|
@ -87,16 +83,15 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'Stonage IT'" name="partner_name"/>
|
||||
<field eval="'Carrie Helle'" name="contact_name"/>
|
||||
<field eval="'Purchase Manager'" name="function"/>
|
||||
<field eval="'Bruxelles'" name="city"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'Carrie Helle'" name="contact_name"/>
|
||||
<field eval="'Purchase Manager'" name="function"/>
|
||||
<field eval="'Bruxelles'" name="city"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
<field name="section_id" ref="crm.section_sales_marketing_department"/>
|
||||
<field eval="'(333) 715-1450'" name="mobile"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Need a Quotation for PC1'" name="name"/>
|
||||
<field eval="'(855) 924-4364'" name="phone"/>
|
||||
<field eval="'helle@stonageit.be'" name="email_from"/>
|
||||
|
@ -110,15 +105,14 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'Opensides'" name="partner_name"/>
|
||||
<field eval="'Tina Pinero'" name="contact_name"/>
|
||||
<field eval="'Consultant'" name="function"/>
|
||||
<field eval="'Roma'" name="city"/>
|
||||
<field name="country_id" ref="base.it"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'Tina Pinero'" name="contact_name"/>
|
||||
<field eval="'Consultant'" name="function"/>
|
||||
<field eval="'Roma'" name="city"/>
|
||||
<field name="country_id" ref="base.it"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'(468) 017-2684'" name="mobile"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor8"/>
|
||||
<field name="stage_id" ref="crm.stage_lead6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Need Info about your Services'" name="name"/>
|
||||
<field eval="'(373) 907-1009'" name="phone"/>
|
||||
<field eval="'info@opensides.be'" name="email_from"/>
|
||||
|
@ -130,15 +124,14 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'Gardner Group'" name="partner_name"/>
|
||||
<field eval="'Wendi Baltz'" name="contact_name"/>
|
||||
<field eval="'Journalist'" name="function"/>
|
||||
<field eval="'Kiev'" name="city"/>
|
||||
<field name="country_id" ref="base.ua"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="'Wendi Baltz'" name="contact_name"/>
|
||||
<field eval="'Journalist'" name="function"/>
|
||||
<field eval="'Kiev'" name="city"/>
|
||||
<field name="country_id" ref="base.ua"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="'(463) 014-1208'" name="mobile"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor4"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Info about Your Company ?'" name="name"/>
|
||||
<field eval="'(282) 603-7489'" name="phone"/>
|
||||
</record>
|
||||
|
@ -149,17 +142,16 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'Survey'" name="name"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Survey Expert'" name="partner_name"/>
|
||||
<field eval="'John Smith'" name="contact_name"/>
|
||||
<field eval="'Sales'" name="function"/>
|
||||
<field eval="'Cambridge'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field eval="'John Smith'" name="contact_name"/>
|
||||
<field eval="'Sales'" name="function"/>
|
||||
<field eval="'Cambridge'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field eval="'smith_john@gmail.com'" name="email_from"/>
|
||||
<field eval="'(282) 596-8584'" name="phone"/>
|
||||
<field eval="'(282) 596-8584'" name="phone"/>
|
||||
</record>
|
||||
<record id="crm_case_business_card0" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
|
@ -168,17 +160,16 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'Partnership'" name="name"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor5"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Marketing Business'" name="partner_name"/>
|
||||
<field eval="'Laure Smith'" name="contact_name"/>
|
||||
<field eval="'Sales'" name="function"/>
|
||||
<field eval="'Oxford'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field eval="'Laure Smith'" name="contact_name"/>
|
||||
<field eval="'Sales'" name="function"/>
|
||||
<field eval="'Oxford'" name="city"/>
|
||||
<field name="country_id" ref="base.uk"/>
|
||||
<field eval="'l.smith@marketing-business.com'" name="email_from"/>
|
||||
<field eval="'(252) 578-7894'" name="phone"/>
|
||||
<field eval="'(252) 578-7894'" name="phone"/>
|
||||
</record>
|
||||
<record id="crm_case_imported_contact0" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
|
@ -186,9 +177,8 @@
|
|||
<field eval="'2'" name="priority"/>
|
||||
<field name="type">lead</field>
|
||||
<field eval="'Info'" name="name"/>
|
||||
<field eval="'cancel'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Business Group'" name="partner_name"/>
|
||||
</record>
|
||||
<record id="crm_case_employee0" model="crm.lead">
|
||||
|
@ -198,12 +188,11 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'Need Info about Onsite Intervention'" name="name"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Agrolait'" name="partner_name"/>
|
||||
<field eval="'Sylvie Lelitre'" name="contact_name"/>
|
||||
<field eval="'Sylvie Lelitre'" name="contact_name"/>
|
||||
</record>
|
||||
<record id="crm_case_company_partnership0" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
|
@ -212,28 +201,15 @@
|
|||
<field name="type">lead</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'Need Quotation for 100 PC and 100 Keyboards'" name="name"/>
|
||||
<field eval="'done'" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Centrale d\'achats 1'" name="partner_name"/>
|
||||
</record>
|
||||
|
||||
<!-- Call Function to Open the leads-->
|
||||
<function model="crm.lead" name="case_open"
|
||||
eval="[ref('crm_case_electonicgoodsdealer0'), ref('crm_case_company_partnership0'), ref('crm_case_webvisitor0'), ref('crm_case_business_card0'), ref('crm.crm_case_employee0')], {'install_mode': True}"
|
||||
/>
|
||||
<!-- Call Function to mark the lead as Pending-->
|
||||
<function model="crm.lead" name="case_pending"
|
||||
eval="[ref('crm_case_itdeveloper0')], {'install_mode': True}"
|
||||
/>
|
||||
<!-- Call Function to Close the leads-->
|
||||
<function model="crm.lead" name="case_close"
|
||||
eval="[ref('crm_case_vpoperations0'), ref('crm_case_developingwebapplications0'), ref('crm_case_webvisitor0')], {'install_mode': True}"
|
||||
/>
|
||||
<!-- Call Function to Cancel the leads-->
|
||||
<!-- Call Function to Cancel the leads (set as Dead) -->
|
||||
<function model="crm.lead" name="case_cancel"
|
||||
eval="[ref('crm_case_mgroperations0'), ref('crm_case_imported_contact0')], {'install_mode': True}"
|
||||
eval="[ref('crm_case_company_partnership0'), ref('crm_case_vpoperations0'), ref('crm_case_developingwebapplications0'), ref('crm_case_webvisitor0')], {'install_mode': True}"
|
||||
/>
|
||||
|
||||
<!-- Demo Opportunities -->
|
||||
|
@ -245,11 +221,10 @@
|
|||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="'150000'" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
<field eval="'Plan to buy 200 PC2'" name="name"/>
|
||||
<field eval="'Conf call with purchase manager'" name="title_action"/>
|
||||
</record>
|
||||
|
@ -260,12 +235,11 @@
|
|||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="45000.0" name="planned_revenue"/>
|
||||
<field eval="35" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="'Pricing Information of Onsite Intervention'" name="name"/>
|
||||
<field eval="'Send price list regarding our interventions'" name="title_action"/>
|
||||
<field eval="time.strftime('%Y-%m-03')" name="date_action"/>
|
||||
|
@ -283,12 +257,11 @@
|
|||
<field name="partner_id" ref="base.res_partner_lucievonck0"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field eval="30000.0" name="planned_revenue"/>
|
||||
<field eval="30" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="'Interest in your Kitchen Design Project'" name="name"/>
|
||||
<field eval="'Send Catalogue by E-Mail'" name="title_action"/>
|
||||
<field eval="time.strftime('%Y-01-10')" name="date_action"/>
|
||||
|
@ -299,19 +272,18 @@
|
|||
<field eval="1367" name="zip"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
</record>
|
||||
<record id="crm_case_unifliege" model="crm.lead">
|
||||
<record id="crm_case_unifliege" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="type_id" ref="crm.type_lead2"/>
|
||||
<field name="partner_id" ref="base.res_partner_accent"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="2500.0" name="planned_revenue"/>
|
||||
<field eval="25" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="'Plan train our students on your product'" name="name"/>
|
||||
<field eval="'Call to define real needs about training'" name="title_action"/>
|
||||
<field eval="time.strftime('%Y-%m-04')" name="date_action"/>
|
||||
|
@ -323,19 +295,18 @@
|
|||
<field eval="75016" name="zip"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
</record>
|
||||
<record id="crm_case_bankwealthy2" model="crm.lead">
|
||||
<record id="crm_case_bankwealthy2" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="type_id" ref="crm.type_lead2"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="462.0" name="planned_revenue"/>
|
||||
<field eval="40" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="'Plan to buy 66 keyboards and 66 mouses'" name="name"/>
|
||||
<field eval="'Propose the kit keyboard+mouse'" name="title_action"/>
|
||||
<field eval="time.strftime('%Y-04-12')" name="date_action"/>
|
||||
|
@ -354,12 +325,11 @@
|
|||
<field name="partner_id" ref="base.res_partner_8"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'done'" name="state"/>
|
||||
<field eval="55000.0" name="planned_revenue"/>
|
||||
<field eval="90" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor7"/>
|
||||
<field name="stage_id" ref="crm.stage_lead5"/>
|
||||
<field name="stage_id" ref="crm.stage_lead6"/>
|
||||
<field eval="'Need 20 Days of Consultancy'" name="name"/>
|
||||
<field eval="time.strftime('%Y-%m-%d')" name="date_deadline"/>
|
||||
<field eval="'info@mycompany.net'" name="email_from"/>
|
||||
|
@ -372,11 +342,10 @@
|
|||
<field name="partner_id" ref="base.res_partner_duboissprl0"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="45000.0" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor5"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
<field name="stage_id" ref="crm.stage_lead5"/>
|
||||
<field eval="'Need new design for my website'" name="name"/>
|
||||
<field eval="time.strftime('%Y-05-01')" name="date_action"/>
|
||||
<field eval="time.strftime('%Y-06-30')" name="date_deadline"/>
|
||||
|
@ -395,40 +364,37 @@
|
|||
<field name="partner_id" ref="base.res_partner_maxtor"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'done'" name="state"/>
|
||||
<field eval="42000.0" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead8"/>
|
||||
<field eval="'Want to subscribe to your online solution'" name="name"/>
|
||||
</record>
|
||||
<record id="crm_case_dirtminingltdunits0" model="crm.lead">
|
||||
<record id="crm_case_dirtminingltdunits0" model="crm.lead">
|
||||
<field eval="30" name="probability"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="partner_id" ref="base.res_partner_tinyatwork"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'done'" name="state"/>
|
||||
<field eval="25000.0" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead6"/>
|
||||
<field name="stage_id" ref="crm.stage_lead8"/>
|
||||
<field eval="'Interest in your Partnership Contract'" name="name"/>
|
||||
</record>
|
||||
<record id="crm_case_dirtminingltdunits10" model="crm.lead">
|
||||
<record id="crm_case_dirtminingltdunits10" model="crm.lead">
|
||||
<field eval="30" name="probability"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="partner_id" ref="base.res_partner_desertic_hispafuentes"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="5000" name="planned_revenue"/>
|
||||
<field eval="30" name="probability"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead2"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="'Plan to attend a training'" name="name"/>
|
||||
<field eval="time.strftime('%Y-04-10')" name="date_action"/>
|
||||
<field eval="time.strftime('%Y-06-12')" name="date_deadline"/>
|
||||
|
@ -439,7 +405,7 @@
|
|||
<field eval="77420" name="zip"/>
|
||||
<field name="country_id" ref="base.fr"/>
|
||||
</record>
|
||||
<record id="crm_case_construstazunits0" model="crm.lead">
|
||||
<record id="crm_case_construstazunits0" model="crm.lead">
|
||||
<field eval="60" name="probability"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
|
@ -447,11 +413,10 @@
|
|||
<field name="partner_id" ref="base.res_partner_thymbra"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="'150000'" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
<field eval="'Need customize the solution'" name="name"/>
|
||||
<field eval="'Conf call with technical service'" name="title_action"/>
|
||||
<field name="partner_name">Thymbra</field>
|
||||
|
@ -461,7 +426,7 @@
|
|||
<field eval="1659" name="zip"/>
|
||||
<field name="country_id" ref="base.ar"/>
|
||||
</record>
|
||||
<record id="crm_case_ericdubois4" model="crm.lead">
|
||||
<record id="crm_case_ericdubois4" model="crm.lead">
|
||||
<field eval="65" name="probability"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
|
@ -469,11 +434,10 @@
|
|||
<field name="partner_id" ref="base.res_partner_ericdubois0"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'open'" name="state"/>
|
||||
<field eval="'1200'" name="planned_revenue"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor1"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field name="stage_id" ref="crm.stage_lead4"/>
|
||||
<field eval="'Interest in your customizable PC'" name="name"/>
|
||||
<field eval="time.strftime('%Y-08-05')" name="date_action"/>
|
||||
<field eval="time.strftime('%Y-10-10')" name="date_deadline"/>
|
||||
|
@ -484,26 +448,24 @@
|
|||
<field eval="7000" name="zip"/>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
</record>
|
||||
<record id="crm_case_fabiendupont" model="crm.lead">
|
||||
<record id="crm_case_fabiendupont" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="type_id" ref="crm.type_lead1"/>
|
||||
<field name="partner_id" ref="base.res_partner_fabiendupont0"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor4"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Need more info about the onsite intervention'" name="name"/>
|
||||
</record>
|
||||
<record id="crm_case_shelvehouse" model="crm.lead">
|
||||
<record id="crm_case_shelvehouse" model="crm.lead">
|
||||
<field eval="1" name="active"/>
|
||||
<field name="type">opportunity</field>
|
||||
<field name="type_id" ref="crm.type_lead1"/>
|
||||
<field name="partner_id" ref="base.res_partner_theshelvehouse0"/>
|
||||
<field eval="'3'" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval="'draft'" name="state"/>
|
||||
<field name="categ_id" ref="crm.categ_oppor4"/>
|
||||
<field name="stage_id" ref="crm.stage_lead1"/>
|
||||
<field eval="'Need more info about your pc2'" name="name"/>
|
||||
|
|
|
@ -1,35 +1,41 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data>
|
||||
|
||||
<!-- Stage Search view -->
|
||||
<record id="crm_lead_stage_search" model="ir.ui.view">
|
||||
<field name="name">Stage - Search</field>
|
||||
<field name="model">crm.case.stage</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Stage Search">
|
||||
<field name="name"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<!--
|
||||
CRM CASE STAGE
|
||||
-->
|
||||
|
||||
<!--Lead Stage Form view -->
|
||||
<record id="crm_lead_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.crm_case_stage_tree"/>
|
||||
<field name="help">Add specific stages to leads and opportunities allowing your sales to better organise their sales pipeline. Stages will allow them to easily track how a specific lead or opportunity is positioned in the sales cycle.</field>
|
||||
</record>
|
||||
<!-- Stage Search view -->
|
||||
<record id="crm_lead_stage_search" model="ir.ui.view">
|
||||
<field name="name">Stage - Search</field>
|
||||
<field name="model">crm.case.stage</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Stage Search">
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
<field name="type"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act" name="Stages"
|
||||
groups="base.group_no_one" sequence="0"
|
||||
parent="base.menu_crm_config_lead" />
|
||||
<!-- Stage Form view -->
|
||||
<record id="crm_lead_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.crm_case_stage_tree"/>
|
||||
<field name="help">Add specific stages to leads and opportunities allowing your sales to better organise their sales pipeline. Stages will allow them to easily track how a specific lead or opportunity is positioned in the sales cycle.</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act" name="Stages" sequence="0" parent="base.menu_crm_config_lead" />
|
||||
|
||||
<!-- Lead/Opportunity Categories Action -->
|
||||
<!--
|
||||
LEADS/OPPORTUNITIES CATEGORIES
|
||||
-->
|
||||
|
||||
<!-- Categories Form View -->
|
||||
<record id="crm_lead_categ_action" model="ir.actions.act_window">
|
||||
<field name="name">Categories</field>
|
||||
<field name="res_model">crm.case.categ</field>
|
||||
|
@ -44,6 +50,9 @@
|
|||
id="menu_crm_lead_categ" name="Categories"
|
||||
parent="base.menu_crm_config_lead" sequence="1" groups="base.group_no_one"/>
|
||||
|
||||
<!--
|
||||
LEADS
|
||||
-->
|
||||
|
||||
<!-- CRM Lead Form View -->
|
||||
<record model="ir.ui.view" id="crm_case_form_view_leads">
|
||||
|
@ -53,14 +62,17 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Leads Form" layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" />
|
||||
<button name="case_mark_lost" string="Close" states="open,pending" type="object" />
|
||||
<button name="case_pending" string="Pending" states="open" type="object" />
|
||||
<button name="case_escalate" string="Escalate" states="open,pending" type="object" />
|
||||
<button name="case_reset" string="Reset to Draft" states="done,cancel" type="object" />
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" />
|
||||
<button name="%(crm.action_crm_lead2opportunity_partner)d" string="Convert to Opportunity" type="action"
|
||||
states="draft,open,pending" help="Convert to Opportunity"/>
|
||||
<button name="case_escalate" string="Escalate" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="case_reset" string="Reset" type="object"
|
||||
states="cancel"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"
|
||||
on_change="onchange_stage_id(stage_id)"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -71,24 +83,9 @@
|
|||
<field name="categ_id"
|
||||
widget="selection"
|
||||
domain="[('object_id.model','=','crm.lead')]"/>
|
||||
<button
|
||||
name="%(crm.action_crm_lead2opportunity_partner)d"
|
||||
string="Convert to Opportunity"
|
||||
help="Convert to Opportunity" icon="gtk-go-forward"
|
||||
type="action"
|
||||
/>
|
||||
<newline />
|
||||
<field name="user_id" />
|
||||
<field name="section_id" widget="selection" />
|
||||
<field name="stage_id" domain="section_id and [('section_ids', '=', section_id)] or []" />
|
||||
<group col="2" colspan="1">
|
||||
<button name="stage_previous" string=""
|
||||
states="open,pending,draft" type="object"
|
||||
icon="gtk-go-back" context="{'stage_type': 'lead'}" />
|
||||
<button name="stage_next" string=""
|
||||
states="open,pending,draft" type="object"
|
||||
icon="gtk-go-forward" context="{'stage_type': 'lead'}" />
|
||||
</group>
|
||||
<field name="type" invisible="1"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
|
@ -142,6 +139,7 @@
|
|||
<field name="type_id" select="1" widget="selection"/>
|
||||
<field name="channel_id" select="1" widget="selection"/>
|
||||
<field name="referred"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Mailings" colspan="2" col="2"/>
|
||||
|
@ -157,76 +155,53 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
<!-- CRM Lead Tree View -->
|
||||
<!-- CRM Lead Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_leads">
|
||||
<field name="name">Leads</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leads" fonts="bold:needaction_pending==True" colors="blue:state=='pending';grey:state in ('cancel', 'done')">
|
||||
<field name="needaction_pending" invisible="1"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date" groups="base.group_no_one"/>
|
||||
<field name="name" string="Subject"/>
|
||||
<field name="contact_name"/>
|
||||
<field name="country_id" invisible="context.get('invisible_country', True)" />
|
||||
<field name="email_from"/>
|
||||
<field name="phone"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="section_id" invisible="context.get('invisible_section', True)" />
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="referred" invisible="1"/>
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_leads">
|
||||
<field name="name">Leads</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leads" fonts="bold:needaction_pending==True" colors="blue:state=='pending';grey:state in ('cancel', 'done')">
|
||||
<field name="needaction_pending" invisible="1"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date" groups="base.group_no_one"/>
|
||||
<field name="name" string="Subject"/>
|
||||
<field name="contact_name"/>
|
||||
<field name="country_id" invisible="context.get('invisible_country', True)" />
|
||||
<field name="email_from"/>
|
||||
<field name="phone"/>
|
||||
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="referred" invisible="1"/>
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next Stage"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="section_id" invisible="context.get('invisible_section', True)" />
|
||||
<field name="user_id" />
|
||||
<field name="state" />
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_close" string="Close"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button name="%(crm.action_crm_lead2opportunity_partner)d"
|
||||
string="Convert to Opportunity"
|
||||
states="draft,open,pending" icon="gtk-index"
|
||||
type="action" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-go-up" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Lead Calendar View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_calendar_view_leads">
|
||||
<field name="name">CRM - Leads Calendar</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">calendar</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Leads Generation"
|
||||
date_start="date_action" color="user_id">
|
||||
<field name="name" />
|
||||
<field name="partner_name" />
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
<!-- CRM Lead Calendar View -->
|
||||
<record model="ir.ui.view" id="crm_case_calendar_view_leads">
|
||||
<field name="name">CRM - Leads Calendar</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">calendar</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Leads Generation"
|
||||
date_start="date_action" color="user_id">
|
||||
<field name="name" />
|
||||
<field name="partner_name" />
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- CRM Lead Kanban View -->
|
||||
<record model="ir.ui.view" id="crm_case_kanban_view_leads">
|
||||
|
@ -235,7 +210,7 @@
|
|||
<field name="type">kanban</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="stage_id">
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="color"/>
|
||||
<field name="priority"/>
|
||||
<field name="planned_revenue" sum="Expected Revenues"/>
|
||||
|
@ -316,7 +291,6 @@
|
|||
</record>
|
||||
|
||||
<!-- CRM Lead Search View -->
|
||||
|
||||
<record id="view_crm_case_leads_filter" model="ir.ui.view">
|
||||
<field name="name">CRM - Leads Search</field>
|
||||
<field name="model">crm.lead</field>
|
||||
|
@ -391,6 +365,10 @@
|
|||
</record>
|
||||
|
||||
|
||||
<!--
|
||||
OPPORTUNITY
|
||||
-->
|
||||
|
||||
<!-- Opportunities Form View -->
|
||||
<record model="ir.ui.view" id="crm_case_form_view_oppor">
|
||||
<field name="name">Opportunities</field>
|
||||
|
@ -400,15 +378,23 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Opportunities" layout="manual">
|
||||
<div class="oe_form_topbar oe_form_topbar_hifirst">
|
||||
<button name="case_mark_won" string="Mark Won" states="open,pending" type="object" />
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" />
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object" />
|
||||
<button name="case_escalate" string="Escalate" states="open,pending" type="object" />
|
||||
<button name="case_mark_lost" string="Mark Lost" states="open,pending" type="object" />
|
||||
<button name="case_reset" string="Reset to Draft" states="done,cancel" type="object" />
|
||||
<button name="case_cancel" string="Cancel" states="draft" type="object" />
|
||||
<button name="case_open" string="Open" type="object"
|
||||
states="draft"/>
|
||||
<button name="case_mark_won" string="Mark Won" type="object"
|
||||
states="draft,open"/>
|
||||
<button name="case_mark_lost" string="Mark Lost" type="object"
|
||||
states="draft,open"/>
|
||||
<button name="case_reset" string="Reset to Draft" type="object"
|
||||
states="cancel"/>
|
||||
<button name="case_escalate" string="Escalate" type="object"
|
||||
states="open"/>
|
||||
<button name="stage_previous" string="Previous" type="object"
|
||||
states="open" icon="gtk-go-back" context="{'stage_type': 'opportunity'}"/>
|
||||
<button name="stage_next" string="Next" type="object"
|
||||
states="open" icon="gtk-go-forward" context="{'stage_type': 'opportunity'}"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"
|
||||
on_change="onchange_stage_id(stage_id)"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -461,20 +447,8 @@
|
|||
<field name="categ_id" select="1"
|
||||
string="Category" widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]" />
|
||||
|
||||
<label string="Stage" for="stage_id" align="1.0"/>
|
||||
<group colspan="1" col="3">
|
||||
<field name="stage_id" nolabel="1"
|
||||
on_change="onchange_stage_id(stage_id)"
|
||||
domain="section_id and [('section_ids', '=', section_id)] or []" width="60%%"/>
|
||||
<button name="stage_previous"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-go-back" string="" context="{'stage_type': 'opportunity'}"/>
|
||||
<button name="stage_next" states="draft,open,pending"
|
||||
type="object" icon="gtk-go-forward" string="" context="{'stage_type': 'opportunity'}"/>
|
||||
</group>
|
||||
|
||||
<field name="priority" string="Priority"/>
|
||||
<field name="state"/>
|
||||
<field name="priority"/>
|
||||
</group>
|
||||
|
||||
<separator colspan="4" string="Details"/>
|
||||
|
@ -528,47 +502,41 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_oppor">
|
||||
<field name="name">Opportunities Tree</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities" fonts="bold:needaction_pending==True" colors="blue:state=='pending' and not(date_deadline and (date_deadline < current_date));gray:state in ('cancel', 'done');red:date_deadline and (date_deadline < current_date)">
|
||||
<field name="needaction_pending" invisible="1"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date" groups="base.group_no_one"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="country_id" invisible="context.get('invisible_country', True)" />
|
||||
<field name="date_action"/>
|
||||
<field name="title_action" />
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous Stage" states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next Stage" states="open,pending" type="object" icon="gtk-go-forward" />
|
||||
<field name="planned_revenue" sum="Expected Revenues"/>
|
||||
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
|
||||
<field name="section_id" invisible="context.get('invisible_section', True)" />
|
||||
<field name="user_id"/>
|
||||
<field name="priority" invisible="1"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending" states="open,draft" type="object" icon="gtk-media-pause" />
|
||||
<button name="case_mark_lost" string="Lost" states="open,pending" type="object" icon="gtk-cancel" />
|
||||
<button name="case_mark_won" string="Won" states="open,pending" type="object" icon="gtk-apply" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Opportunities Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_oppor">
|
||||
<field name="name">Opportunities Tree</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities" fonts="bold:needaction_pending==True" colors="blue:state=='pending' and not(date_deadline and (date_deadline < current_date));gray:state in ('cancel', 'done');red:date_deadline and (date_deadline < current_date)">
|
||||
<field name="needaction_pending" invisible="1"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date" groups="base.group_no_one"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="country_id" invisible="context.get('invisible_country', True)" />
|
||||
<field name="date_action"/>
|
||||
<field name="title_action" />
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="planned_revenue" sum="Expected Revenues"/>
|
||||
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
|
||||
<field name="section_id" invisible="context.get('invisible_section', True)" />
|
||||
<field name="user_id"/>
|
||||
<field name="priority" invisible="1"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Opportunities Search View -->
|
||||
|
@ -599,8 +567,7 @@
|
|||
help="Unassigned Opportunities" />
|
||||
</field>
|
||||
<field name="section_id"
|
||||
context="{'invisible_section': False}"
|
||||
widget="selection">
|
||||
context="{'invisible_section': False, 'default_section_id': self}">
|
||||
<filter icon="terp-personal+"
|
||||
domain="['|', ('section_id.user_id','=',uid), ('section_id.member_ids', 'in', [uid])]"
|
||||
context="{'invisible_section': False}"
|
||||
|
@ -630,19 +597,19 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- crm.lead Opportunities Graph View -->
|
||||
<record model="ir.ui.view" id="crm_case_graph_view_opportunity">
|
||||
<field name="name">CRM - Opportunity Graph</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Opportunity by Categories" type="bar" orientation="horizontal">
|
||||
<field name="categ_id"/>
|
||||
<field name="planned_revenue" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
<!-- crm.lead Opportunities Graph View -->
|
||||
<record model="ir.ui.view" id="crm_case_graph_view_opportunity">
|
||||
<field name="name">CRM - Opportunity Graph</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Opportunity by Categories" type="bar" orientation="horizontal">
|
||||
<field name="categ_id"/>
|
||||
<field name="planned_revenue" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -20,43 +20,35 @@
|
|||
##############################################################################
|
||||
|
||||
from base_calendar import base_calendar
|
||||
from crm import crm_base, crm_case
|
||||
from base_status.base_state import base_state
|
||||
from base_status.base_stage import base_stage
|
||||
import logging
|
||||
from osv import fields, osv
|
||||
import tools
|
||||
from tools.translate import _
|
||||
import logging
|
||||
|
||||
class crm_lead(crm_case, osv.osv):
|
||||
""" CRM Leads """
|
||||
_name = 'crm.lead'
|
||||
crm_lead()
|
||||
|
||||
class crm_phonecall(crm_case, osv.osv):
|
||||
""" CRM Phonecall """
|
||||
_name = 'crm.phonecall'
|
||||
crm_phonecall()
|
||||
|
||||
|
||||
class crm_meeting(crm_base, osv.osv):
|
||||
""" CRM Meeting Cases """
|
||||
class crm_lead(base_stage, osv.osv):
|
||||
""" CRM Leads """
|
||||
_name = 'crm.lead'
|
||||
|
||||
class crm_meeting(base_state, osv.Model):
|
||||
""" Model for CRM meetings """
|
||||
_name = 'crm.meeting'
|
||||
_description = "Meeting"
|
||||
_order = "id desc"
|
||||
_inherit = ["calendar.event", 'ir.needaction_mixin', "mail.thread"]
|
||||
_columns = {
|
||||
# From crm.case
|
||||
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
|
||||
# base_state required fields
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team', states={'done': [('readonly', True)]}, \
|
||||
select=True, help='Sales team to which Case belongs to.'),
|
||||
'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
|
||||
'id': fields.integer('ID', readonly=True),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
'write_date': fields.datetime('Write Date' , readonly=True),
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
# Meeting fields
|
||||
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Meeting Type', \
|
||||
domain="[('object_id.model', '=', 'crm.meeting')]", \
|
||||
),
|
||||
|
@ -66,12 +58,11 @@ class crm_meeting(crm_base, osv.osv):
|
|||
'event_id', 'attendee_id', 'Attendees', states={'done': [('readonly', True)]}),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date_deadline': fields.datetime('Deadline', states={'done': [('readonly', True)]}),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'state': fields.selection([('open', 'Confirmed'),
|
||||
('draft', 'Unconfirmed'),
|
||||
'state': fields.selection([ ('draft', 'Unconfirmed'),
|
||||
('open', 'Confirmed'),
|
||||
('cancel', 'Cancelled'),
|
||||
('done', 'Done')], 'Status', \
|
||||
size=16, readonly=True),
|
||||
('done', 'Done')],
|
||||
string='Status', size=16, readonly=True),
|
||||
}
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
|
@ -91,6 +82,17 @@ class crm_meeting(crm_base, osv.osv):
|
|||
result[obj.id] = [obj.user_id.id]
|
||||
return result
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
""" Confirms meeting """
|
||||
res = super(crm_meeting, self).case_open(cr, uid, ids, context)
|
||||
for (id, name) in self.name_get(cr, uid, ids):
|
||||
id=base_calendar.base_calendar_id2real_id(id)
|
||||
return res
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Meeting'
|
||||
|
||||
|
@ -119,32 +121,12 @@ class crm_meeting(crm_base, osv.osv):
|
|||
meeting.message_append_note(body=parent_message)
|
||||
return True
|
||||
|
||||
def case_close_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Meeting has been <b>done</b>.")
|
||||
return self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
|
||||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
for meeting in self.browse(cr, uid, ids, context=context):
|
||||
if meeting.state != 'draft':
|
||||
return False
|
||||
message = _("Meeting has been <b>confirmed</b>.")
|
||||
meeting.message_append_note(body=message)
|
||||
return True
|
||||
return self.message_append_note(cr, uid, ids, body=_("Meeting has been <b>confirmed</b>."), context=context)
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
"""Confirms meeting
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Meeting Ids
|
||||
@param *args: Tuple Value for additional Params
|
||||
"""
|
||||
res = super(crm_meeting, self).case_open(cr, uid, ids, context)
|
||||
for (id, name) in self.name_get(cr, uid, ids):
|
||||
id=base_calendar.base_calendar_id2real_id(id)
|
||||
return res
|
||||
def case_close_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_append_note(cr, uid, ids, body=_("Meeting has been <b>done</b>."), context=context)
|
||||
|
||||
crm_meeting()
|
||||
|
||||
class calendar_attendee(osv.osv):
|
||||
""" Calendar Attendee """
|
||||
|
|
|
@ -25,7 +25,22 @@
|
|||
<field name="model">crm.meeting</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Meetings">
|
||||
<form string="Meetings" layout="manual">
|
||||
<div class="oe_form_topbar oe_form_topbar_hifirst">
|
||||
<button name="case_open" string="Confirm" type="object"
|
||||
states="draft"/>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="open"/>
|
||||
<button name="case_reset" string="Reset to Unconfirmed" type="object"
|
||||
states="cancel,done"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
<sheet layout="auto">
|
||||
<group col="6" colspan="4">
|
||||
<field name="name" select="1" string="Title"
|
||||
required="1" />
|
||||
|
@ -71,19 +86,6 @@
|
|||
</group>
|
||||
<separator string="Description" colspan="4" />
|
||||
<field name="description" nolabel="1" colspan="4" />
|
||||
<separator colspan="4"/>
|
||||
<group col="8" colspan="4" groups="base.group_no_one">
|
||||
<field name="state" />
|
||||
<button name="case_close" string="Done"
|
||||
states="open" type="object"
|
||||
icon="gtk-jump-to" />
|
||||
<button name="case_reset" string="Reset to Unconfirmed"
|
||||
states="open,done" type="object"
|
||||
icon="gtk-convert" />
|
||||
<button name="case_open" string="Confirm"
|
||||
states="draft" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Invitation Detail">
|
||||
<button string="Invite People"
|
||||
|
@ -209,7 +211,10 @@
|
|||
|
||||
</page>
|
||||
</notebook>
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,26 +19,22 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from crm import crm_base
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
from base_status.base_state import base_state
|
||||
import crm
|
||||
from datetime import datetime
|
||||
from osv import fields, osv
|
||||
import time
|
||||
from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP
|
||||
from datetime import datetime
|
||||
|
||||
class crm_phonecall(crm_base, osv.osv):
|
||||
""" Phonecall Cases """
|
||||
from tools.translate import _
|
||||
|
||||
class crm_phonecall(base_state, osv.osv):
|
||||
""" Model for CRM phonecalls """
|
||||
_name = "crm.phonecall"
|
||||
_description = "Phonecall"
|
||||
_order = "id desc"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
_columns = {
|
||||
# From crm.case
|
||||
'id': fields.integer('ID', readonly=True),
|
||||
'name': fields.char('Call Summary', size=64, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
# base_state required fields
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
|
@ -48,20 +44,21 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'description': fields.text('Description'),
|
||||
'state': fields.selection([
|
||||
('draft', 'Draft'),
|
||||
('open', 'Todo'),
|
||||
'state': fields.selection([ ('draft', 'Draft'),
|
||||
('open', 'Confirmed'),
|
||||
('pending', 'Not Held'),
|
||||
('cancel', 'Cancelled'),
|
||||
('done', 'Held'),
|
||||
], 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Todo\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the call is over, the state is set to \'Held\'.\
|
||||
\nIf the call needs to be done then the state is set to \'Not Held\'.'),
|
||||
('done', 'Held'),],
|
||||
string='Status', size=16, readonly=True,
|
||||
help='The state is set to \'Todo\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the call is over, the state is set to \'Held\'.\
|
||||
If the call needs to be done then the state is set to \'Not Held\'.'),
|
||||
'email_from': fields.char('Email', size=128, help="These people will receive email."),
|
||||
'date_open': fields.datetime('Opened', readonly=True),
|
||||
# phonecall fields
|
||||
'name': fields.char('Call Summary', size=64, required=True),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
'duration': fields.float('Duration', help="Duration in Minutes"),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Category', \
|
||||
domain="['|',('section_id','=',section_id),('section_id','=',False),\
|
||||
|
@ -72,7 +69,6 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date': fields.datetime('Date'),
|
||||
'opportunity_id': fields.many2one ('crm.lead', 'Lead/Opportunity'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
}
|
||||
|
||||
def _get_default_state(self, cr, uid, context=None):
|
||||
|
@ -81,11 +77,10 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
return 'open'
|
||||
|
||||
_defaults = {
|
||||
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date': fields.datetime.now,
|
||||
'priority': crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'state': _get_default_state,
|
||||
'user_id': lambda self,cr,uid,ctx: uid,
|
||||
'active': 1,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
|
@ -96,32 +91,23 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
return obj_id
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
"""Overrides close for crm_case for setting close date
|
||||
"""
|
||||
""" Overrides close for crm_case for setting duration """
|
||||
res = True
|
||||
for phone in self.browse(cr, uid, ids):
|
||||
for phone in self.browse(cr, uid, ids, context=context):
|
||||
phone_id = phone.id
|
||||
data = {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
|
||||
data = {}
|
||||
if phone.duration <=0:
|
||||
duration = datetime.now() - datetime.strptime(phone.date, '%Y-%m-%d %H:%M:%S')
|
||||
data.update({'duration': duration.seconds/float(60)})
|
||||
res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], context)
|
||||
self.write(cr, uid, [phone_id], data)
|
||||
duration = datetime.now() - datetime.strptime(phone.date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
data['duration'] = duration.seconds/float(60)
|
||||
res = super(crm_phonecall, self).case_close(cr, uid, [phone_id], context=context)
|
||||
self.write(cr, uid, [phone_id], data, context=context)
|
||||
return res
|
||||
|
||||
def case_reset(self, cr, uid, ids, context=None):
|
||||
"""Resets case as Todo
|
||||
"""
|
||||
res = super(crm_phonecall, self).case_reset(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'})
|
||||
return res
|
||||
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
"""Overrides cancel for crm_case for setting Open Date
|
||||
"""
|
||||
res = super(crm_phonecall, self).case_open(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
self.write(cr, uid, ids, {'duration': 0.0, 'state':'open'}, context=context)
|
||||
return res
|
||||
|
||||
def schedule_another_phonecall(self, cr, uid, ids, schedule_time, call_summary, \
|
||||
|
@ -300,7 +286,7 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
return value
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
||||
def get_needaction_user_ids(self, cr, uid, ids, context=None):
|
||||
|
@ -336,9 +322,6 @@ class crm_phonecall(crm_base, osv.osv):
|
|||
|
||||
def _call_set_partner_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_append_note(cr, uid, ids, body=_("Partner has been <b>created</b>"), context=context)
|
||||
|
||||
|
||||
crm_phonecall()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -43,10 +43,14 @@
|
|||
states="open,pending" icon="gtk-redo"
|
||||
name="action_make_meeting" type="object" />
|
||||
<field name="state"/>
|
||||
<button name="case_cancel" string="Cancel" states="open,pending" type="object" icon="gtk-cancel"/>
|
||||
<button name="case_open" string="Todo" states="pending" type="object" icon="gtk-go-forward"/>
|
||||
<button name="case_close" string="Held" states="open,pending" type="object" icon="gtk-jump-to"/>
|
||||
<button name="case_pending" string="Not Held" states="open" type="object" icon="gtk-media-pause"/>
|
||||
<button name="case_open" string="Confirm" type="object"
|
||||
states="draft,pending" icon="gtk-go-forward"/>
|
||||
<button name="case_close" string="Held" type="object"
|
||||
states="open,pending" icon="gtk-jump-to"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending" icon="gtk-cancel"/>
|
||||
<button name="case_reset" string="Reset to Todo" type="object"
|
||||
states="cancel" icon="gtk-convert"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -60,13 +64,16 @@
|
|||
<field name="arch" type="xml">
|
||||
<form layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="case_close" string="Held" states="open,pending" type="object" />
|
||||
<button name="case_open" string="Todo" states="pending" type="object" />
|
||||
<button name="case_pending" string="Not Held" states="open" type="object" />
|
||||
<button name="case_reset" string="Reset to Todo" states="cancel" type="object" />
|
||||
<button name="case_cancel" string="Cancel" states="open,pending" type="object" />
|
||||
<button name="case_open" string="Confirm" type="object"
|
||||
states="draft,pending" icon="gtk-go-forward"/>
|
||||
<button name="case_close" string="Held" type="object"
|
||||
states="open,pending" icon="gtk-jump-to"/>
|
||||
<button name="case_reset" string="Reset to Todo" type="object"
|
||||
states="cancel" icon="gtk-convert"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending" icon="gtk-cancel"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="open,done" statusbar_colors='{"pending":"red"}' select="1"/>
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="draft,open,done" select="1"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -117,7 +124,7 @@
|
|||
<field name="description" nolabel="1" colspan="4" />
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -143,6 +143,8 @@
|
|||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
<field name="probability"/>
|
||||
<field name="state"/>
|
||||
<field name="type"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -162,6 +164,9 @@
|
|||
<field name="on_change"/>
|
||||
<field name="case_default"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
<field name="fold"/>
|
||||
<field name="type"/>
|
||||
</group>
|
||||
<separator string="Requirements" colspan="4"/>
|
||||
<field name="requirements" nolabel="1" colspan="4"/>
|
||||
|
|
|
@ -7,14 +7,14 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 6.0dev\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2012-02-08 01:37+0100\n"
|
||||
"PO-Revision-Date: 2012-02-16 14:00+0000\n"
|
||||
"PO-Revision-Date: 2012-06-01 08:42+0000\n"
|
||||
"Last-Translator: Erwin <Unknown>\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: 2012-05-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 15225)\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.lead.report:0
|
||||
|
@ -172,7 +172,7 @@ msgstr "Verwachte besluit maand"
|
|||
#. module: crm
|
||||
#: view:crm.lead2opportunity.partner.mass:0
|
||||
msgid "Assigned Opportunities to"
|
||||
msgstr ""
|
||||
msgstr "Toegewezen porspects aan"
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.lead:0 field:crm.lead,partner_id:0 view:crm.lead.report:0
|
||||
|
@ -599,7 +599,7 @@ msgstr "Einddatum"
|
|||
#. module: crm
|
||||
#: view:crm.opportunity2phonecall:0 view:crm.phonecall2phonecall:0
|
||||
msgid "Schedule/Log a Call"
|
||||
msgstr ""
|
||||
msgstr "Plan/Log een gesprek"
|
||||
|
||||
#. module: crm
|
||||
#: constraint:base.action.rule:0
|
||||
|
@ -792,7 +792,7 @@ msgstr "Doorgaan"
|
|||
#. module: crm
|
||||
#: field:crm.segmentation,som_interval:0
|
||||
msgid "Days per Period"
|
||||
msgstr ""
|
||||
msgstr "Dagen per periode"
|
||||
|
||||
#. module: crm
|
||||
#: field:crm.meeting,byday:0
|
||||
|
@ -960,7 +960,7 @@ msgstr "Dagen voor openen"
|
|||
#. module: crm
|
||||
#: view:crm.meeting:0
|
||||
msgid "Show Time as"
|
||||
msgstr ""
|
||||
msgstr "Tijd weergeven als"
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.phonecall2partner:0
|
||||
|
@ -1344,7 +1344,7 @@ msgstr "Schrijfdatum"
|
|||
#. module: crm
|
||||
#: view:crm.meeting:0
|
||||
msgid "End of Recurrency"
|
||||
msgstr ""
|
||||
msgstr "Einde herhaling"
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.meeting:0
|
||||
|
@ -1907,7 +1907,7 @@ msgstr "Antwoord aan"
|
|||
#. module: crm
|
||||
#: view:crm.case.section:0
|
||||
msgid "Select Stages for this Sales Team"
|
||||
msgstr ""
|
||||
msgstr "Selecteer de fases voor dit verkoopteam"
|
||||
|
||||
#. module: crm
|
||||
#: view:board.board:0
|
||||
|
@ -2779,7 +2779,7 @@ msgstr "E-mail adres van de contactpersoon"
|
|||
#. module: crm
|
||||
#: field:crm.lead,referred:0
|
||||
msgid "Referred by"
|
||||
msgstr ""
|
||||
msgstr "Gerefereerd door"
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.lead:0 model:ir.model,name:crm.model_crm_add_note
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
-
|
||||
I check cancelled lead.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in cancel state}:
|
||||
- state == "cancel"
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_itisatelesalescampaign0'))
|
||||
assert lead.stage_id.id == ref('crm.stage_lead7'), "Stage should be 'Dead' and is %s." % (lead.stage_id.name)
|
||||
assert lead.state == 'cancel', "Opportunity is not in 'cancel' state."
|
||||
assert lead.probability == 0.0, 'Opportunity probability is wrong and should be 0.0.'
|
||||
-
|
||||
I reset cancelled lead into unqualified lead.
|
||||
-
|
||||
|
@ -19,35 +22,24 @@
|
|||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in draft state}:
|
||||
- state == "draft"
|
||||
-
|
||||
I put unqualified lead into pending.
|
||||
I re-open the lead
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_pending(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
self.case_open(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check status of pending lead.
|
||||
I check stage and state of the re-opened lead
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Lead is in pending state}:
|
||||
- state == "pending"
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm.crm_case_itisatelesalescampaign0'))
|
||||
assert lead.stage_id.id == ref('crm.stage_lead2'), "Opportunity stage should be 'Qualification'."
|
||||
assert lead.state == 'open', "Opportunity should be in 'open' state."
|
||||
-
|
||||
I escalate the lead to parent team.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_escalate(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check lead escalate to parent team.
|
||||
I check the lead is correctly escalated to the parent team.
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_itisatelesalescampaign0, string: Escalate lead to parent team}:
|
||||
- section_id.name == "Sales Department"
|
||||
-
|
||||
I mark as lost the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_lost(cr, uid, [ref("crm_case_itisatelesalescampaign0")])
|
||||
-
|
||||
I check opportunity after lost.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_itisatelesalescampaign0'))
|
||||
assert lead.state == 'done', "lead is not done state"
|
||||
assert lead.stage_id.id == ref('crm.stage_lead6'), 'Stage is not changed!'
|
||||
assert lead.probability == 0.0, 'Probability is wrong!'
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.action_makeMeeting(cr, uid, [ref('crm_case_qrecorp0')])
|
||||
|
||||
-
|
||||
After communicated with customer, I put some notes with contract details.
|
||||
-
|
||||
|
@ -60,18 +59,18 @@
|
|||
note_id = self.create(cr, uid, {'body': "ces détails envoyés par le client sur le FAX pour la qualité"})
|
||||
self.action_add(cr, uid, [note_id], context=context)
|
||||
-
|
||||
Finally, I won this opportunity, so I close this opportunity.
|
||||
I win this opportunity
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_won(cr, uid, [ref("crm_case_qrecorp0")])
|
||||
-
|
||||
I check details of the opportunity after won the opportunity.
|
||||
I check details of the opportunity after having won the opportunity.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_qrecorp0'))
|
||||
assert lead.state == 'done', 'Opportunity is not in done state!'
|
||||
assert lead.stage_id.name == 'Won', ' Stage of Opportunity is not win!'
|
||||
assert lead.probability == 100.0, 'probability revenue should not be 100.0!'
|
||||
assert lead.stage_id.id == ref('crm.stage_lead6'), "Opportunity stage should be 'Won'."
|
||||
assert lead.state == 'done', "Opportunity is not in 'done' state!"
|
||||
assert lead.probability == 100.0, "Revenue probability should be 100.0!"
|
||||
-
|
||||
I convert mass lead into opportunity customer.
|
||||
-
|
||||
|
@ -96,6 +95,19 @@
|
|||
assert opp.name == "Interest in Your New Product", "Opportunity name not correct"
|
||||
assert opp.type == 'opportunity', 'Lead is not converted to opportunity!'
|
||||
assert opp.stage_id.id == ref("stage_lead1"), 'Stage of probability is incorrect!'
|
||||
-
|
||||
I loose the second opportunity
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_mark_lost(cr, uid, [ref("crm_case_electonicgoodsdealer0")])
|
||||
-
|
||||
I check details of the opportunity after the loose
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead = self.browse(cr, uid, ref('crm_case_electonicgoodsdealer0'))
|
||||
assert lead.stage_id.id == ref('crm.stage_lead8'), "Opportunity stage should be 'Lost'."
|
||||
assert lead.state == 'cancel', "Lost opportunity is not in 'cancel' state!"
|
||||
assert lead.probability == 0.0, "Revenue probability should be 0.0!"
|
||||
-
|
||||
I confirm review needs meeting.
|
||||
-
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,25 +19,57 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from crm import crm
|
||||
import time
|
||||
from crm import wizard
|
||||
from base_status.base_stage import base_stage
|
||||
import binascii
|
||||
from crm import crm
|
||||
from crm import wizard
|
||||
from osv import fields, osv
|
||||
import time
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
wizard.mail_compose_message.SUPPORTED_MODELS.append('crm.claim')
|
||||
|
||||
CRM_CLAIM_PENDING_STATES = (
|
||||
crm.AVAILABLE_STATES[2][0], # Cancelled
|
||||
crm.AVAILABLE_STATES[3][0], # Done
|
||||
crm.AVAILABLE_STATES[4][0], # Pending
|
||||
)
|
||||
|
||||
|
||||
class crm_claim(crm.crm_case, osv.osv):
|
||||
class crm_claim_stage(osv.osv):
|
||||
""" Model for claim stages. This models the main stages of a claim
|
||||
management flow. Main CRM objects (leads, opportunities, project
|
||||
issues, ...) will now use only stages, instead of state and stages.
|
||||
Stages are for example used to display the kanban view of records.
|
||||
"""
|
||||
Crm claim
|
||||
_name = "crm.claim.stage"
|
||||
_description = "Claim stages"
|
||||
_rec_name = 'name'
|
||||
_order = "sequence"
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Stage Name', size=64, required=True, translate=True),
|
||||
'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
|
||||
'section_ids':fields.many2many('crm.case.section', 'section_claim_stage_rel', 'stage_id', 'section_id', string='Sections',
|
||||
help="Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams."),
|
||||
'state': fields.selection(crm.AVAILABLE_STATES, 'State', required=True, help="The related state for the stage. The state of your document will automatically change regarding the selected stage. For example, if a stage is related to the state 'Close', when your document reaches this stage, it will be automatically have the 'closed' state."),
|
||||
'case_refused': fields.boolean('Refused stage',
|
||||
help='Refused stages are specific stages for done.'),
|
||||
'case_default': fields.boolean('Common to All Teams',
|
||||
help="If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams."),
|
||||
'fold': fields.boolean('Hide in Views when Empty',
|
||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'sequence': lambda *args: 1,
|
||||
'state': 'draft',
|
||||
'fold': False,
|
||||
'case_refused': False,
|
||||
}
|
||||
|
||||
class crm_claim(base_stage, osv.osv):
|
||||
""" Crm claim
|
||||
"""
|
||||
_name = "crm.claim"
|
||||
_description = "Claim"
|
||||
|
@ -73,30 +105,71 @@ class crm_claim(crm.crm_case, osv.osv):
|
|||
'email_cc': fields.text('Watchers Emails', size=252, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
|
||||
'email_from': fields.char('Email', size=128, help="These people will receive email."),
|
||||
'partner_phone': fields.char('Phone', size=32),
|
||||
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_ids','=',section_id)]"),
|
||||
'stage_id': fields.many2one ('crm.claim.stage', 'Stage',
|
||||
domain="['|', ('section_ids', '=', section_id), ('case_default', '=', True)]"),
|
||||
'cause': fields.text('Root Cause'),
|
||||
'state': fields.selection(crm.AVAILABLE_STATES, 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=crm.AVAILABLE_STATES, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'user_id': crm.crm_case._get_default_user,
|
||||
'partner_id': crm.crm_case._get_default_partner,
|
||||
'email_from':crm.crm_case. _get_default_email,
|
||||
'state': lambda *a: 'draft',
|
||||
'section_id':crm.crm_case. _get_section,
|
||||
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'user_id': lambda s, cr, uid, c: s._get_default_user(cr, uid, c),
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
|
||||
'date': fields.datetime.now,
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
|
||||
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'active': lambda *a: 1
|
||||
}
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Claim'
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the lead:
|
||||
- section_id: if set, stages must belong to this section or
|
||||
be a default case
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
section_ids = []
|
||||
if section_id:
|
||||
section_ids.append(section_id)
|
||||
for claim in cases:
|
||||
if claim.section_id:
|
||||
section_ids.append(claim.section_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('section_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('crm.claim.stage').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(crm_claim, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def case_refuse(self, cr, uid, ids, context=None):
|
||||
""" Mark the case as refused: state=done and case_refused=True """
|
||||
for lead in self.browse(cr, uid, ids):
|
||||
stage_id = self.stage_find(cr, uid, [lead], lead.section_id.id or False, ['&', ('state', '=', 'done'), ('case_refused', '=', True)], context=context)
|
||||
if stage_id:
|
||||
self.case_set(cr, uid, [lead.id], values_to_update={}, new_stage_id=stage_id, context=context)
|
||||
return self.case_refuse_send_note(cr, uid, ids, context=context)
|
||||
|
||||
def onchange_partner_id(self, cr, uid, ids, part, email=False):
|
||||
"""This function returns value of partner address based on partner
|
||||
|
@ -110,19 +183,6 @@ class crm_claim(crm.crm_case, osv.osv):
|
|||
}
|
||||
address = self.pool.get('res.partner').browse(cr, uid, part)
|
||||
return {'value': {'email_from': address.email, 'partner_phone': address.phone}}
|
||||
|
||||
def case_open(self, cr, uid, ids, *args):
|
||||
"""Opens Claim"""
|
||||
for l in self.browse(cr, uid, ids):
|
||||
# When coming from draft override date and stage otherwise just set state
|
||||
if l.state == 'draft':
|
||||
message = _("The claim '%s' has been opened.") % l.name
|
||||
self.log(cr, uid, l.id, message)
|
||||
stage_id = self.stage_find(cr, uid, l.section_id.id or False, [('sequence','>',0)])
|
||||
if stage_id:
|
||||
self.stage_set(cr, uid, [l.id], stage_id)
|
||||
res = super(crm_claim, self).case_open(cr, uid, ids, *args)
|
||||
return res
|
||||
|
||||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||
"""Automatically called when new email message arrives"""
|
||||
|
@ -177,6 +237,28 @@ class crm_claim(crm.crm_case, osv.osv):
|
|||
res = self.write(cr, uid, [case.id], values, context=context)
|
||||
return res
|
||||
|
||||
# ---------------------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ---------------------------------------------------
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
""" Override of default prefix for notifications. """
|
||||
return 'Claim'
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Claim has been <b>created</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def case_refuse_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Claim has been <b>refused</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
stage_name = self.pool.get('crm.claim.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
|
||||
class res_partner(osv.osv):
|
||||
_inherit = 'res.partner'
|
||||
_columns = {
|
||||
|
|
|
@ -42,27 +42,39 @@
|
|||
Case Stage
|
||||
-->
|
||||
|
||||
<record model="crm.case.stage" id="stage_claim1">
|
||||
<field name="name">Accepted as Claim</field>
|
||||
<record model="crm.claim.stage" id="stage_claim1">
|
||||
<field name="name">Draft claim</field>
|
||||
<field name="state">draft</field>
|
||||
<field name="sequence">26</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_claim5">
|
||||
<record model="crm.claim.stage" id="stage_claim5">
|
||||
<field name="name">Actions Defined</field>
|
||||
<field name="state">open</field>
|
||||
<field name="sequence">27</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_claim2">
|
||||
<record model="crm.claim.stage" id="stage_claim2">
|
||||
<field name="name">Actions Done</field>
|
||||
<field name="state">done</field>
|
||||
<field name="sequence">28</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record model="crm.case.stage" id="stage_claim3">
|
||||
<field name="name">Won't fix</field>
|
||||
<record model="crm.claim.stage" id="stage_claim3">
|
||||
<field name="name">Refused</field>
|
||||
<field name="state">done</field>
|
||||
<field name="sequence">29</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
<field name="case_refused" eval="True"/>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
<record model="crm.claim.stage" id="stage_claim3">
|
||||
<field name="name">Cancelled</field>
|
||||
<field name="state">cancel</field>
|
||||
<field name="sequence">30</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="crm.case.section" id="crm.section_sales_department">
|
||||
<field name="name">Sales Department</field>
|
||||
<field name="code">Sales</field>
|
||||
<field name="stage_ids" eval="[(4, ref('stage_claim1')), (4, ref('stage_claim2')), (4, ref('stage_claim3')), (4, ref('stage_claim5'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Problem with the delivery of goods"" name="name"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim1"/>
|
||||
<field name="stage_id" ref="crm_claim.stage_claim1"/>
|
||||
|
@ -25,7 +24,6 @@
|
|||
<field eval=""4"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Damaged Products"" name="name"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim2"/>
|
||||
<field name="stage_id" ref="crm_claim.stage_claim5"/>
|
||||
|
@ -38,7 +36,6 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval=""Document related problems"" name="name"/>
|
||||
<field eval=""done"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim3"/>
|
||||
<field name="stage_id" ref="crm_claim.stage_claim2"/>
|
||||
|
@ -52,7 +49,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Product quality not maintained"" name="name"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim1"/>
|
||||
<field name="stage_id" ref="crm_claim.stage_claim5"/>
|
||||
|
@ -65,7 +61,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Some products missing"" name="name"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim3"/>
|
||||
<field name="stage_id" ref="crm_claim.stage_claim3"/>
|
||||
|
@ -77,7 +72,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Problem with the delivery of assignments"" name="name"/>
|
||||
<field eval=""cancel"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-28 14:15:30')" name="date"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim1"/>
|
||||
|
@ -91,7 +85,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""Documents unclear"" name="name"/>
|
||||
<field eval=""done"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-19 13:01:05')" name="date"/>
|
||||
<field name="categ_id" ref="crm_claim.categ_claim3"/>
|
||||
|
|
|
@ -50,5 +50,10 @@
|
|||
<menuitem name="Claims" id="menu_crm_case_claims"
|
||||
parent="base.menu_aftersale" action="crm_case_categ_claim0" sequence="1"/>
|
||||
|
||||
<!-- Claim Stages -->
|
||||
<menuitem id="menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/>
|
||||
<menuitem id="menu_project_config_project" name="Stages" parent="menu_definitions" sequence="1"/>
|
||||
<menuitem id="menu_claim_stage_view" name="Claim Stages" action="crm_claim_stage_act" parent="menu_project_config_project" sequence="20"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -23,12 +23,40 @@
|
|||
|
||||
<!-- Claim Stages -->
|
||||
|
||||
<record id="crm_claim_stage_tree" model="ir.ui.view">
|
||||
<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="Claim Stages">
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_claim_stage_form" model="ir.ui.view">
|
||||
<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="Claim Stage">
|
||||
<field name="name"/>
|
||||
<field name="case_default"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
<field name="case_refused"/>
|
||||
<field name="fold"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_claim_stage_act" model="ir.actions.act_window">
|
||||
<field name="name">Claim Stages</field>
|
||||
<field name="res_model">crm.case.stage</field>
|
||||
<field name="res_model">crm.claim.stage</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_stage_tree"/>
|
||||
<field name="context">{'search_default_claim':1}</field>
|
||||
<field name="view_id" ref="crm_claim_stage_tree"/>
|
||||
<field name="help">You can create claim stages to categorize the status of every claim entered in the system. The stages define all the steps required for the resolution of a claim.</field>
|
||||
</record>
|
||||
|
||||
|
@ -44,19 +72,13 @@
|
|||
<field name="partner_id"/>
|
||||
<field name="user_id" />
|
||||
<field name="date"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="date_action_next"/>
|
||||
<field name="action_next"/>
|
||||
<field name="categ_id" string="Type" select="1"/>
|
||||
<field name="stage_id" invisible="1"/>
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="date_closed" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_close" string="Close"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -68,13 +90,23 @@
|
|||
<field name="arch" type="xml">
|
||||
<form layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="case_close" string="Done" states="open,pending" type="object" />
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" />
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object" />
|
||||
<button name="case_reset" string="Reset to Draft" states="done,cancel" type="object" />
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" />
|
||||
<button name="case_open" string="Open" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="open,pending"/>
|
||||
<button name="case_refuse" string="Refuse" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="stage_previous" string="Previous Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="stage_next" string="Next Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="case_reset" string="Reset to Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" select="1" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"
|
||||
on_change="onchange_stage_id(stage_id)"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -86,11 +118,7 @@
|
|||
<group colspan="4" col="6">
|
||||
<field name="user_id"/>
|
||||
<field name="section_id" widget="selection" />
|
||||
<group colspan="2" col="4">
|
||||
<field name="stage_id" domain="[('section_ids','=',section_id)]"/>
|
||||
<button name="stage_previous" string="" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="" type="object" icon="gtk-go-forward" />
|
||||
</group>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<newline />
|
||||
<field name="priority"/>
|
||||
<field name="date_deadline"/>
|
||||
|
@ -138,32 +166,12 @@
|
|||
<field name="resolution" colspan="2" nolabel="1"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Communication & History">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="Global CC" widget="char"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
<button
|
||||
string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply'}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
context="{'model': 'crm.lead' }"
|
||||
icon="terp-document-new" type="action" />
|
||||
<button string="Send New Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
icon="terp-mail-message-new" type="action"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -227,7 +235,7 @@
|
|||
domain="[]" context="{'group_by':'categ_id'}" />
|
||||
<filter string="Status"
|
||||
icon="terp-stock_effects-object-colorize"
|
||||
domain="[]" context="{'group_by':'state'}" />
|
||||
domain="[]" context="{'group_by':'state'}" groups="base.group_no_one"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Claim Date" icon="terp-go-month"
|
||||
domain="[]" help="Claim Date"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_crm_claim_manager,crm.claim.manager,model_crm_claim,base.group_sale_manager,1,1,1,1
|
||||
access_crm_claim_user,crm.claim.user,model_crm_claim,base.group_sale_salesman,1,1,1,0
|
||||
access_crm_claim_stage_user,crm.claim.stage.user,model_crm_claim_stage,base.group_sale_salesman,1,1,1,1
|
||||
access_crm_claim_report_manager,crm.claim.report.manager,model_crm_claim_report,base.group_sale_manager,1,1,1,1
|
||||
access_crm_claim_partner_manager,crm.claim.partner.manager,model_crm_claim,base.group_partner_manager,1,0,0,0
|
||||
|
|
|
|
@ -30,7 +30,7 @@
|
|||
claim_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right <info@customer.com>')])
|
||||
claim = self.browse(cr, uid, claim_ids[0])
|
||||
assert claim.state == "open", "Claim is not in Open state"
|
||||
assert claim.stage_id.id == ref("crm.stage_lead1"), "Claim is not in New stage"
|
||||
assert claim.stage_id.id == ref("crm.stage_lead2"), "Claim is not in Qualification stage"
|
||||
-
|
||||
After complete all service from our side, I close this claim.
|
||||
-
|
||||
|
|
|
@ -19,13 +19,15 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
from base_status.base_stage import base_stage
|
||||
from crm import crm
|
||||
from crm import wizard
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
|
||||
wizard.mail_compose_message.SUPPORTED_MODELS.append('crm.fundraising')
|
||||
|
||||
class crm_fundraising(crm.crm_case, osv.osv):
|
||||
class crm_fundraising(base_stage, osv.osv):
|
||||
""" Fund Raising Cases """
|
||||
|
||||
_name = "crm.fundraising"
|
||||
|
@ -68,14 +70,62 @@ class crm_fundraising(crm.crm_case, osv.osv):
|
|||
'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),
|
||||
'state': fields.selection(crm.AVAILABLE_STATES, 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=crm.AVAILABLE_STATES, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': 1,
|
||||
'user_id': lambda s, cr, uid, c: s._get_default_user(cr, uid, c),
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
|
||||
'priority': crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'probability': 0.0,
|
||||
'planned_cost': 0.0,
|
||||
'planned_revenue': 0.0,
|
||||
}
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the lead:
|
||||
- section_id: if set, stages must belong to this section or
|
||||
be a default case
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
section_ids = []
|
||||
if section_id:
|
||||
section_ids.append(section_id)
|
||||
for case in cases:
|
||||
if case.section_id:
|
||||
section_ids.append(case.section_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('section_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(crm_fundraising, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||
"""Automatically called when new email message arrives"""
|
||||
|
@ -93,21 +143,23 @@ class crm_fundraising(crm.crm_case, osv.osv):
|
|||
self.write(cr, uid, [res_id], vals, context=context)
|
||||
return res_id
|
||||
|
||||
# ---------------------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ---------------------------------------------------
|
||||
|
||||
_defaults = {
|
||||
'active': 1,
|
||||
'user_id': crm.crm_case._get_default_user,
|
||||
'partner_id': crm.crm_case._get_default_partner,
|
||||
'email_from': crm.crm_case. _get_default_email,
|
||||
'state': 'draft',
|
||||
'section_id': crm.crm_case. _get_section,
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
|
||||
'priority': crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'probability': 0.0,
|
||||
'planned_cost': 0.0,
|
||||
'planned_revenue': 0.0,
|
||||
}
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
""" Override of default prefix for notifications. """
|
||||
return 'Fundraising'
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Fundraising has been <b>created</b>.')
|
||||
self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
return True
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
stage_name = self.pool.get('crm.case.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field eval="250000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-01 10:35:50')" name="date"/>
|
||||
|
@ -26,7 +25,6 @@
|
|||
<field name="partner_id" ref="base.main_partner"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field eval="2000000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-05 12:35:50')" name="date"/>
|
||||
|
@ -43,7 +41,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field eval="500000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-07 13:50:50')" name="date"/>
|
||||
|
@ -59,7 +56,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_4"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field eval="1000000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-12 15:10:50')" name="date"/>
|
||||
|
@ -75,7 +71,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_14"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field eval="5000000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-17 19:00:15')" name="date"/>
|
||||
|
@ -91,7 +86,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""done"" name="state"/>
|
||||
<field eval="10000000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-27 09:00:15')" name="date"/>
|
||||
|
@ -109,7 +103,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_15"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field eval="10000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-01 10:00:15')" name="date"/>
|
||||
|
@ -126,7 +119,6 @@
|
|||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field eval="800000.0" name="planned_cost"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="time.strftime('%Y-%m-24 22:00:15')" name="date"/>
|
||||
|
|
|
@ -50,22 +50,6 @@
|
|||
<field name="user_id" />
|
||||
<field name="state" />
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<button name="case_cancel" string="Cancel"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="draft,open" type="object" icon="gtk-media-pause" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_close" string="Done"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button name="case_reset" string="Reset to Draft"
|
||||
states="done,cancel" type="object" icon="gtk-convert" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -117,29 +101,6 @@
|
|||
<separator colspan="4" string="Notes"/>
|
||||
<field name="description" nolabel="1" colspan="4"/>
|
||||
</page>
|
||||
<page string="Communication & History">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="Global CC" widget="char"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
<button
|
||||
string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
context="{'model': 'crm.lead' }"
|
||||
icon="terp-document-new" type="action" />
|
||||
<button string="Send New Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
icon="terp-mail-message-new" type="action"/>
|
||||
</page>
|
||||
<page string="Extra Info">
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="4" string="Misc"/>
|
||||
|
@ -162,6 +123,9 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from base_status.base_state import base_state
|
||||
from crm import crm
|
||||
from osv import fields, osv
|
||||
import time
|
||||
from crm import wizard
|
||||
from osv import fields, osv
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
|
@ -34,7 +34,7 @@ CRM_HELPDESK_STATES = (
|
|||
|
||||
wizard.mail_compose_message.SUPPORTED_MODELS.append('crm.helpdesk')
|
||||
|
||||
class crm_helpdesk(crm.crm_case, osv.osv):
|
||||
class crm_helpdesk(base_state, osv.osv):
|
||||
""" Helpdesk Cases """
|
||||
|
||||
_name = "crm.helpdesk"
|
||||
|
@ -77,21 +77,24 @@ class crm_helpdesk(crm.crm_case, osv.osv):
|
|||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'user_id': crm.crm_case._get_default_user,
|
||||
'partner_id': crm.crm_case._get_default_partner,
|
||||
'email_from': crm.crm_case. _get_default_email,
|
||||
'user_id': lambda s, cr, uid, c: s._get_default_user(cr, uid, c),
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'state': lambda *a: 'draft',
|
||||
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'section_id': crm.crm_case. _get_section,
|
||||
'date': lambda *a: fields.datetime.now(),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
|
||||
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
|
||||
}
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(crm_helpdesk, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
|
||||
"""Automatically called when new email message arrives"""
|
||||
res_id = super(crm_helpdesk,self).message_new(cr, uid, msg_dict, custom_values=custom_values, context=context)
|
||||
|
@ -142,5 +145,18 @@ class crm_helpdesk(crm.crm_case, osv.osv):
|
|||
res = self.write(cr, uid, [case.id], values, context=context)
|
||||
return res
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# ******************************
|
||||
# OpenChatter
|
||||
# ******************************
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
""" override of default base_state method. """
|
||||
return 'Case'
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Case has been <b>created</b>.')
|
||||
self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
return True
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -30,12 +30,18 @@
|
|||
<field name="arch" type="xml">
|
||||
<form layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="case_close" states="open,pending" string="Close" type="object" />
|
||||
<button name="case_open" states="draft,pending" string="Open" type="object" />
|
||||
<button name="case_pending" states="draft,open" string="Pending" type="object" />
|
||||
<button name="case_reset" states="done,cancel" string="Reset to Draft" type="object" />
|
||||
<button name="case_escalate" states="open,draft,pending" string="Escalate" type="object" />
|
||||
<button name="case_cancel" states="draft,open,pending" string="Cancel" type="object" />
|
||||
<button name="case_open" string="Open" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="case_close" string="Close" type="object"
|
||||
states="open,draft,pending"/>
|
||||
<button name="case_pending" string="Pending" type="object"
|
||||
states="draft,open"/>
|
||||
<button name="case_reset" string="Reset to Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
<button name="case_escalate" string="Escalate" type="object"
|
||||
states="open,draft,pending"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" select="1" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
</div>
|
||||
|
@ -78,29 +84,6 @@
|
|||
<separator colspan="4" string="Notes"/>
|
||||
<field name="description" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
<page string="Communication & History">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="Global CC" widget="char"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree" readonly="1">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="email_from" invisible="1"/>
|
||||
<button
|
||||
string="Reply" attrs="{'invisible': [('email_from', '=', False)]}"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context="{'mail.compose.message.mode':'reply', 'message_id':active_id}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
context="{'model': 'crm.lead' }"
|
||||
icon="terp-document-new" type="action" />
|
||||
<button string="Send New Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
icon="terp-mail-message-new" type="action"/>
|
||||
</page>
|
||||
<page string="Extra Info">
|
||||
<group colspan="2" col="2" groups="base.group_no_one">
|
||||
<separator colspan="4" string="Dates"/>
|
||||
|
@ -126,6 +109,9 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -147,23 +133,6 @@
|
|||
<field name="section_id"/>
|
||||
<field name="priority"/>
|
||||
<field name="state"/>
|
||||
<button name="case_cancel" string="Cancel"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="draft,open" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_close" string="Done"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button name="case_reset" string="Reset to Draft"
|
||||
states="done,cancel" type="object" icon="gtk-convert" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -116,8 +116,6 @@
|
|||
<field name="email_from"/>
|
||||
<field name="email_to"/>
|
||||
<field name="report_name"/>
|
||||
<button name="%(wizard_email_template_preview)d" string="Preview Template"
|
||||
type="action" target="new" icon="gtk-zoom-fit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -48,6 +48,7 @@ class event_event(osv.osv):
|
|||
_name = 'event.event'
|
||||
_description = __doc__
|
||||
_order = 'date_begin'
|
||||
_inherit = ['ir.needaction_mixin','mail.thread']
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not ids:
|
||||
|
@ -70,6 +71,11 @@ class event_event(osv.osv):
|
|||
res = self.name_get(cr, uid, ids, context=context)
|
||||
return dict(res)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(event_event, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
""" Reset the state and the registrations while copying an event
|
||||
"""
|
||||
|
@ -82,6 +88,7 @@ class event_event(osv.osv):
|
|||
return super(event_event, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
def button_draft(self, cr, uid, ids, context=None):
|
||||
self.button_draft_send_note(cr, uid, ids, context=context)
|
||||
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
|
||||
|
||||
def button_cancel(self, cr, uid, ids, context=None):
|
||||
|
@ -91,9 +98,11 @@ class event_event(osv.osv):
|
|||
if event_reg.state == 'done':
|
||||
raise osv.except_osv(_('Error!'),_("You have already set a registration for this event as 'Attended'. Please reset it to draft if you want to cancel this event.") )
|
||||
registration.write(cr, uid, reg_ids, {'state': 'cancel'}, context=context)
|
||||
self.button_cancel_send_note(cr, uid, ids, context=context)
|
||||
return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
|
||||
|
||||
def button_done(self, cr, uid, ids, context=None):
|
||||
self.button_done_send_note(cr, uid, ids, context=context)
|
||||
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
|
||||
|
||||
def check_registration_limits(self, cr, uid, ids, context=None):
|
||||
|
@ -127,6 +136,7 @@ class event_event(osv.osv):
|
|||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
self.check_registration_limits(cr, uid, ids, context=context)
|
||||
self.button_confirm_send_note(cr, uid, ids, context=context)
|
||||
return self.confirm_event(cr, uid, ids, context=context)
|
||||
|
||||
def _get_register(self, cr, uid, ids, fields, args, context=None):
|
||||
|
@ -256,13 +266,50 @@ class event_event(osv.osv):
|
|||
'register_max': type_info.default_registration_max,
|
||||
}
|
||||
return {'value': dic}
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def get_needaction_user_ids(self, cr, uid, ids, context=None):
|
||||
result = dict.fromkeys(ids, [])
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.state == 'draft' and obj.user_id:
|
||||
result[obj.id] = [obj.user_id.id]
|
||||
return result
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Event has been <b>created</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
def button_cancel_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Event has been <b>cancelled</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
def button_draft_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Event has been set to <b>draft</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
def button_done_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Event has been <b>done</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
def button_confirm_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Event has been <b>confirmed</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
event_event()
|
||||
|
||||
class event_registration(osv.osv):
|
||||
"""Event Registration"""
|
||||
_name= 'event.registration'
|
||||
_description = __doc__
|
||||
_inherit = ['mail.thread','res.partner']
|
||||
_inherit = ['ir.needaction_mixin','mail.thread','res.partner']
|
||||
_columns = {
|
||||
'id': fields.integer('ID'),
|
||||
'origin': fields.char('Source', size=124,readonly=True,help="Name of the sale order which create the registration"),
|
||||
|
@ -293,12 +340,17 @@ class event_registration(osv.osv):
|
|||
|
||||
|
||||
def do_draft(self, cr, uid, ids, context=None):
|
||||
self.do_draft_send_note(cr, uid, ids, context=context)
|
||||
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
|
||||
|
||||
def confirm_registration(self, cr, uid, ids, context=None):
|
||||
self.message_append(cr, uid, ids,_('State set to open'),body_text= _('Open'))
|
||||
return self.write(cr, uid, ids, {'state': 'open'}, context=context)
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(event_registration, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def registration_open(self, cr, uid, ids, context=None):
|
||||
""" Open Registration
|
||||
|
@ -395,6 +447,27 @@ class event_registration(osv.osv):
|
|||
data.update(d['value'])
|
||||
return {'value': data}
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def get_needaction_user_ids(self, cr, uid, ids, context=None):
|
||||
result = dict.fromkeys(ids, [])
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.state == 'draft' and obj.user_id:
|
||||
result[obj.id] = [obj.user_id.id]
|
||||
return result
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Registration has been <b>created</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
def do_draft_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Registration has been set as <b>draft</b>.")
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
return True
|
||||
|
||||
event_registration()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -130,7 +130,10 @@
|
|||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -153,10 +156,6 @@
|
|||
<field name="main_speaker_id" groups="base.extended"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state"/>
|
||||
<button string="Confirm Event" help="Confirm Event" name="button_confirm" states="draft" type="object" icon="gtk-apply"/>
|
||||
<button string="Event Done" help="Event Done" name="button_done" states="confirm" type="object" icon="gtk-jump-to"/>
|
||||
<button string="Cancel Event" help="Cancel Event" name="button_cancel" states="draft,confirm" type="object" icon="gtk-cancel"/>
|
||||
<button string="Set To Draft" help="Set To Draft" name="button_draft" states="cancel,done" type="object" icon="gtk-convert"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -346,10 +345,6 @@
|
|||
<field name="user_id"/>
|
||||
<field name="origin"/>
|
||||
<field name="state"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
<button name="button_reg_close" string="Attended" states="open" type="object" icon="gtk-apply"/>
|
||||
<button string="Set To Unconfirmed" name="do_draft" states="cancel,done" type="object" icon="gtk-convert"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -414,7 +409,10 @@
|
|||
</page>
|
||||
|
||||
</notebook>
|
||||
</sheet>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
<field name="currency_id"/>
|
||||
<field name="amount"/>
|
||||
<field name="state"/>
|
||||
<button name="confirm" states="draft" string="Confirm" type="workflow" icon="gtk-apply"/>
|
||||
<button name="refuse" states="confirm,draft,accepted" string="Refuse" type="workflow" icon="gtk-no" groups="base.group_hr_user"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -153,7 +153,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -177,8 +177,6 @@
|
|||
<field name="user_id" invisible="1"/>
|
||||
<!--field name="type"/-->
|
||||
<field name="state"/>
|
||||
<button string="Approve" name="validate" states="confirm" type="workflow" icon="gtk-apply" groups="base.group_hr_user,base.group_hr_manager"/>
|
||||
<button string="Validate" name="second_validate" states="validate1" type="workflow" icon="gtk-apply" groups="base.group_hr_user,base.group_hr_manager"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -234,9 +232,6 @@
|
|||
<field name="manager_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="state"/>
|
||||
<button string="Submit to Manager" name="confirm" states="draft" type="workflow" icon="gtk-yes"/>
|
||||
<button string="Approve" name="validate" states="confirm" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
|
||||
<button string="Refuse" name="refuse" states="confirm" type="workflow" icon="gtk-no" groups="base.group_hr_user"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -262,8 +257,6 @@
|
|||
<field name="manager_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<!--field name="type"/-->
|
||||
<button string="Approve" name="validate" states="confirm" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
|
||||
<button string="Validate" name="second_validate" states="validate1" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
# Latvian translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
|
||||
"PO-Revision-Date: 2012-06-01 07:35+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Latvian <lv@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: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.payslip,move_id:0
|
||||
msgid "Accounting Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.salary.rule,account_tax_id:0
|
||||
msgid "Tax Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.payslip,journal_id:0
|
||||
#: field:hr.payslip.run,journal_id:0
|
||||
msgid "Expense Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:157
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:173
|
||||
#, python-format
|
||||
msgid "Adjustment Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.contract,analytic_account_id:0
|
||||
#: field:hr.salary.rule,analytic_account_id:0
|
||||
msgid "Analytic Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: model:ir.model,name:hr_payroll_account.model_hr_salary_rule
|
||||
msgid "hr.salary.rule"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: model:ir.model,name:hr_payroll_account.model_hr_payslip_run
|
||||
msgid "Payslip Batches"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.contract,journal_id:0
|
||||
msgid "Salary Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: model:ir.model,name:hr_payroll_account.model_hr_payslip
|
||||
msgid "Pay Slip"
|
||||
msgstr "Algas Lapa"
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: constraint:hr.payslip:0
|
||||
msgid "Payslip 'Date From' must be before 'Date To'."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: help:hr.payslip,period_id:0
|
||||
msgid "Keep empty to use the period of the validation(Payslip) date."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:171
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The Expense Journal \"%s\" has not properly configured the Debit Account!"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:155
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The Expense Journal \"%s\" has not properly configured the Credit Account!"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.salary.rule,account_debit:0
|
||||
msgid "Debit Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:102
|
||||
#, python-format
|
||||
msgid "Payslip of %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: model:ir.model,name:hr_payroll_account.model_hr_contract
|
||||
msgid "Contract"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: constraint:hr.contract:0
|
||||
msgid "Error! contract start-date must be lower then contract end-date."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.payslip,period_id:0
|
||||
msgid "Force Period"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: field:hr.salary.rule,account_credit:0
|
||||
msgid "Credit Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: model:ir.model,name:hr_payroll_account.model_hr_payslip_employees
|
||||
msgid "Generate payslips for all selected employees"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:155
|
||||
#: code:addons/hr_payroll_account/hr_payroll_account.py:171
|
||||
#, python-format
|
||||
msgid "Configuration Error!"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_payroll_account
|
||||
#: view:hr.contract:0
|
||||
#: view:hr.salary.rule:0
|
||||
msgid "Accounting"
|
||||
msgstr ""
|
|
@ -37,7 +37,14 @@ system to store and search in your CV base.
|
|||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'images': ['images/hr_recruitment_analysis.jpeg','images/hr_recruitment_applicants.jpeg'],
|
||||
'depends': ['decimal_precision', 'hr', 'survey', 'crm', 'fetchmail'],
|
||||
'depends': [
|
||||
'base_status',
|
||||
'decimal_precision',
|
||||
'hr',
|
||||
'survey',
|
||||
'crm',
|
||||
'fetchmail',
|
||||
],
|
||||
'update_xml': [
|
||||
'wizard/hr_recruitment_phonecall_view.xml',
|
||||
'wizard/hr_recruitment_employee_hired.xml',
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<field name="job_id"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from base_status.base_stage import base_stage
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
@ -57,8 +58,6 @@ class hr_recruitment_source(osv.osv):
|
|||
_columns = {
|
||||
'name': fields.char('Source Name', size=64, required=True, translate=True),
|
||||
}
|
||||
hr_recruitment_source()
|
||||
|
||||
|
||||
class hr_recruitment_stage(osv.osv):
|
||||
""" Stage of HR Recruitment """
|
||||
|
@ -69,12 +68,15 @@ class hr_recruitment_stage(osv.osv):
|
|||
'name': fields.char('Name', size=64, required=True, translate=True),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of stages."),
|
||||
'department_id':fields.many2one('hr.department', 'Specific to a Department', help="Stages of the recruitment process may be different per department. If this stage is common to all departments, keep tempy this field."),
|
||||
'requirements': fields.text('Requirements')
|
||||
'state': fields.selection(AVAILABLE_STATES, 'State', required=True, help="The related state for the stage. The state of your document will automatically change regarding the selected stage. Example, a stage is related to the state 'Close', when your document reach this stage, it will be automatically closed."),
|
||||
'fold': fields.boolean('Hide in views if empty', help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
'requirements': fields.text('Requirements'),
|
||||
}
|
||||
_defaults = {
|
||||
'sequence': 1,
|
||||
'state': 'draft',
|
||||
'fold': False,
|
||||
}
|
||||
hr_recruitment_stage()
|
||||
|
||||
class hr_recruitment_degree(osv.osv):
|
||||
""" Degree of HR Recruitment """
|
||||
|
@ -90,14 +92,60 @@ class hr_recruitment_degree(osv.osv):
|
|||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', 'The name of the Degree of Recruitment must be unique!')
|
||||
]
|
||||
hr_recruitment_degree()
|
||||
|
||||
class hr_applicant(crm.crm_case, osv.osv):
|
||||
class hr_applicant(base_stage, osv.Model):
|
||||
_name = "hr.applicant"
|
||||
_description = "Applicant"
|
||||
_order = "id desc"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
|
||||
def _get_default_department_id(self, cr, uid, context=None):
|
||||
""" Gives default department by checking if present in the context """
|
||||
return (self._resolve_department_id_from_context(cr, uid, context=context) or False)
|
||||
|
||||
def _get_default_stage_id(self, cr, uid, context=None):
|
||||
""" Gives default stage_id """
|
||||
department_id = self._get_default_department_id(cr, uid, context=context)
|
||||
return self.stage_find(cr, uid, [], department_id, [('state', '=', 'draft')], context=context)
|
||||
|
||||
def _resolve_department_id_from_context(self, cr, uid, context=None):
|
||||
""" Returns ID of department based on the value of 'default_department_id'
|
||||
context key, or None if it cannot be resolved to a single
|
||||
department.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if type(context.get('default_department_id')) in (int, long):
|
||||
return context.get('default_department_id')
|
||||
if isinstance(context.get('default_department_id'), basestring):
|
||||
department_name = context['default_department_id']
|
||||
department_ids = self.pool.get('hr.department').name_search(cr, uid, name=department_name, context=context)
|
||||
if len(department_ids) == 1:
|
||||
return int(department_ids[0][0])
|
||||
return None
|
||||
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
stage_obj = self.pool.get('hr.recruitment.stage')
|
||||
order = stage_obj._order
|
||||
# lame hack to allow reverting search, should just work in the trivial case
|
||||
if read_group_order == 'stage_id desc':
|
||||
order = "%s desc" % order
|
||||
# retrieve section_id from the context and write the domain
|
||||
# - ('id', 'in', 'ids'): add columns that should be present
|
||||
# - OR ('department_id', '=', False), ('fold', '=', False): add default columns that are not folded
|
||||
# - OR ('department_id', 'in', department_id), ('fold', '=', False) if department_id: add department columns that are not folded
|
||||
department_id = self._resolve_department_id_from_context(cr, uid, context=context)
|
||||
search_domain = []
|
||||
if department_id:
|
||||
search_domain += ['|', '&', ('department_id', '=', department_id), ('fold', '=', False)]
|
||||
search_domain += ['|', ('id', 'in', ids), '&', ('department_id', '=', False), ('fold', '=', False)]
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
|
||||
return result
|
||||
|
||||
def _compute_day(self, cr, uid, ids, fields, args, context=None):
|
||||
"""
|
||||
@param cr: the current row, from the database cursor,
|
||||
|
@ -134,7 +182,6 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128, required=True),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'active': fields.boolean('Active', help="If the active field is set to false, it will allow you to hide the case without removing it."),
|
||||
'description': fields.text('Description'),
|
||||
'email_from': fields.char('Email', size=128, help="These people will receive email."),
|
||||
|
@ -143,12 +190,15 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'create_date': fields.datetime('Creation Date', readonly=True, select=True),
|
||||
'write_date': fields.datetime('Update Date', readonly=True),
|
||||
'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage'),
|
||||
'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage',
|
||||
domain="['|', ('department_id', '=', department_id), ('department_id', '=', False)]"),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=AVAILABLE_STATES, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'user_id': fields.many2one('res.users', 'Responsible'),
|
||||
# Applicant Columns
|
||||
|
@ -169,7 +219,6 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
'partner_mobile': fields.char('Mobile', size=32),
|
||||
'type_id': fields.many2one('hr.recruitment.degree', 'Degree'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
|
||||
'survey': fields.related('job_id', 'survey_id', type='many2one', relation='survey', string='Survey'),
|
||||
'response': fields.integer("Response"),
|
||||
'reference': fields.char('Refered By', size=128),
|
||||
|
@ -185,33 +234,19 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
|
||||
_defaults = {
|
||||
'active': lambda *a: 1,
|
||||
'user_id': lambda self, cr, uid, context: uid,
|
||||
'email_from': crm.crm_case. _get_default_email,
|
||||
'state': lambda *a: 'draft',
|
||||
'user_id': lambda s, cr, uid, c: uid,
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
|
||||
'department_id': lambda s, cr, uid, c: s._get_default_department_id(cr, uid, c),
|
||||
'priority': lambda *a: '',
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
|
||||
'color': 0,
|
||||
}
|
||||
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
stage_obj = self.pool.get('hr.recruitment.stage')
|
||||
order = stage_obj._order
|
||||
if read_group_order == 'stage_id desc':
|
||||
# lame hack to allow reverting search, should just work in the trivial case
|
||||
order = "%s desc" % order
|
||||
stage_ids = stage_obj._search(cr, uid, ['|',('id','in',ids),('department_id','=',False)], order=order,
|
||||
access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
|
||||
return result
|
||||
|
||||
_group_by_full = {
|
||||
'stage_id': _read_group_stage_ids
|
||||
}
|
||||
|
||||
|
||||
def onchange_job(self,cr, uid, ids, job, context=None):
|
||||
result = {}
|
||||
|
||||
|
@ -229,47 +264,33 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
stage_id = stage_ids and stage_ids[0] or False
|
||||
return {'value': {'stage_id': stage_id}}
|
||||
|
||||
def stage_previous(self, cr, uid, ids, context=None):
|
||||
"""This function computes previous stage for case from its current stage
|
||||
using available stage for that case type
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of case IDs
|
||||
@param context: A standard dictionary for contextual values"""
|
||||
stage_obj = self.pool.get('hr.recruitment.stage')
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
department = (case.department_id.id or False)
|
||||
st = case.stage_id.id or False
|
||||
stage_ids = stage_obj.search(cr, uid, ['|',('department_id','=',department),('department_id','=',False)], context=context)
|
||||
if st and stage_ids.index(st):
|
||||
self.write(cr, uid, [case.id], {'stage_id': stage_ids[stage_ids.index(st)-1]}, context=context)
|
||||
else:
|
||||
self.write(cr, uid, [case.id], {'stage_id': False}, context=context)
|
||||
return True
|
||||
|
||||
def stage_next(self, cr, uid, ids, context=None):
|
||||
"""This function computes next stage for case from its current stage
|
||||
using available stage for that case type
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of case IDs
|
||||
@param context: A standard dictionary for contextual values"""
|
||||
stage_obj = self.pool.get('hr.recruitment.stage')
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
department = (case.department_id.id or False)
|
||||
st = case.stage_id.id or False
|
||||
stage_ids = stage_obj.search(cr, uid, ['|',('department_id','=',department),('department_id','=',False)], context=context)
|
||||
val = False
|
||||
if st and len(stage_ids) != stage_ids.index(st)+1:
|
||||
val = stage_ids[stage_ids.index(st)+1]
|
||||
elif (not st) and stage_ids:
|
||||
val = stage_ids[0]
|
||||
else:
|
||||
val = False
|
||||
self.write(cr, uid, [case.id], {'stage_id': val}, context=context)
|
||||
return True
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the lead:
|
||||
- department_id: if set, stages must belong to this section or
|
||||
be a default case
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
department_ids = []
|
||||
if section_id:
|
||||
department_ids.append(section_id)
|
||||
for case in cases:
|
||||
if case.department_id:
|
||||
department_ids.append(case.department_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if department_ids:
|
||||
search_domain += ['|', ('department_id', 'in', department_ids)]
|
||||
search_domain.append(('department_id', '=', False))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('hr.recruitment.stage').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def action_makeMeeting(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
|
@ -474,12 +495,6 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
"""
|
||||
return self.set_priority(cr, uid, ids, '3')
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if 'stage_id' in vals and vals['stage_id']:
|
||||
stage = self.pool.get('hr.recruitment.stage').browse(cr, uid, vals['stage_id'], context=context)
|
||||
self.message_append_note(cr, uid, ids, body=_("Stage changed to <b>%s</b>.") % stage.name, context=context)
|
||||
return super(hr_applicant,self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# -------------------------------------------------------
|
||||
|
@ -497,7 +512,13 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
if obj.state == 'draft' and obj.user_id:
|
||||
result[obj.id] = [obj.user_id.id]
|
||||
return result
|
||||
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
if not stage_id: return True
|
||||
stage_name = self.pool.get('hr.recruitment.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Applicant'
|
||||
|
||||
|
@ -529,7 +550,6 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
message = _("Applicant has been <b>created</b>.")
|
||||
return self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
|
||||
hr_applicant()
|
||||
|
||||
class hr_job(osv.osv):
|
||||
_inherit = "hr.job"
|
||||
|
@ -537,6 +557,6 @@ class hr_job(osv.osv):
|
|||
_columns = {
|
||||
'survey_id': fields.many2one('survey', 'Interview Form', help="Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job"),
|
||||
}
|
||||
hr_job()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<!--
|
||||
<data noupdate="1">
|
||||
|
||||
-->
|
||||
<data>
|
||||
|
||||
<!-- HR Recruitment Source -->
|
||||
|
||||
|
@ -37,30 +39,36 @@
|
|||
<field name="name">Doctoral Degree</field>
|
||||
<field name="sequence">4</field>
|
||||
</record>
|
||||
|
||||
<record model="hr.recruitment.stage" id="stage_job1">
|
||||
<field name="name">Initial Qualification</field>
|
||||
<field name="state">draft</field>
|
||||
<field name="sequence">1</field>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job2">
|
||||
<field name="name">First Interview</field>
|
||||
<field name="state">open</field>
|
||||
<field name="sequence">2</field>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job3">
|
||||
<field name="name">Second Interview</field>
|
||||
<field name="state">open</field>
|
||||
<field name="sequence">3</field>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job4">
|
||||
<field name="name">Contract Proposed</field>
|
||||
<field name="state">pending</field>
|
||||
<field name="sequence">4</field>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job5">
|
||||
<field name="name">Contract Signed</field>
|
||||
<field name="state">done</field>
|
||||
<field name="sequence">5</field>
|
||||
</record>
|
||||
<record model="hr.recruitment.stage" id="stage_job6">
|
||||
<field name="name">Refused</field>
|
||||
<field name="state">cancel</field>
|
||||
<field name="sequence">6</field>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
<record id="survey_job_0" model="survey">
|
||||
<field name="title">Job Survey</field>
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
<field name="partner_phone"/>
|
||||
<field name="job_id"/>
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous" states="open,pending" type="object" icon="gtk-go-back"/>
|
||||
<button name="stage_next" string="Next" states="open,pending" type="object" icon="gtk-go-forward"/>
|
||||
<field name="title_action" invisible="context.get('invisible_next_action', True)"/>
|
||||
<field name="date_action" invisible="context.get('invisible_next_date', True)"/>
|
||||
<field name="source_id" invisible="1"/>
|
||||
|
@ -62,9 +60,7 @@
|
|||
<field name="availability" invisible="1"/>
|
||||
<field name="department_id" invisible="context.get('invisible_department', True)"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="In Progress" states="draft,pending" type="object" icon="gtk-go-forward"/>
|
||||
<button name="case_pending" string="Pending" states="open" type="object" icon="gtk-media-pause"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -76,14 +72,24 @@
|
|||
<field name="arch" type="xml">
|
||||
<form layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="%(action_hr_recruitment_hired_employee)d" string="Hire" states="open,pending" type="action"/>
|
||||
<button name="case_open" string="In Progress" states="draft,pending" type="object"/>
|
||||
<button name="case_pending" string="Pending" states="open" type="object"/>
|
||||
<button name="case_reset" string="Reset to New" states="done,cancel" type="object"/>
|
||||
<button name="case_cancel" string="Refuse" states="draft,open,pending" type="object"/>
|
||||
<button name="%(action_hr_recruitment_hired_employee)d" string="Hire" type="action"
|
||||
states="open,pending"/>
|
||||
<button name="case_open" string="Open" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="case_pending" string="Pending" type="object"
|
||||
states="open"/>
|
||||
<button name="case_reset" string="Reset to New" type="object"
|
||||
states="done,cancel"/>
|
||||
<button name="case_cancel" string="Refuse" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="stage_previous" string="Previous" type="object"
|
||||
states="open" icon="gtk-go-back"/>
|
||||
<button name="stage_next" string="Next" type="object"
|
||||
states="open" icon="gtk-go-forward"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
<sheet string="Jobs - Recruitment Form" layout="auto">
|
||||
<group colspan="4" col="4">
|
||||
|
@ -96,11 +102,7 @@
|
|||
<field name="user_id"/>
|
||||
<field name="job_id" on_change="onchange_job(job_id)"/>
|
||||
<field name="department_id" widget="selection" on_change="onchange_department_id(department_id)"/>
|
||||
<group colspan="2" col="4">
|
||||
<field name="stage_id" domain="['|',('department_id','=',department_id),('department_id','=',False)]"/>
|
||||
<button name="stage_previous" string="" type="object" icon="gtk-go-back"/>
|
||||
<button icon="gtk-go-forward" string="" name="stage_next" type="object"/>
|
||||
</group>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="date_action"/>
|
||||
<group colspan="2" col="8">
|
||||
<field name="title_action"/>
|
||||
|
@ -139,6 +141,13 @@
|
|||
<field name="source_id"/>
|
||||
<field name="reference"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="2" string="Dates"/>
|
||||
<field name="create_date"/>
|
||||
<field name="write_date"/>
|
||||
<field name="date_closed"/>
|
||||
<field name="date_open"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Notes">
|
||||
<field name="description" nolabel="1" colspan="4"/>
|
||||
|
@ -146,7 +155,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -241,7 +250,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="stage_id">
|
||||
<field name="color"/>
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="priority"/>
|
||||
<field name="survey"/>
|
||||
<field name="user_id"/>
|
||||
|
@ -360,6 +369,7 @@
|
|||
<field name="sequence" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -377,6 +387,7 @@
|
|||
<field name="name" select="1"/>
|
||||
<field name="department_id"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
</group>
|
||||
<separator string="Requirements" colspan="4"/>
|
||||
<field name="requirements" nolabel="1" colspan="4"/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-
|
||||
In Order to test process of Recruitment,
|
||||
-
|
||||
Applicant interested in job position. so He send resume by email.
|
||||
An applicant is interested in the job position. So he sends a resume by email.
|
||||
-
|
||||
!python {model: mail.thread}: |
|
||||
import addons
|
||||
|
@ -9,27 +9,42 @@
|
|||
request_message = request_file.read()
|
||||
self.message_process(cr, uid, 'hr.applicant', request_message)
|
||||
-
|
||||
After getting the mail, I check details of new applicant.
|
||||
After getting the mail, I check the details of the new applicant.
|
||||
-
|
||||
!python {model: hr.applicant}: |
|
||||
applicant_ids = self.search(cr, uid, [('email_from','=', 'Mr. Richard Anderson <Richard_Anderson@yahoo.com>')])
|
||||
assert applicant_ids, "Applicant is not created after getting the mail"
|
||||
applicant = self.browse(cr, uid, applicant_ids[0], context=context)
|
||||
resume_ids = self.pool.get('ir.attachment').search(cr, uid, [('datas_fname','=','resume.doc'),('res_model','=',self._name),('res_id','=',applicant.id)])
|
||||
assert applicant.name == "Application for the post of Jr.application Programmer.", "Subject does not match"
|
||||
assert applicant.state == "draft"
|
||||
assert len(resume_ids), "Resume does not attached."
|
||||
assert applicant.name == "Application for the post of Jr.application Programmer.", "Applicant name does not match."
|
||||
assert applicant.stage_id.id == ref('hr_recruitment.stage_job1'), "Stage should be 'Initial qualification' and is '%s'." % (applicant.stage_id.name)
|
||||
assert applicant.state == "draft", "Applicant state should be 'draft'."
|
||||
assert len(resume_ids), "Resume is not attached."
|
||||
-
|
||||
I refuse applicant for the Recruitment.
|
||||
I refuse the applicant (hr_case_programmer)
|
||||
-
|
||||
!python {model: hr.applicant}: |
|
||||
self.case_close(cr, uid, [ref("hr_case_programmer")])
|
||||
self.case_cancel(cr, uid, [ref("hr_case_programmer")])
|
||||
-
|
||||
I open applicant for the Recruitment.
|
||||
I check the details of the refused applicant.
|
||||
-
|
||||
!python {model: hr.applicant}: |
|
||||
applicant = self.browse(cr, uid, ref("hr_case_programmer"), context=context)
|
||||
assert applicant.stage_id.id == ref('hr_recruitment.stage_job6'), "Stage should be 'Refused' and is %s." % (applicant.stage_id.name)
|
||||
assert applicant.state == 'cancel', "Applicant is not in 'cancel' state."
|
||||
-
|
||||
I reset and re-open the previously refused applicant.
|
||||
-
|
||||
!python {model: hr.applicant}: |
|
||||
self.case_reset(cr, uid, [ref("hr_case_programmer")])
|
||||
self.case_open(cr, uid, [ref("hr_case_programmer")])
|
||||
-
|
||||
I check the details of the re-opened applicant.
|
||||
-
|
||||
!python {model: hr.applicant}: |
|
||||
applicant = self.browse(cr, uid, ref("hr_case_programmer"), context=context)
|
||||
assert applicant.stage_id.id == ref('hr_recruitment.stage_job2'), "Stage should be 'First interview' and is '%s'." % (applicant.stage_id.name)
|
||||
assert applicant.state == "open", "Applicant state should be 'open'."
|
||||
-
|
||||
I assign the Job position to the applicant
|
||||
-
|
||||
|
@ -91,7 +106,7 @@
|
|||
-
|
||||
I check that applicant is "Hired".
|
||||
-
|
||||
!assert {model: hr.applicant, id: hr_case_programmer}:
|
||||
!assert {model: hr.applicant, id: hr_case_programmer, string: Applicant state is done}:
|
||||
- state == 'done'
|
||||
-
|
||||
I do not give employment to the hired the applicant.
|
||||
|
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-01 05:33+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: idea
|
||||
|
|
|
@ -267,10 +267,6 @@
|
|||
<field name="count_comments"/>
|
||||
<field name="count_votes"/>
|
||||
<field name="state"/>
|
||||
<button name="idea_open" string="Open" states="draft" icon="terp-gtk-go-back-rtl"/>
|
||||
<button name="%(idea.action_idea_post_vote)d" icon="gtk-execute" type="action" states="open" string="Submit Vote"/>
|
||||
<button name="idea_close" string="Accept" states="open" icon="gtk-jump-to"/>
|
||||
<button name="idea_cancel" string="Refuse" states="open" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -60,16 +60,6 @@
|
|||
<field name="category"/>
|
||||
<field name="price" sum="Total price"/>
|
||||
<field name="state"/>
|
||||
<button colspan="1"
|
||||
name="%(action_lunch_order_cancel)d"
|
||||
string="Cancel Order"
|
||||
type="action" states="confirmed"
|
||||
icon="gtk-cancel" />
|
||||
<button colspan="1"
|
||||
name="%(action_lunch_order_confirm)d"
|
||||
string="Confirm Order"
|
||||
type="action" states="draft"
|
||||
icon="terp-gtk-go-back-rtl" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -340,7 +330,7 @@
|
|||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Box Amount by User">
|
||||
<field name="date" invisible="1"/>
|
||||
<field name="date" invisible="1"/>
|
||||
<field name="year" invisible="1"/>
|
||||
<field name="day" invisible="1"/>
|
||||
<field name="month" invisible="1"/>
|
||||
|
|
|
@ -9,3 +9,4 @@ Mail Module documentation topics
|
|||
mail_thread
|
||||
mail_openchatter_howto
|
||||
mail_needaction_howto
|
||||
mail_partner
|
||||
|
|
|
@ -38,7 +38,7 @@ Make your module inheriting from the ``mail.thread`` class.
|
|||
# inherit from mail.thread allows the use of OpenChatter
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
Use the thread viewer widget inside your form view by using the ThreadView widget on the message_ids_social field inherited from mail.thread.
|
||||
Use the thread viewer widget inside your form view by using the ThreadView widget on the message_ids field inherited from mail.thread.
|
||||
|
||||
::
|
||||
|
||||
|
@ -50,7 +50,7 @@ Use the thread viewer widget inside your form view by using the ThreadView widge
|
|||
<field name="arch" type="xml">
|
||||
<form>
|
||||
[...]
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
What is shown
|
||||
==============
|
||||
- for every module which are related to partner show apporopriate message in the partner view like opportunities, sale orders and invoices.
|
||||
|
||||
|
||||
How it is done
|
||||
===============
|
||||
- _inherit = 'mail.thread'
|
||||
|
||||
- Override def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None) search by the partner
|
|
@ -69,7 +69,8 @@
|
|||
<label string="This group is visible by non members" colspan="2"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"
|
||||
options='{"thread_level": 1}'/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -61,29 +61,29 @@ class mail_thread(osv.osv):
|
|||
'''
|
||||
_name = 'mail.thread'
|
||||
_description = 'Email Thread'
|
||||
|
||||
|
||||
def _get_message_ids(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for id in ids:
|
||||
res[id] = self.message_load_ids(cr, uid, [id], context=context)
|
||||
return res
|
||||
|
||||
# OpenChatter: message_ids_social is a dummy field that should not be used
|
||||
|
||||
# OpenChatter: message_ids is a dummy field that should not be used
|
||||
_columns = {
|
||||
'message_ids_social': fields.function(_get_message_ids, method=True,
|
||||
'message_ids': fields.function(_get_message_ids, method=True,
|
||||
type='one2many', obj='mail.message', string='Temp messages', _fields_id = 'res_id'),
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
# Automatic subscription when creating/reading
|
||||
#------------------------------------------------------
|
||||
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
"""Automatically subscribe the creator"""
|
||||
thread_id = super(mail_thread, self).create(cr, uid, vals, context=context);
|
||||
self.message_subscribe(cr, uid, [thread_id], [uid], context=context)
|
||||
return thread_id;
|
||||
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
"""Automatically subscribe the writer"""
|
||||
if isinstance(ids, (int, long)):
|
||||
|
@ -92,7 +92,7 @@ class mail_thread(osv.osv):
|
|||
if write_res:
|
||||
self.message_subscribe(cr, uid, ids, [uid], context=context)
|
||||
return write_res;
|
||||
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
"""Override unlink, to automatically delete
|
||||
- subscriptions
|
||||
|
@ -111,13 +111,13 @@ class mail_thread(osv.osv):
|
|||
# delete notifications
|
||||
msg_to_del_ids = msg_obj.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)], context=context)
|
||||
msg_obj.unlink(cr, uid, msg_to_del_ids, context=context)
|
||||
|
||||
|
||||
return super(mail_thread, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
|
||||
#------------------------------------------------------
|
||||
# Generic message api
|
||||
#------------------------------------------------------
|
||||
|
||||
|
||||
def message_create(self, cr, uid, thread_id, vals, context=None):
|
||||
"""OpenSocial: wrapper of mail.message create method
|
||||
- creates the mail.message
|
||||
|
@ -131,15 +131,15 @@ class mail_thread(osv.osv):
|
|||
notification_obj = self.pool.get('mail.notification')
|
||||
res_users_obj = self.pool.get('res.users')
|
||||
body = vals.get('body_html', '') if vals.get('subtype', 'plain') == 'html' else vals.get('body_text', '')
|
||||
|
||||
|
||||
# automatically subscribe the writer of the message
|
||||
if vals['user_id']:
|
||||
self.message_subscribe(cr, uid, [thread_id], [vals['user_id']], context=context)
|
||||
|
||||
|
||||
# get users that will get a notification pushed
|
||||
user_to_push_ids = self.message_create_get_notification_user_ids(cr, uid, [thread_id], vals, context=context)
|
||||
user_to_push_from_parse_ids = self.message_parse_users(cr, uid, [thread_id], body, context=context)
|
||||
|
||||
|
||||
# set email_from and email_to for comments and notifications
|
||||
if vals.get('type', False) and vals['type'] == 'comment' or vals['type'] == 'notification':
|
||||
current_user = res_users_obj.browse(cr, uid, [uid], context=context)[0]
|
||||
|
@ -159,24 +159,24 @@ class mail_thread(osv.osv):
|
|||
if email_to:
|
||||
vals['email_to'] = email_to
|
||||
vals['state'] = 'outgoing'
|
||||
|
||||
|
||||
# create message
|
||||
msg_id = message_obj.create(cr, uid, vals, context=context)
|
||||
|
||||
|
||||
# special: if install mode, do not push demo data
|
||||
if context.get('install_mode', False):
|
||||
return True
|
||||
|
||||
|
||||
# push to users
|
||||
for id in user_to_push_ids:
|
||||
notification_obj.create(cr, uid, {'user_id': id, 'message_id': msg_id}, context=context)
|
||||
|
||||
|
||||
return msg_id
|
||||
|
||||
|
||||
def message_create_get_notification_user_ids(self, cr, uid, thread_ids, new_msg_vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
|
||||
notif_user_ids = []
|
||||
body = new_msg_vals.get('body_html', '') if new_msg_vals.get('subtype', 'plain') == 'html' else new_msg_vals.get('body_text', '')
|
||||
for thread_id in thread_ids:
|
||||
|
@ -193,7 +193,7 @@ class mail_thread(osv.osv):
|
|||
parent_notif_ids = notif_obj.search(cr, uid, [('message_id', '=', new_msg_vals.get('parent_id'))], context=context)
|
||||
parent_notifs = notif_obj.read(cr, uid, parent_notif_ids, context=context)
|
||||
notif_user_ids += [parent_notif['user_id'][0] for parent_notif in parent_notifs]
|
||||
|
||||
|
||||
# remove duplicate entries
|
||||
notif_user_ids = list(set(notif_user_ids))
|
||||
return notif_user_ids
|
||||
|
@ -214,7 +214,7 @@ class mail_thread(osv.osv):
|
|||
for model_name in self.pool.obj_list():
|
||||
model = self.pool.get(model_name)
|
||||
if 'mail.thread' in getattr(model, '_inherit', []):
|
||||
ret_dict[model_name] = model._description
|
||||
ret_dict[model_name] = model._description
|
||||
return ret_dict
|
||||
|
||||
def message_append(self, cr, uid, threads, subject, body_text=None, body_html=None,
|
||||
|
@ -259,7 +259,7 @@ class mail_thread(osv.osv):
|
|||
to determine the model of the thread to
|
||||
update (instead of the current model).
|
||||
"""
|
||||
if context is None:
|
||||
if context is None:
|
||||
context = {}
|
||||
if attachments is None:
|
||||
attachments = {}
|
||||
|
@ -329,7 +329,7 @@ class mail_thread(osv.osv):
|
|||
'headers': headers,
|
||||
'reply_to': reply_to,
|
||||
'original': original, })
|
||||
|
||||
|
||||
new_msg_ids.append(self.message_create(cr, uid, thread.id, data, context=context))
|
||||
return new_msg_ids
|
||||
|
||||
|
@ -390,7 +390,7 @@ class mail_thread(osv.osv):
|
|||
if (cur_iter > max_iter):
|
||||
_logger.warning("Possible infinite loop in _message_add_ancestor_ids. Note that this algorithm is intended to check for cycle in message graph.")
|
||||
return child_ids
|
||||
|
||||
|
||||
def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None):
|
||||
""" OpenChatter feature: return thread messages ids. It searches in
|
||||
mail.messages where res_id = ids, (res_)model = current model.
|
||||
|
@ -408,13 +408,15 @@ class mail_thread(osv.osv):
|
|||
limit=limit, offset=offset, context=context)
|
||||
if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context)
|
||||
return msg_ids
|
||||
|
||||
|
||||
def message_load(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None):
|
||||
""" OpenChatter feature: return thread messages
|
||||
"""
|
||||
msg_ids = self.message_load_ids(cr, uid, ids, limit, offset, domain, ascent, root_ids, context=context)
|
||||
return self.pool.get('mail.message').read(cr, uid, msg_ids, context=context)
|
||||
|
||||
msgs = self.pool.get('mail.message').read(cr, uid, msg_ids, context=context)
|
||||
msgs = sorted(msgs, key=lambda d: (-d['id']))
|
||||
return msgs
|
||||
|
||||
def get_pushed_messages(self, cr, uid, ids, limit=100, offset=0, msg_search_domain=[], ascent=False, root_ids=[], context=None):
|
||||
""" OpenChatter: wall: get messages to display (=pushed notifications)
|
||||
:param domain: domain to add to the search; especially child_of
|
||||
|
@ -442,7 +444,7 @@ class mail_thread(osv.osv):
|
|||
if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context)
|
||||
msgs = msg_obj.read(cr, uid, msg_ids, context=context)
|
||||
return msgs
|
||||
|
||||
|
||||
#------------------------------------------------------
|
||||
# Email specific
|
||||
#------------------------------------------------------
|
||||
|
@ -534,7 +536,7 @@ class mail_thread(osv.osv):
|
|||
|
||||
def message_new(self, cr, uid, msg_dict, custom_values=None, context=None):
|
||||
"""Called by ``message_process`` when a new message is received
|
||||
for a given thread model, if the message did not belong to
|
||||
for a given thread model, if the message did not belong to
|
||||
an existing thread.
|
||||
The default behavior is to create a new record of the corresponding
|
||||
model (based on some very basic info extracted from the message),
|
||||
|
@ -660,7 +662,7 @@ class mail_thread(osv.osv):
|
|||
The keys used in the returned dict are meant to map
|
||||
to usual names for relationships towards a partner
|
||||
and one of its addresses.
|
||||
|
||||
|
||||
:param email: email address for which a partner
|
||||
should be searched for.
|
||||
:rtype: dict
|
||||
|
@ -685,7 +687,7 @@ class mail_thread(osv.osv):
|
|||
#------------------------------------------------------
|
||||
# Note specific
|
||||
#------------------------------------------------------
|
||||
|
||||
|
||||
def message_broadcast(self, cr, uid, ids, subject=None, body=None, parent_id=False, type='notification', subtype='html', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -710,11 +712,11 @@ class mail_thread(osv.osv):
|
|||
for msg_id in msg_ids:
|
||||
notification_obj.create(cr, uid, {'user_id': user.id, 'message_id': msg_id}, context=context)
|
||||
return True
|
||||
|
||||
|
||||
def log(self, cr, uid, id, message, secondary=False, context=None):
|
||||
_logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.")
|
||||
self.message_append_note(cr, uid, [id], 'res.log', message, context=context)
|
||||
|
||||
|
||||
def message_append_note(self, cr, uid, ids, subject=None, body=None, parent_id=False, type='notification', subtype='html', context=None):
|
||||
if subject is None:
|
||||
if type == 'notification':
|
||||
|
@ -730,29 +732,29 @@ class mail_thread(osv.osv):
|
|||
body_html = body
|
||||
body_text = body
|
||||
return self.message_append(cr, uid, ids, subject, body_html=body_html, body_text=body_text, parent_id=parent_id, type=type, subtype=subtype, context=context)
|
||||
|
||||
|
||||
#------------------------------------------------------
|
||||
# Subscription mechanism
|
||||
#------------------------------------------------------
|
||||
|
||||
|
||||
def message_get_subscribers_ids(self, cr, uid, ids, context=None):
|
||||
subscr_obj = self.pool.get('mail.subscription')
|
||||
subscr_ids = subscr_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context)
|
||||
subs = subscr_obj.read(cr, uid, subscr_ids, context=context)
|
||||
return [sub['user_id'][0] for sub in subs]
|
||||
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
user_ids = self.message_get_subscribers_ids(cr, uid, ids, context=context)
|
||||
users = self.pool.get('res.users').read(cr, uid, user_ids, fields=['id', 'name', 'avatar'], context=context)
|
||||
return users
|
||||
|
||||
|
||||
def message_is_subscriber(self, cr, uid, ids, user_id = None, context=None):
|
||||
users = self.message_get_subscribers(cr, uid, ids, context=context)
|
||||
sub_user_id = uid if user_id is None else user_id
|
||||
if sub_user_id in [user['id'] for user in users]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, user_ids = None, context=None):
|
||||
subscription_obj = self.pool.get('mail.subscription')
|
||||
to_subscribe_uids = [uid] if user_ids is None else user_ids
|
||||
|
@ -776,7 +778,7 @@ class mail_thread(osv.osv):
|
|||
#------------------------------------------------------
|
||||
# Notification API
|
||||
#------------------------------------------------------
|
||||
|
||||
|
||||
def message_remove_pushed_notifications(self, cr, uid, ids, msg_ids, remove_childs=True, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
|
|
@ -24,11 +24,32 @@ from osv import fields
|
|||
|
||||
class res_partner(osv.osv):
|
||||
""" Inherits partner and adds CRM information in the partner form """
|
||||
_inherit = 'res.partner'
|
||||
_name = "res.partner"
|
||||
_inherit = ['res.partner', 'mail.thread']
|
||||
_columns = {
|
||||
'emails': fields.one2many('mail.message', 'partner_id', 'Emails', readonly=True, domain=[('email_from','!=',False)]),
|
||||
}
|
||||
|
||||
def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[False], context=None):
|
||||
""" Override of message_load_ids
|
||||
partner discussion page :
|
||||
- messages posted on res.partner, partner_id = partner.id
|
||||
- messages directly sent to partner
|
||||
"""
|
||||
msg_obj = self.pool.get('mail.message')
|
||||
msg_ids = []
|
||||
partner_ids=[]
|
||||
for partner in self.browse(cr, uid, ids, context=context):
|
||||
msg_ids += msg_obj.search(cr, uid, [ ('res_id', '=', partner.id), ('model', '=' ,self._name)] + domain,
|
||||
limit=limit, offset=offset, context=context)
|
||||
if self._name=='res.partner':
|
||||
partner_ids=msg_obj.search(cr, uid, [ ('partner_id', 'in', ids)] + domain,
|
||||
limit=limit, offset=offset, context=context)
|
||||
if partner_ids :
|
||||
msg_ids+= partner_ids
|
||||
if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context)
|
||||
return msg_ids
|
||||
|
||||
res_partner()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
<page string="History" position="inside">
|
||||
<field name="emails" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<xpath expr="/form/notebook" position="after">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"
|
||||
options='{"thread_level": 1}'/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</field>
|
||||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</data>
|
||||
|
|
|
@ -476,10 +476,12 @@ openerp.mail = function(session) {
|
|||
// QWeb template to use when rendering the object
|
||||
template: 'RecordThread',
|
||||
|
||||
init: function() {
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.see_subscribers = true;
|
||||
this.thread = null;
|
||||
this.params = this.get_definition_options();
|
||||
this.params.thread_level = this.params.thread_level || 0;
|
||||
// datasets
|
||||
this.ds = new session.web.DataSet(this, this.view.model);
|
||||
this.ds_users = new session.web.DataSet(this, 'res.users');
|
||||
|
@ -520,12 +522,8 @@ openerp.mail = function(session) {
|
|||
// create and render Thread widget
|
||||
this.$element.find('div.oe_mail_recthread_left').empty();
|
||||
if (this.thread) this.thread.destroy();
|
||||
// hack: for groups and users
|
||||
if (this.view.model == 'mail.group') thread_level = 1;
|
||||
if (this.view.model == 'res.users') thread_level = 1;
|
||||
else thread_level = 0;
|
||||
this.thread = new mail.Thread(this, {'res_model': this.view.model, 'res_id': this.view.datarecord.id, 'uid': this.session.uid,
|
||||
'thread_level': thread_level, 'show_post_comment': true, 'limit': 15});
|
||||
'thread_level': this.params.thread_level, 'show_post_comment': true, 'limit': 15});
|
||||
var thread_done = this.thread.appendTo(this.$element.find('div.oe_mail_recthread_left'));
|
||||
return fetch_sub_done && thread_done;
|
||||
},
|
||||
|
|
|
@ -189,7 +189,6 @@
|
|||
<field name="campaign_id"/>
|
||||
<field name="date_run"/>
|
||||
<field name="sync_last_date"/>
|
||||
<button string="Synchronize Manually" states="running" name="synchroniz" icon="terp-project" type="object"/>
|
||||
<field name="state" />
|
||||
</tree>
|
||||
</field>
|
||||
|
|
|
@ -8,13 +8,13 @@ msgstr ""
|
|||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:49+0000\n"
|
||||
"PO-Revision-Date: 2012-05-31 06:17+0000\n"
|
||||
"PO-Revision-Date: 2012-06-02 04:49+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-06-01 05:32+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-03 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: mrp
|
||||
|
@ -387,9 +387,9 @@ msgid ""
|
|||
"sales person creates a sales order, he can relate it to several properties "
|
||||
"and OpenERP will automatically select the BoM to use according the needs."
|
||||
msgstr ""
|
||||
"同じ製品で異なった構築方法を持つ場合、OpenERPのプロパティは製品製造のための正しい部品表を選択するのに使用されます。それぞれの部品表には幾つかのプロ"
|
||||
"パティを割り当てることができます。販売員が販売オーダーを作成した時、彼はそれを幾つかのプロパティに関連付けることができ、そして、OpenERPは要求によっ"
|
||||
"て使用する部品表を自動的に選択します。"
|
||||
"同じ製品で異なった構築方法を持つ場合、OpenERPの属性は製品製造のための正しい部品表を選択するのに使用されます。それぞれの部品表には幾つかの属性を割り"
|
||||
"当てることができます。販売員が販売オーダーを作成した時、彼はそれを幾つかの属性に関連付けることができ、そして、OpenERPは要求によって使用する部品表を"
|
||||
"自動的に選択します。"
|
||||
|
||||
#. module: mrp
|
||||
#: help:mrp.production,picking_id:0
|
||||
|
@ -460,7 +460,7 @@ msgstr "会社名は固有でなければいけません。"
|
|||
msgid ""
|
||||
"Define specific property groups that can be assigned to the properties of "
|
||||
"your bill of materials."
|
||||
msgstr "部品表のプロパティに割り当てることができる特定のプロパティグループを定義して下さい。"
|
||||
msgstr "部品表の属性に割り当てることができる特定の属性グループを定義して下さい。"
|
||||
|
||||
#. module: mrp
|
||||
#: help:mrp.workcenter,costs_cycle:0
|
||||
|
@ -932,7 +932,7 @@ msgstr "時間数"
|
|||
#: view:mrp.property:0
|
||||
#: view:mrp.property.group:0
|
||||
msgid "Property Group"
|
||||
msgstr "プロパティグループ"
|
||||
msgstr "属性グループ"
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
|
@ -1601,7 +1601,7 @@ msgstr "承認"
|
|||
#. module: mrp
|
||||
#: view:mrp.property.group:0
|
||||
msgid "Properties categories"
|
||||
msgstr "プロパティの分類"
|
||||
msgstr "属性の分類"
|
||||
|
||||
#. module: mrp
|
||||
#: help:mrp.production.workcenter.line,sequence:0
|
||||
|
@ -2072,7 +2072,7 @@ msgstr "部品表"
|
|||
#: view:procurement.order:0
|
||||
#: field:procurement.order,property_ids:0
|
||||
msgid "Properties"
|
||||
msgstr "プロパティ"
|
||||
msgstr "属性"
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.routing.workcenter:0
|
||||
|
@ -2120,12 +2120,12 @@ msgstr "作業オーダー"
|
|||
#. module: mrp
|
||||
#: view:board.board:0
|
||||
msgid "Procurements in Exception"
|
||||
msgstr "例外の調達"
|
||||
msgstr "調達の例外"
|
||||
|
||||
#. module: mrp
|
||||
#: model:process.transition,name:mrp.process_transition_minimumstockprocure0
|
||||
msgid "'Minimum stock rule' material"
|
||||
msgstr "材料の最上在庫ルール"
|
||||
msgstr "材料の最小在庫ルール"
|
||||
|
||||
#. module: mrp
|
||||
#: model:ir.model,name:mrp.model_mrp_product_price
|
||||
|
@ -2190,7 +2190,7 @@ msgstr "次の生産オーダー"
|
|||
#: model:ir.actions.act_window,name:mrp.mrp_property_group_action
|
||||
#: model:ir.ui.menu,name:mrp.menu_mrp_property_group_action
|
||||
msgid "Property Groups"
|
||||
msgstr "プロパティグループ"
|
||||
msgstr "属性グループ"
|
||||
|
||||
#. module: mrp
|
||||
#: model:process.transition,note:mrp.process_transition_procurestockableproduct0
|
||||
|
|
|
@ -658,6 +658,8 @@
|
|||
icon="terp-accessories-archiver+"
|
||||
name="%(mrp.action_change_production_qty)d"
|
||||
string="Change Qty" states="ready,confirmed" />
|
||||
</group>
|
||||
<group colspan="4" col="4">
|
||||
<label string="" colspan="2"/>
|
||||
<field name="product_uos_qty" groups="product.group_uos"/>
|
||||
<field name="product_uos" groups="product.group_uos"/>
|
||||
|
@ -791,7 +793,7 @@
|
|||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -43,7 +43,7 @@ class procurement_order(osv.osv):
|
|||
cr.execute('update procurement_order set message=%s where id=%s', (_('No BoM defined for this product !'), procurement.id))
|
||||
for (id, name) in self.name_get(cr, uid, procurement.id):
|
||||
message = _("Procurement '%s' has an exception: 'No BoM defined for this product !'") % name
|
||||
self.log(cr, uid, id, message)
|
||||
self.message_append_note(cr, uid, [procurement.id], body=message, context=context)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -97,6 +97,7 @@ class procurement_order(osv.osv):
|
|||
})
|
||||
res[procurement.id] = produce_id
|
||||
self.write(cr, uid, [procurement.id], {'state': 'running'})
|
||||
self.running_send_note(cr, uid, ids, context=context)
|
||||
bom_result = production_obj.action_compute(cr, uid,
|
||||
[produce_id], properties=[x.id for x in procurement.property_ids])
|
||||
wf_service.trg_validate(uid, 'mrp.production', produce_id, 'button_confirm', cr)
|
||||
|
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-01 05:33+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: mrp_operations
|
||||
|
|
|
@ -57,10 +57,6 @@
|
|||
<field name="cycle"/>
|
||||
<field name="hour"/>
|
||||
<field name="state" />
|
||||
<button name="button_start_working" string="Start" states="draft" icon="terp-gtk-jump-to-ltr" help="Start Working"/>
|
||||
<button name="button_resume" string="Resume" states="pause" icon="gtk-media-pause" help="Resume Work Order"/>
|
||||
<button name="button_pause" string="Pending" states="startworking" icon="gtk-media-pause" help="Pause Work Order"/>
|
||||
<button name="button_done" string="Finished" states="startworking" icon="terp-check" help="Finish Order"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -121,7 +117,9 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-01 05:33+0000\n"
|
||||
"X-Launchpad-Export-Date: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: mrp_repair
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,407 @@
|
|||
# Japanese translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
|
||||
"PO-Revision-Date: 2012-06-01 23:22+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-06-02 05:35+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/share_wizard.py:51
|
||||
#, python-format
|
||||
msgid "Please select at least one user to share with"
|
||||
msgstr "共有するためには少なくとも1ユーザと共有して下さい。"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/share_wizard.py:55
|
||||
#, python-format
|
||||
msgid "Please select at least one group to share with"
|
||||
msgstr "共有するためには少なくとも1グループと共有して下さい。"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal,group_id:0
|
||||
msgid "Group"
|
||||
msgstr "グループ"
|
||||
|
||||
#. module: portal
|
||||
#: view:share.wizard:0
|
||||
#: field:share.wizard,group_ids:0
|
||||
msgid "Existing groups"
|
||||
msgstr "既存のグループ"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_res_portal_wizard_user
|
||||
msgid "Portal User Config"
|
||||
msgstr "ポータルユーザ設定"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard.user:0
|
||||
msgid "Portal User"
|
||||
msgstr "ポータルユーザ"
|
||||
|
||||
#. module: portal
|
||||
#: model:res.groups,comment:portal.group_portal_manager
|
||||
msgid ""
|
||||
"Portal managers have access to the portal definitions, and can easily "
|
||||
"configure the users, access rights and menus of portal users."
|
||||
msgstr "ポータルマネジャはポータル定義へアクセスして、ユーザ、アクセス権、ユーザのポータルメニューの設定を簡単にできます。"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,override_menu:0
|
||||
msgid "Enable this option to override the Menu Action of portal users"
|
||||
msgstr "ポータルユーザのメニューアクションを無効にするためにはこのオプションを有効にして下さい。"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.wizard.user,user_email:0
|
||||
msgid "E-mail"
|
||||
msgstr "Eメール"
|
||||
|
||||
#. module: portal
|
||||
#: constraint:res.users:0
|
||||
msgid "The chosen company is not in the allowed companies for this user"
|
||||
msgstr "選択した会社は、このユーザに許された会社ではありません。"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
#: field:res.portal,widget_ids:0
|
||||
msgid "Widgets"
|
||||
msgstr "ウィジェット"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard:0
|
||||
msgid "Send Invitations"
|
||||
msgstr "招待の送信"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
msgid "Widgets Assigned to Users"
|
||||
msgstr "ユーザ割当ウィジット"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,url:0
|
||||
msgid "The url where portal users can connect to the server"
|
||||
msgstr "ポータルユーザがサーバに接続できるURL"
|
||||
|
||||
#. module: portal
|
||||
#: model:res.groups,comment:portal.group_portal_officer
|
||||
msgid "Portal officers can create new portal users with the portal wizard."
|
||||
msgstr "ポータル役員はポータルウィザードを使って新しいポータルユーザを作成できます。"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal.wizard,message:0
|
||||
msgid "This text is included in the welcome email sent to the users"
|
||||
msgstr "このテキストはユーザに送信される歓迎Eメールに含まれます。"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,menu_action_id:0
|
||||
msgid "If set, replaces the standard menu for the portal's users"
|
||||
msgstr "セットした場合、ポータルユーザのための標準メニューを置き換えます。"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.wizard.user,lang:0
|
||||
msgid "Language"
|
||||
msgstr "言語"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
msgid "Portal Name"
|
||||
msgstr "ポータル名"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard.user:0
|
||||
msgid "Portal Users"
|
||||
msgstr "ポータルユーザ"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal,override_menu:0
|
||||
msgid "Override Menu Action of Users"
|
||||
msgstr "ユーザのメニューアクションの無効化"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal,menu_action_id:0
|
||||
msgid "Menu Action"
|
||||
msgstr "メニューアクション"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.wizard.user,name:0
|
||||
msgid "User Name"
|
||||
msgstr "ユーザ名"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,group_id:0
|
||||
msgid "The group corresponding to this portal"
|
||||
msgstr "このポータルに対応するグループ"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_res_portal_widget
|
||||
msgid "Portal Widgets"
|
||||
msgstr "ポータルウィジット"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_res_portal
|
||||
#: model:ir.module.category,name:portal.module_category_portal
|
||||
#: view:res.portal:0
|
||||
#: field:res.portal.widget,portal_id:0
|
||||
#: field:res.portal.wizard,portal_id:0
|
||||
msgid "Portal"
|
||||
msgstr "ポータル"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/portal_wizard.py:35
|
||||
#, python-format
|
||||
msgid "Your OpenERP account at %(company)s"
|
||||
msgstr "%(company)s 上のあなたのOpenERPアカウント"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/portal.py:107
|
||||
#: code:addons/portal/portal.py:184
|
||||
#, python-format
|
||||
msgid "%s Menu"
|
||||
msgstr "%s メニュー"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal.wizard,portal_id:0
|
||||
msgid "The portal in which new users must be added"
|
||||
msgstr "新しいユーザを追加すべきポータル"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_res_portal_wizard
|
||||
msgid "Portal Wizard"
|
||||
msgstr "ポータルウィザード"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,widget_ids:0
|
||||
msgid "Widgets assigned to portal users"
|
||||
msgstr "ポータルユーザ割当ウィザード"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/portal_wizard.py:163
|
||||
#, python-format
|
||||
msgid "(missing url)"
|
||||
msgstr "(不足しているURL)"
|
||||
|
||||
#. module: portal
|
||||
#: view:share.wizard:0
|
||||
#: field:share.wizard,user_ids:0
|
||||
msgid "Existing users"
|
||||
msgstr "既存ユーザ"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.wizard.user,wizard_id:0
|
||||
msgid "Wizard"
|
||||
msgstr "ウィザード"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal.wizard.user,user_email:0
|
||||
msgid ""
|
||||
"Will be used as user login. Also necessary to send the account information "
|
||||
"to new users"
|
||||
msgstr "ユーザログインとして使用されます。新しいユーザへのアカウント情報を送信するためにも必要です。"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal,parent_menu_id:0
|
||||
msgid "Parent Menu"
|
||||
msgstr "親メニュー"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal,url:0
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.widget,widget_id:0
|
||||
msgid "Widget"
|
||||
msgstr "ウィジット"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal.wizard.user,lang:0
|
||||
msgid "The language for the user's user interface"
|
||||
msgstr "ユーザのユーザインタフェースのための言語"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard:0
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
msgid "Website"
|
||||
msgstr "Webサイト"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
msgid "Create Parent Menu"
|
||||
msgstr "親メニュー作成"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard:0
|
||||
msgid ""
|
||||
"The following text will be included in the welcome email sent to users."
|
||||
msgstr "次のテキストはユーザに送信する歓迎Eメールに含まれます。"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/portal_wizard.py:135
|
||||
#, python-format
|
||||
msgid "Email required"
|
||||
msgstr "Eメールは必須"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_res_users
|
||||
msgid "res.users"
|
||||
msgstr ""
|
||||
|
||||
#. module: portal
|
||||
#: constraint:res.portal.wizard.user:0
|
||||
msgid "Invalid email address"
|
||||
msgstr "無効なEメールアドレスです。"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/portal_wizard.py:136
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You must have an email address in your User Preferences to send emails."
|
||||
msgstr "Eメール送信のためのユーザ設定の中にEメールアドレスを持つ必要があります。"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_ir_ui_menu
|
||||
msgid "ir.ui.menu"
|
||||
msgstr ""
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
#: view:res.portal.wizard:0
|
||||
#: field:res.portal.wizard,user_ids:0
|
||||
msgid "Users"
|
||||
msgstr "ユーザ"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.actions.act_window,name:portal.portal_list_action
|
||||
#: model:ir.ui.menu,name:portal.portal_list_menu
|
||||
#: model:ir.ui.menu,name:portal.portal_menu
|
||||
#: view:res.portal:0
|
||||
msgid "Portals"
|
||||
msgstr "ポータル"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal,parent_menu_id:0
|
||||
msgid "The menu action opens the submenus of this menu item"
|
||||
msgstr "メニューアクションはこのメニュー項目のサブメニューを開きます。"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.widget,sequence:0
|
||||
msgid "Sequence"
|
||||
msgstr "順序"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.users,partner_id:0
|
||||
msgid "Related Partner"
|
||||
msgstr "関連パートナ"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal:0
|
||||
msgid "Portal Menu"
|
||||
msgstr "ポータルメニュー"
|
||||
|
||||
#. module: portal
|
||||
#: sql_constraint:res.users:0
|
||||
msgid "You can not have two users with the same login !"
|
||||
msgstr "同じログインでは2つのユーザを持てません。"
|
||||
|
||||
#. module: portal
|
||||
#: view:res.portal.wizard:0
|
||||
#: field:res.portal.wizard,message:0
|
||||
msgid "Invitation message"
|
||||
msgstr "招待メッセージ"
|
||||
|
||||
#. module: portal
|
||||
#: code:addons/portal/wizard/portal_wizard.py:36
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Dear %(name)s,\n"
|
||||
"\n"
|
||||
"You have been created an OpenERP account at %(url)s.\n"
|
||||
"\n"
|
||||
"Your login account data is:\n"
|
||||
"Database: %(db)s\n"
|
||||
"User: %(login)s\n"
|
||||
"Password: %(password)s\n"
|
||||
"\n"
|
||||
"%(message)s\n"
|
||||
"\n"
|
||||
"--\n"
|
||||
"OpenERP - Open Source Business Applications\n"
|
||||
"http://www.openerp.com\n"
|
||||
msgstr ""
|
||||
"%(name)s 様、\n"
|
||||
"\n"
|
||||
"あなたのOpenERPアカウントは作成されました。%(url)s\n"
|
||||
"\n"
|
||||
"あなたのログイン情報は次のとおりです:\n"
|
||||
"データベース:%(db)s\n"
|
||||
"ユーザ:%(login)s\n"
|
||||
"パスワード:%(password)s\n"
|
||||
"\n"
|
||||
"%(message)s\n"
|
||||
"\n"
|
||||
"--\n"
|
||||
"OpenERP - Open Source Business Applications\n"
|
||||
"http://www.openerp.com\n"
|
||||
|
||||
#. module: portal
|
||||
#: model:res.groups,name:portal.group_portal_manager
|
||||
msgid "Manager"
|
||||
msgstr "マネジャ"
|
||||
|
||||
#. module: portal
|
||||
#: help:res.portal.wizard.user,name:0
|
||||
msgid "The user's real name"
|
||||
msgstr "ユーザの本名"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.actions.act_window,name:portal.address_wizard_action
|
||||
#: model:ir.actions.act_window,name:portal.partner_wizard_action
|
||||
#: view:res.portal.wizard:0
|
||||
msgid "Add Portal Access"
|
||||
msgstr "ポータルアクセスの追加"
|
||||
|
||||
#. module: portal
|
||||
#: field:res.portal.wizard.user,partner_id:0
|
||||
msgid "Partner"
|
||||
msgstr "パートナ"
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.actions.act_window,help:portal.portal_list_action
|
||||
msgid ""
|
||||
"\n"
|
||||
"A portal helps defining specific views and rules for a group of users (the\n"
|
||||
"portal group). A portal menu, widgets and specific groups may be assigned "
|
||||
"to\n"
|
||||
"the portal's users.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"ポータルはユーザのグループ(ポータルグループ)のために特定のビューやルールの\n"
|
||||
"定義ができます。ポータルメニュー、ウィジット、特定のグループはポータルユーザに\n"
|
||||
"割り当てることができます。\n"
|
||||
" "
|
||||
|
||||
#. module: portal
|
||||
#: model:ir.model,name:portal.model_share_wizard
|
||||
msgid "Share Wizard"
|
||||
msgstr "共有ウィザード"
|
||||
|
||||
#. module: portal
|
||||
#: model:res.groups,name:portal.group_portal_officer
|
||||
msgid "Officer"
|
||||
msgstr "役員"
|
|
@ -0,0 +1,313 @@
|
|||
# Japanese translation for openobject-addons
|
||||
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-02-08 00:36+0000\n"
|
||||
"PO-Revision-Date: 2012-06-01 23:37+0000\n"
|
||||
"Last-Translator: Akira Hiyama <Unknown>\n"
|
||||
"Language-Team: Japanese <ja@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: 2012-06-03 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 15342)\n"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.model,name:process.model_process_node
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Process Node"
|
||||
msgstr "処理ノード"
|
||||
|
||||
#. module: process
|
||||
#: help:process.process,active:0
|
||||
msgid ""
|
||||
"If the active field is set to False, it will allow you to hide the process "
|
||||
"without removing it."
|
||||
msgstr "アクティブ項目にFalseを設定すると、処理を削除することなく非表示にできます。"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,menu_id:0
|
||||
msgid "Related Menu"
|
||||
msgstr "関連メニュー"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition,action_ids:0
|
||||
msgid "Buttons"
|
||||
msgstr "ボタン"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Group By..."
|
||||
msgstr "グループ化…"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.node,kind:0
|
||||
msgid "State"
|
||||
msgstr "状態"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
msgid "Kind Of Node"
|
||||
msgstr "ノードの種類"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,help_url:0
|
||||
msgid "Help URL"
|
||||
msgstr "ヘルプURL"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.actions.act_window,name:process.action_process_node_form
|
||||
#: model:ir.ui.menu,name:process.menu_process_node_form
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Process Nodes"
|
||||
msgstr "処理ノード"
|
||||
|
||||
#. module: process
|
||||
#: view:process.process:0
|
||||
#: field:process.process,node_ids:0
|
||||
msgid "Nodes"
|
||||
msgstr "ノード"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: field:process.node,condition_ids:0
|
||||
#: view:process.process:0
|
||||
msgid "Conditions"
|
||||
msgstr "条件"
|
||||
|
||||
#. module: process
|
||||
#: view:process.transition:0
|
||||
msgid "Search Process Transition"
|
||||
msgstr "処理遷移の検索"
|
||||
|
||||
#. module: process
|
||||
#: field:process.condition,node_id:0
|
||||
msgid "Node"
|
||||
msgstr "ノード"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.transition.action,state:0
|
||||
msgid "Workflow Trigger"
|
||||
msgstr "ワークフロートリガー"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition,note:0
|
||||
msgid "Description"
|
||||
msgstr "説明"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.model,name:process.model_process_transition_action
|
||||
msgid "Process Transitions Actions"
|
||||
msgstr "処理遷移アクション"
|
||||
|
||||
#. module: process
|
||||
#: field:process.condition,model_id:0
|
||||
#: view:process.node:0
|
||||
#: field:process.node,model_id:0
|
||||
#: view:process.process:0
|
||||
#: field:process.process,model_id:0
|
||||
msgid "Object"
|
||||
msgstr "オブジェクト"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition,source_node_id:0
|
||||
msgid "Source Node"
|
||||
msgstr "元ノード"
|
||||
|
||||
#. module: process
|
||||
#: view:process.transition:0
|
||||
#: field:process.transition,transition_ids:0
|
||||
msgid "Workflow Transitions"
|
||||
msgstr "ワークフロー遷移"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition.action,action:0
|
||||
msgid "Action ID"
|
||||
msgstr "アクションID"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.model,name:process.model_process_transition
|
||||
#: view:process.transition:0
|
||||
msgid "Process Transition"
|
||||
msgstr "処理遷移"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.model,name:process.model_process_condition
|
||||
msgid "Condition"
|
||||
msgstr "条件"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.transition.action,state:0
|
||||
msgid "Dummy"
|
||||
msgstr "ダミー"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.actions.act_window,name:process.action_process_form
|
||||
#: model:ir.ui.menu,name:process.menu_process_form
|
||||
msgid "Processes"
|
||||
msgstr "処理"
|
||||
|
||||
#. module: process
|
||||
#: field:process.condition,name:0
|
||||
#: field:process.node,name:0
|
||||
#: field:process.process,name:0
|
||||
#: field:process.transition,name:0
|
||||
#: field:process.transition.action,name:0
|
||||
msgid "Name"
|
||||
msgstr "名前"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,transition_in:0
|
||||
msgid "Starting Transitions"
|
||||
msgstr "遷移の始点"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: field:process.node,note:0
|
||||
#: view:process.process:0
|
||||
#: field:process.process,note:0
|
||||
#: view:process.transition:0
|
||||
msgid "Notes"
|
||||
msgstr "注記"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition.action,transition_id:0
|
||||
msgid "Transition"
|
||||
msgstr "遷移"
|
||||
|
||||
#. module: process
|
||||
#: view:process.process:0
|
||||
msgid "Search Process"
|
||||
msgstr "処理検索"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.node,kind:0
|
||||
#: field:process.node,subflow_id:0
|
||||
msgid "Subflow"
|
||||
msgstr "サブフロー"
|
||||
|
||||
#. module: process
|
||||
#: field:process.process,active:0
|
||||
msgid "Active"
|
||||
msgstr "アクティブ"
|
||||
|
||||
#. module: process
|
||||
#: view:process.transition:0
|
||||
msgid "Associated Groups"
|
||||
msgstr "関連グループ"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,model_states:0
|
||||
msgid "States Expression"
|
||||
msgstr "状態式"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.transition.action,state:0
|
||||
msgid "Action"
|
||||
msgstr "アクション"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,flow_start:0
|
||||
msgid "Starting Flow"
|
||||
msgstr "開始フロー"
|
||||
|
||||
#. module: process
|
||||
#: field:process.condition,model_states:0
|
||||
msgid "Expression"
|
||||
msgstr "式"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition,group_ids:0
|
||||
msgid "Required Groups"
|
||||
msgstr "グループは必須"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Incoming Transitions"
|
||||
msgstr "内向き遷移"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition.action,state:0
|
||||
msgid "Type"
|
||||
msgstr "タイプ"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,transition_out:0
|
||||
msgid "Ending Transitions"
|
||||
msgstr "遷移の終点"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.model,name:process.model_process_process
|
||||
#: field:process.node,process_id:0
|
||||
#: view:process.process:0
|
||||
msgid "Process"
|
||||
msgstr "処理"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
msgid "Search ProcessNode"
|
||||
msgstr "処理ノード検索"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Other Conditions"
|
||||
msgstr "他の条件"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.ui.menu,name:process.menu_process
|
||||
msgid "Enterprise Process"
|
||||
msgstr "企業の処理"
|
||||
|
||||
#. module: process
|
||||
#: view:process.transition:0
|
||||
msgid "Actions"
|
||||
msgstr "アクション"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Properties"
|
||||
msgstr "属性"
|
||||
|
||||
#. module: process
|
||||
#: model:ir.actions.act_window,name:process.action_process_transition_form
|
||||
#: model:ir.ui.menu,name:process.menu_process_transition_form
|
||||
msgid "Process Transitions"
|
||||
msgstr "処理遷移"
|
||||
|
||||
#. module: process
|
||||
#: field:process.transition,target_node_id:0
|
||||
msgid "Target Node"
|
||||
msgstr "対象ノード"
|
||||
|
||||
#. module: process
|
||||
#: field:process.node,kind:0
|
||||
msgid "Kind of Node"
|
||||
msgstr "ノードの種類"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Outgoing Transitions"
|
||||
msgstr "外向き遷移"
|
||||
|
||||
#. module: process
|
||||
#: view:process.node:0
|
||||
#: view:process.process:0
|
||||
msgid "Transitions"
|
||||
msgstr "遷移"
|
||||
|
||||
#. module: process
|
||||
#: selection:process.transition.action,state:0
|
||||
msgid "Object Method"
|
||||
msgstr "オブジェクトメソッド"
|
File diff suppressed because it is too large
Load Diff
|
@ -81,6 +81,7 @@ class procurement_order(osv.osv):
|
|||
_name = "procurement.order"
|
||||
_description = "Procurement"
|
||||
_order = 'priority,date_planned desc'
|
||||
_inherit = ['mail.thread']
|
||||
_log_create = False
|
||||
_columns = {
|
||||
'name': fields.char('Reason', size=64, required=True, help='Procurement name.'),
|
||||
|
@ -103,7 +104,7 @@ class procurement_order(osv.osv):
|
|||
" a make to order method."),
|
||||
|
||||
'note': fields.text('Note'),
|
||||
'message': fields.char('Latest error', size=64, help="Exception occurred while computing procurement orders."),
|
||||
'message': fields.char('Latest error', size=124, help="Exception occurred while computing procurement orders."),
|
||||
'state': fields.selection([
|
||||
('draft','Draft'),
|
||||
('cancel','Cancelled'),
|
||||
|
@ -276,7 +277,7 @@ class procurement_order(osv.osv):
|
|||
if not res:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def check_buy(self, cr, uid, ids):
|
||||
""" Checks product type.
|
||||
@return: True or Product Id.
|
||||
|
@ -287,24 +288,26 @@ class procurement_order(osv.osv):
|
|||
if procurement.product_id.product_tmpl_id.supply_method <> 'buy':
|
||||
return False
|
||||
if not procurement.product_id.seller_ids:
|
||||
cr.execute('update procurement_order set message=%s where id=%s',
|
||||
(_('No supplier defined for this product !'), procurement.id))
|
||||
message = _('No supplier defined for this product !')
|
||||
self.message_append_note(cr, uid, [procurement.id], body=message)
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
|
||||
return False
|
||||
partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement.
|
||||
|
||||
if not partner:
|
||||
cr.execute('update procurement_order set message=%s where id=%s',
|
||||
(_('No default supplier defined for this product'), procurement.id))
|
||||
message = _('No default supplier defined for this product')
|
||||
self.message_append_note(cr, uid, [procurement.id], body=message)
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
|
||||
return False
|
||||
|
||||
if user.company_id and user.company_id.partner_id:
|
||||
if partner.id == user.company_id.partner_id.id:
|
||||
return False
|
||||
|
||||
address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery']
|
||||
if not address_id:
|
||||
cr.execute('update procurement_order set message=%s where id=%s',
|
||||
(_('No address defined for the supplier'), procurement.id))
|
||||
message = _('No address defined for the supplier')
|
||||
self.message_append_note(cr, uid, [procurement.id], body=message)
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -346,14 +349,18 @@ class procurement_order(osv.osv):
|
|||
move_obj.action_confirm(cr, uid, [id], context=context)
|
||||
self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
|
||||
self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
|
||||
self.confirm_send_note(cr, uid, ids, context)
|
||||
return True
|
||||
|
||||
def action_move_assigned(self, cr, uid, ids, context=None):
|
||||
""" Changes procurement state to Running and writes message.
|
||||
@return: True
|
||||
"""
|
||||
message = _('From stock: products assigned.')
|
||||
self.write(cr, uid, ids, {'state': 'running',
|
||||
'message': _('from stock: products assigned.')})
|
||||
'message': message}, context=context)
|
||||
self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
self.running_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def _check_make_to_stock_service(self, cr, uid, procurement, context=None):
|
||||
|
@ -383,8 +390,9 @@ class procurement_order(osv.osv):
|
|||
message = _("Not enough stock.")
|
||||
|
||||
if message:
|
||||
self.log(cr, uid, procurement.id, _("Procurement '%s' is in exception: ") % (procurement.name) + message)
|
||||
message = _("Procurement '%s' is in exception: ") % (procurement.name) + message
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
|
||||
self.message_append_note(cr, uid, [procurement.id], body=message, context=context)
|
||||
return ok
|
||||
|
||||
def action_produce_assign_service(self, cr, uid, ids, context=None):
|
||||
|
@ -393,6 +401,7 @@ class procurement_order(osv.osv):
|
|||
"""
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
self.write(cr, uid, [procurement.id], {'state': 'running'})
|
||||
self.running_send_note(cr, uid, ids, context=None)
|
||||
return True
|
||||
|
||||
def action_produce_assign_product(self, cr, uid, ids, context=None):
|
||||
|
@ -427,6 +436,7 @@ class procurement_order(osv.osv):
|
|||
if len(todo):
|
||||
move_obj.write(cr, uid, todo, {'state': 'assigned'})
|
||||
self.write(cr, uid, ids, {'state': 'cancel'})
|
||||
self.cancel_send_note(cr, uid, ids, context=None)
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
for id in ids:
|
||||
wf_service.trg_trigger(uid, 'procurement.order', id, cr)
|
||||
|
@ -451,6 +461,7 @@ class procurement_order(osv.osv):
|
|||
@return: True
|
||||
"""
|
||||
res = self.write(cr, uid, ids, {'state': 'ready'})
|
||||
self.ready_send_note(cr, uid, ids, context=None)
|
||||
return res
|
||||
|
||||
def action_done(self, cr, uid, ids):
|
||||
|
@ -463,11 +474,39 @@ class procurement_order(osv.osv):
|
|||
if procurement.close_move and (procurement.move_id.state <> 'done'):
|
||||
move_obj.action_done(cr, uid, [procurement.move_id.id])
|
||||
res = self.write(cr, uid, ids, {'state': 'done', 'date_close': time.strftime('%Y-%m-%d')})
|
||||
self.done_send_note(cr, uid, ids, context=None)
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
for id in ids:
|
||||
wf_service.trg_trigger(uid, 'procurement.order', id, cr)
|
||||
return res
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
obj_id = super(procurement_order, self).create(cr, uid, vals, context)
|
||||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been <b>created</b>."), context=context)
|
||||
|
||||
def confirm_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been <b>confirmed</b>."), context=context)
|
||||
|
||||
def running_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been set to <b>running</b>."), context=context)
|
||||
|
||||
def ready_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been set to <b>ready</b>."), context=context)
|
||||
|
||||
def cancel_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been <b>cancelled</b>."), context=context)
|
||||
|
||||
def done_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Procurement has been <b>done</b>."), context=context)
|
||||
|
||||
procurement_order()
|
||||
|
||||
class StockPicking(osv.osv):
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -19,15 +19,15 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import netsvc
|
||||
import pooler
|
||||
from osv import osv
|
||||
from osv import fields
|
||||
from tools.translate import _
|
||||
from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
|
||||
import tools
|
||||
import netsvc
|
||||
import pooler
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
_inherit = 'procurement.order'
|
||||
|
@ -69,7 +69,7 @@ class procurement_order(osv.osv):
|
|||
cr.commit()
|
||||
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
|
||||
maxdate = (datetime.today() + relativedelta(days=company.schedule_range)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||
start_date = time.strftime('%Y-%m-%d, %Hh %Mm %Ss')
|
||||
start_date = fields.datetime.now()
|
||||
offset = 0
|
||||
report = []
|
||||
report_total = 0
|
||||
|
@ -113,13 +113,14 @@ class procurement_order(osv.osv):
|
|||
proc.product_id.name,))
|
||||
report_except += 1
|
||||
|
||||
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
offset += len(ids)
|
||||
if not ids: break
|
||||
end_date = time.strftime('%Y-%m-%d, %Hh %Mm %Ss')
|
||||
end_date = fields.datetime.now()
|
||||
if uid:
|
||||
request = self.pool.get('res.request')
|
||||
# Chatter: old res.request is now a chatter on res.users, id=uid
|
||||
summary = _("""Here is the procurement scheduling report.
|
||||
|
||||
Start Time: %s
|
||||
|
@ -130,12 +131,7 @@ class procurement_order(osv.osv):
|
|||
|
||||
Exceptions:\n""") % (start_date, end_date, report_total, report_except, report_later)
|
||||
summary += '\n'.join(report)
|
||||
request.create(cr, uid,
|
||||
{'name': "Procurement Processing Report.",
|
||||
'act_from': uid,
|
||||
'act_to': uid,
|
||||
'body': summary,
|
||||
})
|
||||
self.pool.get('res.users').message_append_note(cr, uid, [uid], body=summary, context=context)
|
||||
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
|
@ -237,7 +233,6 @@ class procurement_order(osv.osv):
|
|||
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
|
||||
location_obj = self.pool.get('stock.location')
|
||||
procurement_obj = self.pool.get('procurement.order')
|
||||
request_obj = self.pool.get('res.request')
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
report = []
|
||||
offset = 0
|
||||
|
@ -293,12 +288,8 @@ class procurement_order(osv.osv):
|
|||
if use_new_cursor:
|
||||
cr.commit()
|
||||
if user_id and report:
|
||||
request_obj.create(cr, uid, {
|
||||
'name': 'Orderpoint report.',
|
||||
'act_from': user_id,
|
||||
'act_to': user_id,
|
||||
'body': '\n'.join(report)
|
||||
})
|
||||
# Chatter: old res.request is now a chatter on res.users, id=uid
|
||||
self.pool.get('res.users').message_append_note(cr, uid, [user_id], body='\n'.join(report), subject=_('Orderpoint report'), context=context)
|
||||
if use_new_cursor:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -68,7 +68,7 @@
|
|||
<field name="type">form</field>
|
||||
<field eval="7" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Product">
|
||||
<form string="Product" layout="auto">
|
||||
<group colspan="4" col="8">
|
||||
<group colspan="4" col="2">
|
||||
<separator string="Name" colspan="2"/>
|
||||
|
@ -190,7 +190,9 @@
|
|||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"category": "Project Management",
|
||||
"sequence": 8,
|
||||
"images": ["images/gantt.png", "images/project_dashboard.jpeg","images/project_task_tree.jpeg","images/project_task.jpeg","images/project.jpeg","images/task_analysis.jpeg"],
|
||||
"depends": ["base_setup", "product", "analytic", "board", "mail", "resource","web_kanban"],
|
||||
"depends": ["base_setup", "base_status", "product", "analytic", "board", "mail", "resource","web_kanban"],
|
||||
"description": """
|
||||
Project management module tracks multi-level projects, tasks, work done on tasks, eso.
|
||||
======================================================================================
|
||||
|
|
|
@ -17,11 +17,8 @@
|
|||
<field name="planned_hours" widget="float_time"/>
|
||||
<field name="effective_hours" widget="float_time"/>
|
||||
<field name="progress" widget="progressbar"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/>
|
||||
<button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="gtk-sort-descending" help="For changing to delegate state"/>
|
||||
<button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/>
|
||||
<field name="stage_id" invisible="context.get('set_visible',False)"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -39,10 +36,8 @@
|
|||
<field name="date_deadline"/>
|
||||
<field name="total_hours" widget="float_time"/>
|
||||
<field name="progress" widget="progressbar"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/>
|
||||
<button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="action_close" states="draft,pending,open" string="Done" type="object" icon="gtk-apply" help="For changing to done state"/>
|
||||
<field name="stage_id" invisible="context.get('set_visible',False)"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
# Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,18 +19,15 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from lxml import etree
|
||||
import time
|
||||
from base_status.base_stage import base_stage
|
||||
from datetime import datetime, date
|
||||
|
||||
from tools.translate import _
|
||||
from lxml import etree
|
||||
from osv import fields, osv
|
||||
from openerp.addons.resource.faces import task as Task
|
||||
import time
|
||||
from tools.translate import _
|
||||
|
||||
# I think we can remove this in v6.1 since VMT's improvements in the framework ?
|
||||
#class project_project(osv.osv):
|
||||
# _name = 'project.project'
|
||||
#project_project()
|
||||
_TASK_STATE = [('draft', 'New'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done'), ('cancelled', 'Cancelled')]
|
||||
|
||||
class project_task_type(osv.osv):
|
||||
_name = 'project.task.type'
|
||||
|
@ -40,14 +37,20 @@ class project_task_type(osv.osv):
|
|||
'name': fields.char('Stage Name', required=True, size=64, translate=True),
|
||||
'description': fields.text('Description'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'project_default': fields.boolean('Common to All Projects', help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
|
||||
'case_default': fields.boolean('Common to All Projects',
|
||||
help="If you check this field, this stage will be proposed by default on each new project. It will not assign this stage to existing projects."),
|
||||
'project_ids': fields.many2many('project.project', 'project_task_type_rel', 'type_id', 'project_id', 'Projects'),
|
||||
'state': fields.selection(_TASK_STATE, 'State', required=True,
|
||||
help="The related state for the stage. The state of your document will automatically change regarding the selected stage. Example, a stage is related to the state 'Close', when your document reach this stage, it will be automatically closed."),
|
||||
'fold': fields.boolean('Hide in views if empty',
|
||||
help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
|
||||
}
|
||||
_defaults = {
|
||||
'sequence': 1
|
||||
'sequence': 1,
|
||||
'state': 'draft',
|
||||
'fold': False,
|
||||
}
|
||||
_order = 'sequence'
|
||||
project_task_type()
|
||||
|
||||
class project(osv.osv):
|
||||
_name = "project.project"
|
||||
|
@ -208,7 +211,7 @@ class project(osv.osv):
|
|||
return True
|
||||
|
||||
def _get_type_common(self, cr, uid, context):
|
||||
ids = self.pool.get('project.task.type').search(cr, uid, [('project_default','=',1)], context=context)
|
||||
ids = self.pool.get('project.task.type').search(cr, uid, [('case_default','=',1)], context=context)
|
||||
return ids
|
||||
|
||||
_order = "sequence"
|
||||
|
@ -239,7 +242,7 @@ class project(osv.osv):
|
|||
def set_done(self, cr, uid, ids, context=None):
|
||||
task_obj = self.pool.get('project.task')
|
||||
task_ids = task_obj.search(cr, uid, [('project_id', 'in', ids), ('state', 'not in', ('cancelled', 'done'))])
|
||||
task_obj.write(cr, uid, task_ids, {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
|
||||
task_obj.case_close(cr, uid, task_ids, context=context)
|
||||
self.write(cr, uid, ids, {'state':'close'}, context=context)
|
||||
self.set_close_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
@ -247,7 +250,7 @@ class project(osv.osv):
|
|||
def set_cancel(self, cr, uid, ids, context=None):
|
||||
task_obj = self.pool.get('project.task')
|
||||
task_ids = task_obj.search(cr, uid, [('project_id', 'in', ids), ('state', '!=', 'done')])
|
||||
task_obj.write(cr, uid, task_ids, {'state': 'cancelled', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
|
||||
task_obj.case_cancel(cr, uid, task_ids, context=context)
|
||||
self.write(cr, uid, ids, {'state':'cancelled'}, context=context)
|
||||
self.set_cancel_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
@ -501,49 +504,60 @@ def Project():
|
|||
def set_close_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Project has been <b>closed</b>.")
|
||||
return self.message_append_note(cr, uid, ids, body=message, context=context)
|
||||
|
||||
project()
|
||||
|
||||
class task(osv.osv):
|
||||
|
||||
class task(base_stage, osv.osv):
|
||||
_name = "project.task"
|
||||
_description = "Task"
|
||||
_log_create = True
|
||||
_date_name = "date_start"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
|
||||
def _get_default_project_id(self, cr, uid, context=None):
|
||||
""" Gives default section by checking if present in the context """
|
||||
return (self._resolve_project_id_from_context(cr, uid, context=context) or False)
|
||||
|
||||
def _get_default_stage_id(self, cr, uid, context=None):
|
||||
""" Gives default stage_id """
|
||||
project_id = self._get_default_project_id(cr, uid, context=context)
|
||||
return self.stage_find(cr, uid, [], project_id, [('state', '=', 'draft')], context=context)
|
||||
|
||||
def _resolve_project_id_from_context(self, cr, uid, context=None):
|
||||
"""Return ID of project based on the value of 'project_id'
|
||||
context key, or None if it cannot be resolved to a single project.
|
||||
""" Returns ID of project based on the value of 'default_project_id'
|
||||
context key, or None if it cannot be resolved to a single
|
||||
project.
|
||||
"""
|
||||
if context is None: context = {}
|
||||
if type(context.get('default_project_id')) in (int, long):
|
||||
project_id = context['default_project_id']
|
||||
return project_id
|
||||
return context['default_project_id']
|
||||
if isinstance(context.get('default_project_id'), basestring):
|
||||
project_name = context['default_project_id']
|
||||
project_ids = self.pool.get('project.project').name_search(cr, uid, name=project_name)
|
||||
project_ids = self.pool.get('project.project').name_search(cr, uid, name=project_name, context=context)
|
||||
if len(project_ids) == 1:
|
||||
return project_ids[0][0]
|
||||
return None
|
||||
|
||||
def _read_group_type_id(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
stage_obj = self.pool.get('project.task.type')
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
order = stage_obj._order
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
if read_group_order == 'type_id desc':
|
||||
# lame way to allow reverting search, should just work in the trivial case
|
||||
# lame way to allow reverting search, should just work in the trivial case
|
||||
if read_group_order == 'stage_id desc':
|
||||
order = '%s desc' % order
|
||||
# retrieve section_id from the context and write the domain
|
||||
# - ('id', 'in', 'ids'): add columns that should be present
|
||||
# - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
|
||||
# - OR ('project_ids', 'in', project_id), ('fold', '=', False) if project_id: add project columns that are not folded
|
||||
search_domain = []
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
if project_id:
|
||||
domain = ['|', ('id','in',ids), ('project_ids','in',project_id)]
|
||||
else:
|
||||
domain = ['|', ('id','in',ids), ('project_default','=',1)]
|
||||
stage_ids = stage_obj._search(cr, uid, domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
search_domain += ['|', '&', ('project_ids', '=', project_id), ('fold', '=', False)]
|
||||
search_domain += ['|', ('id', 'in', ids), '&', ('case_default', '=', True), ('fold', '=', False)]
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
|
||||
return result
|
||||
|
||||
|
||||
def _read_group_user_id(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
res_users = self.pool.get('res.users')
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
|
@ -562,11 +576,10 @@ class task(osv.osv):
|
|||
return result
|
||||
|
||||
_group_by_full = {
|
||||
'type_id': _read_group_type_id,
|
||||
'user_id': _read_group_user_id
|
||||
'stage_id': _read_group_stage_ids,
|
||||
'user_id': _read_group_user_id,
|
||||
}
|
||||
|
||||
|
||||
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
obj_project = self.pool.get('project.project')
|
||||
for domain in args:
|
||||
|
@ -597,7 +610,6 @@ class task(osv.osv):
|
|||
res[task.id]['progress'] = 100.0
|
||||
return res
|
||||
|
||||
|
||||
def onchange_remaining(self, cr, uid, ids, remaining=0.0, planned = 0.0):
|
||||
if remaining and not planned:
|
||||
return {'value':{'planned_hours': remaining}}
|
||||
|
@ -640,7 +652,7 @@ class task(osv.osv):
|
|||
if not default.get('remaining_hours', False):
|
||||
default['remaining_hours'] = float(self.read(cr, uid, id, ['planned_hours'])['planned_hours'])
|
||||
default['active'] = True
|
||||
default['type_id'] = False
|
||||
default['stage_id'] = False
|
||||
if not default.get('name', False):
|
||||
default['name'] = self.browse(cr, uid, id, context=context).name or ''
|
||||
if not context.get('copy',False):
|
||||
|
@ -670,10 +682,15 @@ class task(osv.osv):
|
|||
'description': fields.text('Description'),
|
||||
'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True),
|
||||
'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."),
|
||||
'type_id': fields.many2one('project.task.type', 'Stage'),
|
||||
'state': fields.selection([('draft', 'New'),('cancelled', 'Cancelled'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done')], 'Status', readonly=True, required=True,
|
||||
help='If the task is created the state is \'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\'.'),
|
||||
'stage_id': fields.many2one('project.task.type', 'Stage',
|
||||
domain="['|', ('project_ids', '=', project_id), ('case_default', '=', True)]"),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=_TASK_STATE, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready To Pull')], 'Kanban State',
|
||||
help="A task's kanban state indicates special situations affecting it:\n"
|
||||
" * Normal is the default situation\n"
|
||||
|
@ -722,6 +739,8 @@ class task(osv.osv):
|
|||
}
|
||||
|
||||
_defaults = {
|
||||
'stage_id': _get_default_stage_id,
|
||||
'project_id': _get_default_project_id,
|
||||
'state': 'draft',
|
||||
'kanban_state': 'normal',
|
||||
'priority': '2',
|
||||
|
@ -729,7 +748,7 @@ class task(osv.osv):
|
|||
'sequence': 10,
|
||||
'active': True,
|
||||
'user_id': lambda obj, cr, uid, context: uid,
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c),
|
||||
}
|
||||
|
||||
_order = "priority, sequence, date_start, name, id"
|
||||
|
@ -828,6 +847,41 @@ class task(osv.osv):
|
|||
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
|
||||
return res
|
||||
|
||||
# ****************************************
|
||||
# Case management
|
||||
# ****************************************
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the lead:
|
||||
- section_id: if set, stages must belong to this section or
|
||||
be a default stage; if not set, stages must be default
|
||||
stages
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
section_ids = []
|
||||
if section_id:
|
||||
section_ids.append(section_id)
|
||||
for task in cases:
|
||||
if task.project_id:
|
||||
section_ids.append(task.project_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('project_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def _check_child_task(self, cr, uid, ids, context=None):
|
||||
if context == None:
|
||||
context = {}
|
||||
|
@ -840,9 +894,9 @@ class task(osv.osv):
|
|||
return True
|
||||
|
||||
def action_close(self, cr, uid, ids, context=None):
|
||||
# This action open wizard to send email to partner or project manager after close task.
|
||||
if context == None:
|
||||
context = {}
|
||||
""" This action closes the task, then opens the wizard to send an
|
||||
email to the partner or the project manager.
|
||||
"""
|
||||
task_id = len(ids) and ids[0] or False
|
||||
self._check_child_task(cr, uid, ids, context=context)
|
||||
if not task_id: return False
|
||||
|
@ -863,28 +917,17 @@ class task(osv.osv):
|
|||
}
|
||||
return res
|
||||
|
||||
def do_close(self, cr, uid, ids, context={}):
|
||||
"""
|
||||
Close Task
|
||||
"""
|
||||
def do_close(self, cr, uid, ids, context=None):
|
||||
""" Compatibility when changing to case_close. """
|
||||
return self.case_close(cr, uid, ids, context=context)
|
||||
|
||||
def case_close(self, cr, uid, ids, context=None):
|
||||
""" Closes Task """
|
||||
request = self.pool.get('res.request')
|
||||
if not isinstance(ids,list): ids = [ids]
|
||||
if not isinstance(ids, list): ids = [ids]
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
vals = {}
|
||||
project = task.project_id
|
||||
if project:
|
||||
# Send request to project manager
|
||||
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.user_id.id,
|
||||
'ref_partner_id': task.partner_id.id,
|
||||
'ref_doc1': 'project.task,%d'% (task.id,),
|
||||
'ref_doc2': 'project.project,%d'% (project.id,),
|
||||
}, context=context)
|
||||
|
||||
for parent_id in task.parent_ids:
|
||||
if parent_id.state in ('pending','draft'):
|
||||
reopen = True
|
||||
|
@ -893,71 +936,61 @@ class task(osv.osv):
|
|||
reopen = False
|
||||
if reopen:
|
||||
self.do_reopen(cr, uid, [parent_id.id], context=context)
|
||||
vals.update({'state': 'done'})
|
||||
vals.update({'remaining_hours': 0.0})
|
||||
# close task
|
||||
vals['remaining_hours'] = 0.0
|
||||
if not task.date_end:
|
||||
vals.update({ 'date_end':time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
self.write(cr, uid, [task.id],vals, context=context)
|
||||
self.do_close_send_note(cr, uid, [task.id], context)
|
||||
vals['date_end'] = fields.datetime.now()
|
||||
self.case_set(cr, uid, [task.id], 'done', vals, context=context)
|
||||
self.case_close_send_note(cr, uid, [task.id], context=context)
|
||||
return True
|
||||
|
||||
def do_reopen(self, cr, uid, ids, context=None):
|
||||
request = self.pool.get('res.request')
|
||||
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
project = task.project_id
|
||||
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.user_id.id,
|
||||
'ref_partner_id': task.partner_id.id,
|
||||
'ref_doc1': 'project.task,%d' % task.id,
|
||||
'ref_doc2': 'project.project,%d' % project.id,
|
||||
}, context=context)
|
||||
|
||||
self.write(cr, uid, [task.id], {'state': 'open'}, context=context)
|
||||
self.do_open_send_note(cr, uid, [task.id], context)
|
||||
self.case_set(cr, uid, [task.id], 'open', {}, context=context)
|
||||
self.case_open_send_note(cr, uid, [task.id], context)
|
||||
return True
|
||||
|
||||
def do_cancel(self, cr, uid, ids, context={}):
|
||||
def do_cancel(self, cr, uid, ids, context=None):
|
||||
""" Compatibility when changing to case_cancel. """
|
||||
return self.case_cancel(cr, uid, ids, context=context)
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
request = self.pool.get('res.request')
|
||||
tasks = self.browse(cr, uid, ids, context=context)
|
||||
self._check_child_task(cr, uid, ids, context=context)
|
||||
for task in tasks:
|
||||
project = task.project_id
|
||||
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.user_id.id,
|
||||
'ref_partner_id': task.partner_id.id,
|
||||
'ref_doc1': 'project.task,%d' % task.id,
|
||||
'ref_doc2': 'project.project,%d' % project.id,
|
||||
}, context=context)
|
||||
self.write(cr, uid, [task.id], {'state': 'cancelled', 'remaining_hours':0.0}, context=context)
|
||||
self.do_cancel_send_note(cr, uid, [task.id], context)
|
||||
self.case_set(cr, uid, [task.id], 'cancelled', {'remaining_hours': 0.0}, context=context)
|
||||
self.case_cancel_send_note(cr, uid, [task.id], context=context)
|
||||
return True
|
||||
|
||||
def do_open(self, cr, uid, ids, context={}):
|
||||
def do_open(self, cr, uid, ids, context=None):
|
||||
""" Compatibility when changing to case_open. """
|
||||
return self.case_open(cr, uid, ids, context=context)
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
if not isinstance(ids,list): ids = [ids]
|
||||
tasks= self.browse(cr, uid, ids, context=context)
|
||||
for t in tasks:
|
||||
data = {'state': 'open'}
|
||||
if not t.date_start:
|
||||
data['date_start'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
self.write(cr, uid, [t.id], data, context=context)
|
||||
self.do_open_send_note(cr, uid, [t.id], context)
|
||||
self.case_set(cr, uid, ids, 'open', {'date_start': fields.datetime.now()}, context=context)
|
||||
self.case_open_send_note(cr, uid, ids, context)
|
||||
return True
|
||||
|
||||
def do_draft(self, cr, uid, ids, context={}):
|
||||
self.write(cr, uid, ids, {'state': 'draft'}, context=context)
|
||||
self.do_draft_send_note(cr, uid, ids, context)
|
||||
def do_draft(self, cr, uid, ids, context=None):
|
||||
""" Compatibility when changing to case_draft. """
|
||||
return self.case_draft(cr, uid, ids, context=context)
|
||||
|
||||
def case_draft(self, cr, uid, ids, context=None):
|
||||
self.case_set(cr, uid, ids, 'draft', {}, context=context)
|
||||
self.case_draft_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
|
||||
def do_pending(self, cr, uid, ids, context=None):
|
||||
""" Compatibility when changing to case_pending. """
|
||||
return self.case_pending(cr, uid, ids, context=context)
|
||||
|
||||
def case_pending(self, cr, uid, ids, context=None):
|
||||
self.case_set(cr, uid, ids, 'pending', {}, context=context)
|
||||
return self.case_pending_send_note(cr, uid, ids, context=context)
|
||||
|
||||
def _delegate_task_attachments(self, cr, uid, task_id, delegated_task_id, context=None):
|
||||
attachment = self.pool.get('ir.attachment')
|
||||
attachment_ids = attachment.search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', task_id)], context=context)
|
||||
|
@ -966,7 +999,6 @@ class task(osv.osv):
|
|||
new_attachment_ids.append(attachment.copy(cr, uid, attachment_id, default={'res_id': delegated_task_id}, context=context))
|
||||
return new_attachment_ids
|
||||
|
||||
|
||||
def do_delegate(self, cr, uid, ids, delegate_data={}, context=None):
|
||||
"""
|
||||
Delegate Task to another users.
|
||||
|
@ -1000,11 +1032,6 @@ class task(osv.osv):
|
|||
delegated_tasks[task.id] = delegated_task_id
|
||||
return delegated_tasks
|
||||
|
||||
def do_pending(self, cr, uid, ids, context={}):
|
||||
self.write(cr, uid, ids, {'state': 'pending'}, context=context)
|
||||
self.do_pending_send_note(cr, uid, ids, context)
|
||||
return True
|
||||
|
||||
def set_remaining_time(self, cr, uid, ids, remaining_time=1.0, context=None):
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
if (task.state=='draft') or (task.planned_hours==0.0):
|
||||
|
@ -1033,36 +1060,6 @@ class task(osv.osv):
|
|||
def set_kanban_state_done(self, cr, uid, ids, context=None):
|
||||
self.write(cr, uid, ids, {'kanban_state': 'done'}, context=context)
|
||||
|
||||
def _change_type(self, cr, uid, ids, next, context=None):
|
||||
"""
|
||||
go to the next stage
|
||||
if next is False, go to previous stage
|
||||
"""
|
||||
for task in self.browse(cr, uid, ids):
|
||||
if task.project_id.type_ids:
|
||||
typeid = task.type_id.id
|
||||
types_seq={}
|
||||
for type in task.project_id.type_ids :
|
||||
types_seq[type.id] = type.sequence
|
||||
if next:
|
||||
types = sorted(types_seq.items(), lambda x, y: cmp(x[1], y[1]))
|
||||
else:
|
||||
types = sorted(types_seq.items(), lambda x, y: cmp(y[1], x[1]))
|
||||
sorted_types = [x[0] for x in types]
|
||||
if not typeid:
|
||||
self.write(cr, uid, task.id, {'type_id': sorted_types[0]})
|
||||
elif typeid and typeid in sorted_types and sorted_types.index(typeid) != len(sorted_types)-1:
|
||||
index = sorted_types.index(typeid)
|
||||
self.write(cr, uid, task.id, {'type_id': sorted_types[index+1]})
|
||||
self.state_change_send_note(cr, uid, [task.id], context)
|
||||
return True
|
||||
|
||||
def next_type(self, cr, uid, ids, context=None):
|
||||
return self._change_type(cr, uid, ids, True, context=context)
|
||||
|
||||
def prev_type(self, cr, uid, ids, context=None):
|
||||
return self._change_type(cr, uid, ids, False, context=context)
|
||||
|
||||
def _store_history(self, cr, uid, ids, context=None):
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
self.pool.get('project.task.history').create(cr, uid, {
|
||||
|
@ -1070,7 +1067,7 @@ class task(osv.osv):
|
|||
'remaining_hours': task.remaining_hours,
|
||||
'planned_hours': task.planned_hours,
|
||||
'kanban_state': task.kanban_state,
|
||||
'type_id': task.type_id.id,
|
||||
'type_id': task.stage_id.id,
|
||||
'state': task.state,
|
||||
'user_id': task.user_id.id
|
||||
|
||||
|
@ -1084,22 +1081,25 @@ class task(osv.osv):
|
|||
return task_id
|
||||
|
||||
# Overridden to reset the kanban_state to normal whenever
|
||||
# the stage (type_id) of the task changes.
|
||||
# the stage (stage_id) of the task changes.
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
if vals and not 'kanban_state' in vals and 'type_id' in vals:
|
||||
new_stage = vals.get('type_id')
|
||||
if vals and not 'kanban_state' in vals and 'stage_id' in vals:
|
||||
new_stage = vals.get('stage_id')
|
||||
vals_reset_kstate = dict(vals, kanban_state='normal')
|
||||
for t in self.browse(cr, uid, ids, context=context):
|
||||
write_vals = vals_reset_kstate if t.type_id != new_stage else vals
|
||||
#TO FIX:Kanban view doesn't raise warning
|
||||
#stages = [stage.id for stage in t.project_id.type_ids]
|
||||
#if new_stage not in stages:
|
||||
#raise osv.except_osv(_('Warning !'), _('Stage is not defined in the project.'))
|
||||
write_vals = vals_reset_kstate if t.stage_id != new_stage else vals
|
||||
super(task,self).write(cr, uid, [t.id], write_vals, context=context)
|
||||
result = True
|
||||
else:
|
||||
result = super(task,self).write(cr, uid, ids, vals, context=context)
|
||||
if ('type_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals):
|
||||
if ('stage_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals):
|
||||
self._store_history(cr, uid, ids, context=context)
|
||||
self.state_change_send_note(cr, uid, ids, context)
|
||||
return result
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
|
@ -1139,7 +1139,11 @@ class task(osv.osv):
|
|||
# ---------------------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ---------------------------------------------------
|
||||
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
""" Override of default prefix for notifications. """
|
||||
return 'Task'
|
||||
|
||||
def get_needaction_user_ids(self, cr, uid, ids, context=None):
|
||||
result = dict.fromkeys(ids, [])
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -1156,28 +1160,16 @@ class task(osv.osv):
|
|||
sub_ids.append(obj.manager_id.id)
|
||||
return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_append_note(cr, uid, ids, body=_("Task has been <b>created</b>."), context=context)
|
||||
|
||||
def do_pending_send_note(self, cr, uid, ids, context=None):
|
||||
if not isinstance(ids,list): ids = [ids]
|
||||
msg = _('Task is now <b>pending</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def do_open_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Task has been <b>opened</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def do_cancel_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Task has been <b>canceled</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def do_close_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Task has been <b>closed</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def do_draft_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Task has been <b>renewed</b>.')
|
||||
def case_draft_send_note(self, cr, uid, ids, context=None):
|
||||
msg = _('Task has been set as <b>draft</b>.')
|
||||
return self.message_append_note(cr, uid, ids, body=msg, context=context)
|
||||
|
||||
def do_delegation_send_note(self, cr, uid, ids, context=None):
|
||||
|
@ -1186,13 +1178,6 @@ class task(osv.osv):
|
|||
self.message_append_note(cr, uid, [task.id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
def state_change_send_note(self, cr, uid, ids, context=None):
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
msg = _('Stage changed to <b>%s</b>') % (task.type_id.name)
|
||||
self.message_append_note(cr, uid, [task.id], body=msg, context=context)
|
||||
return True
|
||||
|
||||
task()
|
||||
|
||||
class project_work(osv.osv):
|
||||
_name = "project.task.work"
|
||||
|
@ -1231,7 +1216,7 @@ class project_work(osv.osv):
|
|||
for work in self.browse(cr, uid, ids):
|
||||
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
|
||||
return super(project_work,self).unlink(cr, uid, ids,*args, **kwargs)
|
||||
project_work()
|
||||
|
||||
|
||||
class account_analytic_account(osv.osv):
|
||||
|
||||
|
@ -1252,7 +1237,6 @@ class account_analytic_account(osv.osv):
|
|||
raise osv.except_osv(_('Warning !'), _('Please delete the project linked with this account first.'))
|
||||
return super(account_analytic_account, self).unlink(cr, uid, ids, *args, **kwargs)
|
||||
|
||||
account_analytic_account()
|
||||
|
||||
#
|
||||
# Tasks History, used for cumulative flow charts (Lean/Agile)
|
||||
|
@ -1313,7 +1297,7 @@ class project_task_history(osv.osv):
|
|||
_defaults = {
|
||||
'date': fields.date.context_today,
|
||||
}
|
||||
project_task_history()
|
||||
|
||||
|
||||
class project_task_history_cumulative(osv.osv):
|
||||
_name = 'project.task.history.cumulative'
|
||||
|
@ -1341,4 +1325,4 @@ class project_task_history_cumulative(osv.osv):
|
|||
) as history
|
||||
)
|
||||
""")
|
||||
project_task_history_cumulative()
|
||||
|
||||
|
|
|
@ -24,22 +24,40 @@
|
|||
<record id="project_tt_specification" model="project.task.type">
|
||||
<field name="sequence">1</field>
|
||||
<field name="name">Design</field>
|
||||
<field name="project_default" eval="1"/>
|
||||
<field name="state">draft</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record id="project_tt_development" model="project.task.type">
|
||||
<field name="sequence">2</field>
|
||||
<field name="name">Development</field>
|
||||
<field name="project_default" eval="1"/>
|
||||
<field name="state">open</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record id="project_tt_testing" model="project.task.type">
|
||||
<field name="sequence">3</field>
|
||||
<field name="name">Testing</field>
|
||||
<field name="project_default" eval="1"/>
|
||||
<field name="state">open</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record id="project_tt_pending" model="project.task.type">
|
||||
<field name="sequence">4</field>
|
||||
<field name="name">Pending</field>
|
||||
<field name="state">pending</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
<record id="project_tt_merge" model="project.task.type">
|
||||
<field name="sequence">4</field>
|
||||
<field name="sequence">5</field>
|
||||
<field name="name">Deployment</field>
|
||||
<field name="project_default" eval="1"/>
|
||||
<field name="state">done</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
</record>
|
||||
<record id="project_tt_cancel" model="project.task.type">
|
||||
<field name="sequence">6</field>
|
||||
<field name="name">Cancelled</field>
|
||||
<field name="state">cancelled</field>
|
||||
<field name="case_default" eval="True"/>
|
||||
<field name="fold" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Prepare Requirements Document</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
<field name="color">3</field>
|
||||
</record>
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Make SRS</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_3" model="project.task">
|
||||
|
@ -99,7 +99,7 @@
|
|||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Design Use Cases</field>
|
||||
<field name="date_deadline" eval="time.strftime('%Y-%m-24')"/>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_4" model="project.task">
|
||||
|
@ -112,7 +112,7 @@
|
|||
<field name="description">Use the account_budget module</field>
|
||||
<field name="date_deadline" eval="time.strftime('%Y-%m-19')"/>
|
||||
<field name="color">3</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_5" model="project.task">
|
||||
|
@ -125,7 +125,7 @@
|
|||
<field name="kanban_state">done</field>
|
||||
<field name="priority">0</field>
|
||||
<field name="date_deadline" eval="time.strftime('%Y-%m-%d')"/>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_6" model="project.task">
|
||||
|
@ -135,7 +135,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Risk Management Planning</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_7" model="project.task">
|
||||
|
@ -145,7 +145,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Create Project Schedules</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_8" model="project.task">
|
||||
|
@ -156,7 +156,7 @@
|
|||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Dataflow Design</field>
|
||||
<field name="priority">0</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_9" model="project.task">
|
||||
|
@ -166,7 +166,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">User Interface Design</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_10" model="project.task">
|
||||
|
@ -177,7 +177,7 @@
|
|||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Develop Module in Sale Management</field>
|
||||
<field name="kanban_state">blocked</field>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_11" model="project.task">
|
||||
|
@ -187,7 +187,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Develop module in Warehouse</field>
|
||||
<field name="type_id" ref="project_tt_merge"/>
|
||||
<field name="stage_id" ref="project_tt_merge"/>
|
||||
</record>
|
||||
|
||||
<function model="project.task" name="do_close" eval="[ref('project_task_11')], {'install_mode': True}"/>
|
||||
|
@ -199,7 +199,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Integrate Modules</field>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<function model="project.task" name="do_close" eval="[ref('project_task_12')], {'install_mode': True}"/>
|
||||
|
@ -211,7 +211,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Unit Testing</field>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<function model="project.task" name="do_pending" eval="[ref('project_task_13')], {'install_mode': True}"/>
|
||||
|
@ -223,8 +223,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Regression Test</field>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="state">pending</field>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="project_task_15" model="project.task">
|
||||
|
@ -234,7 +233,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Documentation</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
<field name="date_start">2011-02-06</field>
|
||||
</record>
|
||||
|
||||
|
@ -247,7 +246,7 @@
|
|||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Performance Tuning</field>
|
||||
<field name="description">Test on Runbot</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
<function model="project.task" name="do_open" eval="[ref('project_task_16')], {'install_mode': True}"/>
|
||||
|
||||
|
@ -258,7 +257,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Deploy and Review on Customer System</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
<function model="project.task" name="do_open" eval="[ref('project_task_17')], {'install_mode': True}"/>
|
||||
|
||||
|
@ -269,7 +268,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project.project_integrate_openerp"/>
|
||||
<field name="name">Training and Presentation</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
|
@ -322,7 +321,7 @@
|
|||
<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_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="project_id" ref="project_project_22"/>
|
||||
<field name="description">BoM, After sales returns, interventions. Traceability.</field>
|
||||
|
@ -334,7 +333,7 @@
|
|||
<field name="planned_hours">16.0</field>
|
||||
<field name="remaining_hours">16.0</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
<field name="project_id" ref="project_project_23"/>
|
||||
<field name="name">Data importation + Doc</field>
|
||||
</record>
|
||||
|
@ -344,7 +343,7 @@
|
|||
<field name="planned_hours">16.0</field>
|
||||
<field name="remaining_hours">16.0</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
<field name="project_id" ref="project_project_23"/>
|
||||
<field name="name">Modifications asked by the customer.</field>
|
||||
</record>
|
||||
|
@ -353,7 +352,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_id" ref="project_tt_testing"/>
|
||||
<field name="stage_id" ref="project_tt_testing"/>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="priority">0</field>
|
||||
<field name="project_id" ref="project_project_21"/>
|
||||
|
@ -364,7 +363,7 @@
|
|||
<field name="sequence">15</field>
|
||||
<field name="planned_hours">8.0</field>
|
||||
<field name="remaining_hours">8.0</field>
|
||||
<field name="type_id" ref="project_tt_testing"/>
|
||||
<field name="stage_id" ref="project_tt_testing"/>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="project_id" ref="project_project_21"/>
|
||||
<field name="name">Internal testing + Software Install</field>
|
||||
|
@ -374,7 +373,7 @@
|
|||
<field name="sequence">17</field>
|
||||
<field name="planned_hours">16.0</field>
|
||||
<field name="remaining_hours">16.0</field>
|
||||
<field name="type_id" ref="project_tt_development"/>
|
||||
<field name="stage_id" ref="project_tt_development"/>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="priority">2</field>
|
||||
<field name="project_id" ref="project_project_21"/>
|
||||
|
@ -389,7 +388,7 @@
|
|||
<field name="user_id" eval="False"/>
|
||||
<field name="project_id" ref="project_project_23"/>
|
||||
<field name="name">Parameters</field>
|
||||
<field name="type_id" ref="project_tt_specification"/>
|
||||
<field name="stage_id" ref="project_tt_specification"/>
|
||||
</record>
|
||||
<function model="project.task" name="do_open" eval="[ref('project_task_189')], {'install_mode': True}"/>
|
||||
|
||||
|
@ -398,10 +397,9 @@
|
|||
<field name="planned_hours">32.0</field>
|
||||
<field name="remaining_hours">32.0</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="state">open</field>
|
||||
<field name="project_id" ref="project_project_21"/>
|
||||
<field name="name">Start of the doc redaction + MRP</field>
|
||||
<field name="type_id" ref="project_tt_testing"/>
|
||||
<field name="stage_id" ref="project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<!-- Schedule tasks to assign users and dates -->
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
<newline/>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -161,7 +161,7 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<act_window
|
||||
context="{'search_default_project_id': [active_id], 'default_project_id': active_id}"
|
||||
id="act_project_project_2_project_task_all"
|
||||
|
@ -305,15 +305,26 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Project" layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="action_close" states="pending,open" string="Done" type="object"/>
|
||||
<button name="do_open" states="pending,draft" string="Start Task" type="object"/>
|
||||
<button name="%(action_project_task_reevaluate)d" states="done,cancelled" string="Reactivate" type="action" context="{'button_reactivate':True}" />
|
||||
<button name="do_pending" states="open" string="Pending" type="object"/>
|
||||
<button name="do_draft" states="open" string="Draft" type="object"/>
|
||||
<button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action"/>
|
||||
<button name="do_cancel" states="draft,open,pending" string="Cancel" type="object"/>
|
||||
<button name="do_open" string="Start Task" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="%(action_project_task_reevaluate)d" string="Reactivate" type="action"
|
||||
states="done,cancelled" context="{'button_reactivate':True}"/>
|
||||
<button name="do_pending" string="Pending" type="object"
|
||||
states="open"/>
|
||||
<button name="action_close" string="Done" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="do_draft" string="Draft" type="object"
|
||||
states="cancel,done"/>
|
||||
<button name="%(action_project_task_delegate)d" string="Delegate" type="action"
|
||||
states="pending,open,draft"/>
|
||||
<button name="do_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending" />
|
||||
<button name="stage_previous" string="Previous Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-back" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="stage_next" string="Next Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-forward" attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}' select="1"/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -362,7 +373,8 @@
|
|||
<tree string="Delegated tasks">
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="effective_hours" widget="float_time"/>
|
||||
<field name="progress" widget="progressbar"/>
|
||||
<field name="remaining_hours" widget="float_time"/>
|
||||
|
@ -376,43 +388,40 @@
|
|||
<separator string="Planning" colspan="2"/>
|
||||
<field name="priority"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</group>
|
||||
|
||||
<separator string="Miscellaneous" colspan="4"/>
|
||||
<field name="partner_id" />
|
||||
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
|
||||
<group col="4" colspan="2">
|
||||
<field name="type_id" widget="selection" readonly="1"/>
|
||||
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
|
||||
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
|
||||
</group>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<separator colspan="4" string="Notes"/>
|
||||
<field colspan="4" name="notes" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_bottom">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Project Task Kanban View -->
|
||||
<record model="ir.ui.view" id="view_task_kanban">
|
||||
<field name="name">project.task.kanban</field>
|
||||
<field name="model">project.task</field>
|
||||
<field name="type">kanban</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="type_id" >
|
||||
<kanban default_group_by="stage_id" >
|
||||
<field name="color"/>
|
||||
<field name="priority"/>
|
||||
<field name="type_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="user_email"/>
|
||||
<field name="description"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="kanban_state"/>
|
||||
<field name="remaining_hours" sum="Remaining Time" groups="project.group_time_work_estimation_tasks"/>
|
||||
<field name="date_deadline"/>
|
||||
|
@ -508,20 +517,11 @@
|
|||
<field name="effective_hours" widget="float_time" sum="Spent Hours" invisible="1"/>
|
||||
<field name="remaining_hours" widget="float_time" sum="Remaining Hours" on_change="onchange_remaining(remaining_hours,planned_hours)" invisible="context.get('set_visible',False)" groups="project.group_time_work_estimation_tasks"/>
|
||||
<field name="date_deadline" invisible="context.get('deadline_visible',True)"/>
|
||||
<field name="type_id" invisible="context.get('set_visible',False)"/>
|
||||
<button name="next_type" invisible="context.get('set_visible',False)"
|
||||
states="draft,open,pending"
|
||||
string="Change Stage"
|
||||
type="object"
|
||||
icon="gtk-go-forward"
|
||||
help="Change Type"/>
|
||||
<field name="stage_id" invisible="context.get('set_visible',False)"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)" groups="base.group_no_one"/>
|
||||
<field name="date_start" invisible="1" groups="base.group_no_one"/>
|
||||
<field name="date_end" invisible="1" groups="base.group_no_one"/>
|
||||
<field name="progress" widget="progressbar" invisible="context.get('set_visible',False)"/>
|
||||
<field name="state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="do_open" states="pending,draft,done,cancelled" string="Start Task" type="object" icon="gtk-media-play" help="For changing to open state" invisible="context.get('set_visible',False)"/>
|
||||
<button name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="terp-personal" help="For changing to delegate state"/>
|
||||
<button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -589,7 +589,7 @@
|
|||
<separator orientation="vertical"/>
|
||||
<filter string="Project" name="group_project_id" icon="terp-folder-violet" domain="[]" context="{'group_by':'project_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'type_id'}"/>
|
||||
<filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Status" name="group_state" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Deadline" icon="terp-gnome-cpu-frequency-applet+" domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
|
@ -660,7 +660,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Tasks Stages">
|
||||
<group>
|
||||
<filter icon="terp-check" string="Common" name="common" domain="[('project_default', '=', 1)]" help="Stages common to all projects"/>
|
||||
<filter icon="terp-check" string="Common" name="common" domain="[('case_default', '=', 1)]" help="Stages common to all projects"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
|
@ -674,10 +674,14 @@
|
|||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Task Stage">
|
||||
<group colspan="4" col="6">
|
||||
<field name="name"/>
|
||||
<field name="project_default"/>
|
||||
<field name="sequence"/>
|
||||
<group colspan="2" col="2">
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
</group>
|
||||
<group colspan="2" col="4">
|
||||
<field name="case_default"/>
|
||||
<field name="sequence"/>
|
||||
<field name="fold"/>
|
||||
</group>
|
||||
<separator string="Description" colspan="4"/>
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
|
@ -693,6 +697,7 @@
|
|||
<tree string="Task Stage">
|
||||
<field name="sequence"/>
|
||||
<field name="name"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -707,10 +712,10 @@
|
|||
|
||||
<menuitem id="menu_tasks_config" name="GTD" parent="project.menu_definitions" sequence="1"/>
|
||||
|
||||
<menuitem id="menu_project_config_project" name="Stages" parent="menu_definitions" sequence="1"/>
|
||||
<menuitem id="menu_project_config_project" name="Stages" parent="project.menu_definitions" sequence="1"/>
|
||||
|
||||
<menuitem action="open_task_type_form" id="menu_task_types_view" parent="menu_project_config_project" sequence="2" groups="base.group_no_one"/>
|
||||
<menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/>
|
||||
<menuitem action="open_task_type_form" name="Task Stages" id="menu_task_types_view" parent="menu_project_config_project" sequence="2"/>
|
||||
<menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1" groups="base.group_no_one"/>
|
||||
|
||||
<act_window context="{'search_default_user_id': [active_id], 'default_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"/>
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
<field name="user_id"/>
|
||||
<field name="remaining_hours"/>
|
||||
<field name="kanban_state"/>
|
||||
<field name="state"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -82,7 +82,7 @@ class report_project_task_user(osv.osv):
|
|||
t.name as name,
|
||||
t.company_id,
|
||||
t.partner_id,
|
||||
t.type_id,
|
||||
t.stage_id,
|
||||
remaining_hours as remaining_hours,
|
||||
total_hours as total_hours,
|
||||
t.delay_hours as hours_delay,
|
||||
|
@ -114,7 +114,7 @@ class report_project_task_user(osv.osv):
|
|||
name,
|
||||
t.company_id,
|
||||
t.partner_id,
|
||||
t.type_id
|
||||
t.stage_id
|
||||
|
||||
""")
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@
|
|||
<tree string="Task By Days" >
|
||||
<field name="day"/>
|
||||
<field name="total_task"/>
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
I change the stage of task to next stage.
|
||||
-
|
||||
!python {model: project.task}: |
|
||||
self.next_type(cr, uid, [ref("project_task_1")])
|
||||
self.stage_next(cr, uid, [ref("project_task_1")])
|
||||
-
|
||||
!record {model: project.task.reevaluate, id: reevaluate_id}:
|
||||
remaining_hours : 120
|
||||
|
@ -68,9 +68,9 @@
|
|||
I change the stage of task to previous stage.
|
||||
-
|
||||
!python {model: project.task}: |
|
||||
self.prev_type(cr, uid, [ref("project_task_1")])
|
||||
self.stage_previous(cr, uid, [ref("project_task_1")])
|
||||
-
|
||||
I cancel Task.
|
||||
-
|
||||
!python {model: project.task}: |
|
||||
self.do_cancel(cr, uid, [ref("project_task_2")])
|
||||
self.do_cancel(cr, uid, [ref("project_task_2")])
|
||||
|
|
|
@ -38,6 +38,7 @@ and decide on their status as they evolve.
|
|||
'website': 'http://www.openerp.com',
|
||||
'images': ['images/issue_analysis.jpeg','images/project_issue.jpeg'],
|
||||
'depends': [
|
||||
'base_status',
|
||||
'crm',
|
||||
'project',
|
||||
],
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph orientation="vertical" string="Project Issue" type="bar">
|
||||
<field name="type_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="nbr" operator="+"/>
|
||||
<field group="True" name="user_id"/>
|
||||
</graph>
|
||||
|
@ -96,18 +96,10 @@
|
|||
<field name="partner_id"/>
|
||||
<field name="project_id" />
|
||||
<field name="priority" string="Priority"/>
|
||||
<field name="type_id" widget="selection" readonly="1"/>
|
||||
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
|
||||
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
|
||||
<field name="version_id" widget="selection"/>
|
||||
<field name="progress" widget="progressbar" attrs="{'invisible':[('task_id','=',False)]}"/>
|
||||
<field name="state"/>
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
|
||||
<button name="case_close" string="Done" states="open,draft,pending" type="object" icon="gtk-jump-to"/>
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward" help="To Do"/>
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object" icon="gtk-media-pause"/>
|
||||
<button name="case_escalate" string="Escalate" states="open,draft,pending" type="object" icon="gtk-go-up"/>
|
||||
<button name="case_reset" string="Reset to Draft" states="done,cancel" type="object" icon="gtk-convert"/>
|
||||
<field name="stage_id" widget="selection" readonly="1"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="task_id" invisible="1"/>
|
||||
</tree>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from base_status.base_stage import base_stage
|
||||
from crm import crm
|
||||
from datetime import datetime
|
||||
from osv import fields,osv
|
||||
|
@ -42,12 +43,62 @@ class project_issue_version(osv.osv):
|
|||
}
|
||||
project_issue_version()
|
||||
|
||||
class project_issue(crm.crm_case, osv.osv):
|
||||
_ISSUE_STATE= [('draft', 'New'), ('open', 'In Progress'), ('cancel', 'Cancelled'), ('done', 'Done'),('pending', 'Pending')]
|
||||
|
||||
class project_issue(base_stage, osv.osv):
|
||||
_name = "project.issue"
|
||||
_description = "Project Issue"
|
||||
_order = "priority, create_date desc"
|
||||
_inherit = ['ir.needaction_mixin', 'mail.thread']
|
||||
|
||||
def _get_default_project_id(self, cr, uid, context=None):
|
||||
""" Gives default project by checking if present in the context """
|
||||
return self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
|
||||
def _get_default_stage_id(self, cr, uid, context=None):
|
||||
""" Gives default stage_id """
|
||||
project_id = self._get_default_project_id(cr, uid, context=context)
|
||||
return self.stage_find(cr, uid, [], project_id, [('state', '=', 'draft')], context=context)
|
||||
|
||||
def _resolve_project_id_from_context(self, cr, uid, context=None):
|
||||
""" Returns ID of project based on the value of 'default_project_id'
|
||||
context key, or None if it cannot be resolved to a single
|
||||
project.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if type(context.get('default_project_id')) in (int, long):
|
||||
return context.get('default_project_id')
|
||||
if isinstance(context.get('default_project_id'), basestring):
|
||||
project_name = context['default_project_id']
|
||||
project_ids = self.pool.get('project.project').name_search(cr, uid, name=project_name, context=context)
|
||||
if len(project_ids) == 1:
|
||||
return int(project_ids[0][0])
|
||||
return None
|
||||
|
||||
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
|
||||
access_rights_uid = access_rights_uid or uid
|
||||
stage_obj = self.pool.get('project.task.type')
|
||||
order = stage_obj._order
|
||||
# lame hack to allow reverting search, should just work in the trivial case
|
||||
if read_group_order == 'stage_id desc':
|
||||
order = "%s desc" % order
|
||||
# retrieve section_id from the context and write the domain
|
||||
# - ('id', 'in', 'ids'): add columns that should be present
|
||||
# - OR ('case_default', '=', True), ('fold', '=', False): add default columns that are not folded
|
||||
# - OR ('project_ids', 'in', project_id), ('fold', '=', False) if project_id: add project columns that are not folded
|
||||
search_domain = []
|
||||
project_id = self._resolve_project_id_from_context(cr, uid, context=context)
|
||||
if project_id:
|
||||
search_domain += ['|', '&', ('project_ids', '=', project_id), ('fold', '=', False)]
|
||||
search_domain += ['|', ('id', 'in', ids), '&', ('case_default', '=', True), ('fold', '=', False)]
|
||||
# perform search
|
||||
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
|
||||
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
|
||||
# restore order of the search
|
||||
result.sort(lambda x,y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
|
||||
return result
|
||||
|
||||
def _compute_day(self, cr, uid, ids, fields, args, context=None):
|
||||
"""
|
||||
@param cr: the current row, from the database cursor,
|
||||
|
@ -173,11 +224,13 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner', select=1),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'description': fields.text('Description'),
|
||||
'state': fields.selection([('draft', 'New'), ('cancel', 'Cancelled'), ('open', 'In Progress'),('pending', 'Pending'),('done', 'Done') ], 'Status', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'state': fields.related('stage_id', 'state', type="selection", store=True,
|
||||
selection=_ISSUE_STATE, string="State", readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
If the case is in progress the state is set to \'Open\'.\
|
||||
When the case is over, the state is set to \'Done\'.\
|
||||
If the case needs to be reviewed then the state is \
|
||||
set to \'Pending\'.'),
|
||||
'email_from': fields.char('Email', size=128, help="These people will receive email.", select=1),
|
||||
'email_cc': fields.char('Watchers Emails', size=256, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
|
||||
'date_open': fields.datetime('Opened', readonly=True,select=True),
|
||||
|
@ -188,7 +241,8 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('object_id.model', '=', 'crm.project.bug')]"),
|
||||
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
|
||||
'version_id': fields.many2one('project.issue.version', 'Version'),
|
||||
'type_id': fields.many2one ('project.task.type', 'Stages', domain="[('project_ids', '=', project_id)]"),
|
||||
'stage_id': fields.many2one ('project.task.type', 'Stages',
|
||||
domain="['|', ('project_ids', '=', project_id), ('case_default', '=', True)]"),
|
||||
'project_id':fields.many2one('project.project', 'Project'),
|
||||
'duration': fields.float('Duration'),
|
||||
'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]"),
|
||||
|
@ -205,7 +259,6 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
multi='compute_day', type="integer", help="Difference in days between last action and current date"),
|
||||
'color': fields.integer('Color Index'),
|
||||
'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
'progress': fields.function(_hours_get, string='Progress (%)', multi='hours', group_operator="avg", help="Computed as: Time Spent / Total Time.",
|
||||
|
@ -221,15 +274,20 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
|
||||
_defaults = {
|
||||
'active': 1,
|
||||
'partner_id': crm.crm_case._get_default_partner,
|
||||
'email_from': crm.crm_case._get_default_email,
|
||||
'partner_id': lambda s, cr, uid, c: s._get_default_partner(cr, uid, c),
|
||||
'email_from': lambda s, cr, uid, c: s._get_default_email(cr, uid, c),
|
||||
'state': 'draft',
|
||||
'section_id': crm.crm_case._get_section,
|
||||
'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
|
||||
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
|
||||
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
|
||||
'priority': crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'categ_id' : lambda *a: False,
|
||||
}
|
||||
|
||||
_group_by_full = {
|
||||
'stage_id': _read_group_stage_ids
|
||||
}
|
||||
|
||||
def set_priority(self, cr, uid, ids, priority):
|
||||
"""Set lead priority
|
||||
"""
|
||||
|
@ -312,36 +370,20 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
def convert_to_bug(self, cr, uid, ids, context=None):
|
||||
return self._convert(cr, uid, ids, 'bug_categ', context=context)
|
||||
|
||||
def next_type(self, cr, uid, ids, context=None):
|
||||
for task in self.browse(cr, uid, ids):
|
||||
typeid = task.type_id.id
|
||||
types = map(lambda x:x.id, task.project_id.type_ids or [])
|
||||
if types:
|
||||
if not typeid:
|
||||
self.write(cr, uid, [task.id], {'type_id': types[0]})
|
||||
elif typeid and typeid in types and types.index(typeid) != len(types)-1 :
|
||||
index = types.index(typeid)
|
||||
self.write(cr, uid, [task.id], {'type_id': types[index+1]})
|
||||
return True
|
||||
|
||||
def prev_type(self, cr, uid, ids, context=None):
|
||||
for task in self.browse(cr, uid, ids):
|
||||
typeid = task.type_id.id
|
||||
types = map(lambda x:x.id, task.project_id and task.project_id.type_ids or [])
|
||||
if types:
|
||||
if typeid and typeid in types:
|
||||
index = types.index(typeid)
|
||||
self.write(cr, uid, [task.id], {'type_id': index and types[index-1] or False})
|
||||
return True
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
issue = self.read(cr, uid, id, ['name'], context=context)
|
||||
if not default:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
default['name'] = issue['name'] + _(' (copy)')
|
||||
return super(project_issue, self).copy(cr, uid, id, default=default,
|
||||
context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
#Update last action date every time the user change the stage, the state or send a new email
|
||||
logged_fields = ['type_id', 'state', 'message_ids']
|
||||
logged_fields = ['stage_id', 'state', 'message_ids']
|
||||
if any([field in vals for field in logged_fields]):
|
||||
vals['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
if vals.get('type_id', False):
|
||||
stage = self.pool.get('project.task.type').browse(cr, uid, vals['type_id'], context=context)
|
||||
self.message_append_note(cr, uid, ids, body=_("Stage changed to <b>%s</b>.") % stage.name, context=context)
|
||||
return super(project_issue, self).write(cr, uid, ids, vals, context)
|
||||
|
||||
def onchange_task_id(self, cr, uid, ids, task_id, context=None):
|
||||
|
@ -363,15 +405,51 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
self.create_send_note(cr, uid, [obj_id], context=context)
|
||||
return obj_id
|
||||
|
||||
def case_open(self, cr, uid, ids, context=None):
|
||||
res = super(project_issue, self).case_open(cr, uid, ids, context)
|
||||
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S'), 'user_id' : uid})
|
||||
return res
|
||||
# -------------------------------------------------------
|
||||
# Stage management
|
||||
# -------------------------------------------------------
|
||||
|
||||
def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
|
||||
""" Override of the base.stage method
|
||||
Parameter of the stage search taken from the issue:
|
||||
- type: stage type must be the same or 'both'
|
||||
- section_id: if set, stages must belong to this section or
|
||||
be a default case
|
||||
"""
|
||||
if isinstance(cases, (int, long)):
|
||||
cases = self.browse(cr, uid, cases, context=context)
|
||||
# collect all section_ids
|
||||
section_ids = []
|
||||
if section_id:
|
||||
section_ids.append(section_id)
|
||||
for task in cases:
|
||||
if task.project_id:
|
||||
section_ids.append(task.project_id.id)
|
||||
# OR all section_ids and OR with case_default
|
||||
search_domain = []
|
||||
if section_ids:
|
||||
search_domain += [('|')] * len(section_ids)
|
||||
for section_id in section_ids:
|
||||
search_domain.append(('project_ids', '=', section_id))
|
||||
search_domain.append(('case_default', '=', True))
|
||||
# AND with the domain in parameter
|
||||
search_domain += list(domain)
|
||||
# perform search, return the first found
|
||||
stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context)
|
||||
if stage_ids:
|
||||
return stage_ids[0]
|
||||
return False
|
||||
|
||||
def case_cancel(self, cr, uid, ids, context=None):
|
||||
""" Cancels case """
|
||||
self.case_set(cr, uid, ids, 'cancelled', {'active': True}, context=context)
|
||||
self.case_cancel_send_note(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
def case_escalate(self, cr, uid, ids, context=None):
|
||||
cases = self.browse(cr, uid, ids)
|
||||
for case in cases:
|
||||
data = {'state' : 'draft'}
|
||||
data = {}
|
||||
if case.project_id.project_escalation_id:
|
||||
data['project_id'] = case.project_id.project_escalation_id.id
|
||||
if case.project_id.project_escalation_id.user_id:
|
||||
|
@ -380,10 +458,14 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
self.pool.get('project.task').write(cr, uid, [case.task_id.id], {'project_id': data['project_id'], 'user_id': False})
|
||||
else:
|
||||
raise osv.except_osv(_('Warning !'), _('You cannot escalate this issue.\nThe relevant Project has not configured the Escalation Project!'))
|
||||
self.write(cr, uid, [case.id], data)
|
||||
self.case_escalate_send_note(cr, uid, [case.id], context)
|
||||
self.case_set(cr, uid, ids, 'draft', data, context=context)
|
||||
self.case_escalate_send_note(cr, uid, [case.id], context=context)
|
||||
return True
|
||||
|
||||
# -------------------------------------------------------
|
||||
# Mail gateway
|
||||
# -------------------------------------------------------
|
||||
|
||||
def message_new(self, cr, uid, msg, custom_values=None, context=None):
|
||||
"""Automatically called when new email message arrives"""
|
||||
if context is None:
|
||||
|
@ -434,7 +516,7 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
# Reassign the 'open' state to the case if this one is in pending or done
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
if record.state in ('pending', 'done'):
|
||||
record.write({'state' : 'open'})
|
||||
self.case_set(cr, uid, ids, 'open', {}, context=context)
|
||||
|
||||
vls = { }
|
||||
for line in msg['body_text'].split('\n'):
|
||||
|
@ -448,15 +530,6 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
res = self.write(cr, uid, ids, vals)
|
||||
self.message_append_dict(cr, uid, ids, msg, context=context)
|
||||
return res
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
issue = self.read(cr, uid, id, ['name'], context=context)
|
||||
if not default:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
default['name'] = issue['name'] + _(' (copy)')
|
||||
return super(project_issue, self).copy(cr, uid, id, default=default,
|
||||
context=context)
|
||||
|
||||
# -------------------------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
|
@ -475,9 +548,15 @@ class project_issue(crm.crm_case, osv.osv):
|
|||
if obj.user_id:
|
||||
sub_ids.append(obj.user_id.id)
|
||||
return self.pool.get('res.users').read(cr, uid, sub_ids, context=context)
|
||||
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
stage_name = self.pool.get('project.task.type').name_get(cr, uid, [stage_id], context=context)[0][1]
|
||||
return self.message_append_note(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), context=context)
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Project issue '
|
||||
""" Override of default prefix for notifications. """
|
||||
return 'Project issue'
|
||||
|
||||
def convert_to_task_send_note(self, cr, uid, ids, context=None):
|
||||
message = _("Project issue has been <b>converted</b> in to task.")
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
<field eval=""5"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_agrolait"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
|
@ -15,7 +14,7 @@
|
|||
<field eval="15.0" name="duration"/>
|
||||
<field eval=""Bug in Accounts module"" name="name"/>
|
||||
<field eval=""agr@agrolait.com"" name="email_from"/>
|
||||
<field name="type_id" ref="project.project_tt_specification"/>
|
||||
<field name="stage_id" ref="project.project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_programnotgivingproperoutput0" model="project.issue">
|
||||
|
@ -23,28 +22,26 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_asus"/>
|
||||
<field eval=""done"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="3.5" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field eval=""Program not giving proper output"" name="name"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field name="type_id" ref="project.project_tt_specification"/>
|
||||
<field name="stage_id" ref="project.project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_outputincorrect0" model="project.issue">
|
||||
<field eval="time.strftime('%Y-%m-18 14:30:00')" name="date"/>
|
||||
<field eval=""4"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field eval=""cancel"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="2.3" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_23"/>
|
||||
<field eval=""Output incorrect"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_development"/>
|
||||
<field name="stage_id" ref="project.project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_problemloadingpage0" model="project.issue">
|
||||
|
@ -52,14 +49,13 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_14"/>
|
||||
<field eval=""cancel"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="4.0" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Problem loading page"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_pagenotfound0" model="project.issue">
|
||||
|
@ -67,14 +63,13 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_desertic_hispafuentes"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="1.0" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Page not Found"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_development"/>
|
||||
<field name="stage_id" ref="project.project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_programmingerror0" model="project.issue">
|
||||
|
@ -82,14 +77,13 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_5"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="4.0" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Programming Error"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_logicalerrorinprogram0" model="project.issue">
|
||||
|
@ -97,14 +91,13 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_6"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="2.0" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_9"/>
|
||||
<field eval=""Logical Error in Program"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_constrainterror0" model="project.issue">
|
||||
|
@ -112,14 +105,13 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_6"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="7.3" name="duration"/>
|
||||
<field name="categ_id" ref="bug_categ"/>
|
||||
<field name="project_id" ref="project.project_project_9"/>
|
||||
<field eval=""Constraint Error"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_errorinprogram0" model="project.issue">
|
||||
|
@ -127,13 +119,12 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_id" ref="base.res_partner_5"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="1.3" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Error in Program"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_patcheserrorinprogram0" model="project.issue">
|
||||
|
@ -141,14 +132,13 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="13.0" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_9"/>
|
||||
<field eval=""Patches Error in Program"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_testing"/>
|
||||
<field name="stage_id" ref="project.project_tt_testing"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_newfeaturestobeadded0" model="project.issue">
|
||||
|
@ -156,14 +146,13 @@
|
|||
<field eval=""4"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_maxtor"/>
|
||||
<field eval=""open"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="3.2" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_21"/>
|
||||
<field eval=""New Features To Be Added"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_merge"/>
|
||||
<field name="stage_id" ref="project.project_tt_merge"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_addmenustothemodule0" model="project.issue">
|
||||
|
@ -171,7 +160,6 @@
|
|||
<field eval=""1"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_id" ref="base.res_partner_9"/>
|
||||
<field eval=""done"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="3.0" name="duration"/>
|
||||
|
@ -179,7 +167,7 @@
|
|||
<field name="project_id" ref="project.project_project_21"/>
|
||||
<field eval=""Add menus to the module"" name="name"/>
|
||||
<field eval=""info@opensides.be"" name="email_from"/>
|
||||
<field name="type_id" ref="project.project_tt_development"/>
|
||||
<field name="stage_id" ref="project.project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_includeattendancesheetinproject0" model="project.issue">
|
||||
|
@ -187,7 +175,6 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_10"/>
|
||||
<field eval=""cancel"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="2.0" name="duration"/>
|
||||
|
@ -195,7 +182,7 @@
|
|||
<field name="project_id" ref="project.project_project_9"/>
|
||||
<field eval=""Include Attendance sheet in Project"" name="name"/>
|
||||
<field eval=""contact@tecsas.fr"" name="email_from"/>
|
||||
<field name="type_id" ref="project.project_tt_development"/>
|
||||
<field name="stage_id" ref="project.project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_createnewobject0" model="project.issue">
|
||||
|
@ -203,14 +190,13 @@
|
|||
<field eval=""3"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_6"/>
|
||||
<field eval=""draft"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="2.45" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Create new object"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_specification"/>
|
||||
<field name="stage_id" ref="project.project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_improvereportsinhrms0" model="project.issue">
|
||||
|
@ -218,14 +204,13 @@
|
|||
<field eval=""4"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="partner_id" ref="base.res_partner_11"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="15.0" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Improve Reports in HRMS"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_development"/>
|
||||
<field name="stage_id" ref="project.project_tt_development"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_improvereportsinpms0" model="project.issue">
|
||||
|
@ -233,14 +218,13 @@
|
|||
<field eval=""2"" name="priority"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="partner_id" ref="base.res_partner_11"/>
|
||||
<field eval=""pending"" name="state"/>
|
||||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
<field eval="1" name="active"/>
|
||||
<field eval="06.15" name="duration"/>
|
||||
<field name="categ_id" ref="feature_request_categ"/>
|
||||
<field name="project_id" ref="project.project_project_22"/>
|
||||
<field eval=""Improve Reports in PMS"" name="name"/>
|
||||
<field name="type_id" ref="project.project_tt_specification"/>
|
||||
<field name="stage_id" ref="project.project_tt_specification"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -52,14 +52,26 @@
|
|||
<field name="arch" type="xml">
|
||||
<form layout="manual">
|
||||
<div class="oe_form_topbar">
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object"/>
|
||||
<button name="case_close" string="Done" states="open,draft,pending" type="object"/>
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object"/>
|
||||
<button name="case_reset" string="Reset to New" states="done,cancel" type="object"/>
|
||||
<button name="case_escalate" string="Escalate" states="open,draft,pending" type="object"/>
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object"/>
|
||||
<button name="case_open" string="Open" type="object"
|
||||
states="draft,pending"/>
|
||||
<button name="case_close" string="Done" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="case_pending" string="Pending" type="object"
|
||||
states="draft,open"/>
|
||||
<button name="case_escalate" string="Escalate" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<button name="case_reset" string="Reset to New" type="object"
|
||||
states="cancelled,done"/>
|
||||
<button name="stage_previous" string="Previous Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-back"
|
||||
attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="stage_next" string="Next Stage" type="object"
|
||||
states="open,pending" icon="gtk-go-forward"
|
||||
attrs="{'invisible': [('stage_id','=', False)]}"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" nolabel="1" widget="statusbar" statusbar_visible="draft,open,done" statusbar_colors='{"pending":"blue"}'/>
|
||||
<field name="stage_id" nolabel="1" widget="statusbar"/>
|
||||
</div>
|
||||
<div class="oe_clear"/>
|
||||
</div>
|
||||
|
@ -75,11 +87,7 @@
|
|||
</group>
|
||||
<field name="user_id"/>
|
||||
<field name="version_id" colspan="2" widget="selection"/>
|
||||
<group colspan="2" col="4">
|
||||
<field name="type_id" string="Stages" />
|
||||
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
|
||||
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
|
||||
</group>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="General">
|
||||
|
@ -118,9 +126,9 @@
|
|||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids_social" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
<div class="oe_form_sheet_width">
|
||||
<field name="message_ids" colspan="4" widget="ThreadView" nolabel="1"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -138,19 +146,11 @@
|
|||
<field name="partner_id"/>
|
||||
<field name="project_id" />
|
||||
<field name="priority" string="Priority"/>
|
||||
<field name="type_id" widget="selection" readonly="1" string="Stages" />
|
||||
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
|
||||
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
|
||||
<field name="version_id" widget="selection"/>
|
||||
<field name="user_id"/>
|
||||
<field name="progress" widget="progressbar" attrs="{'invisible':[('task_id','=',False)]}"/>
|
||||
<field name="state"/>
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
|
||||
<button name="case_close" string="Done" states="open,draft,pending" type="object" icon="gtk-jump-to"/>
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward" help="To Do"/>
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object" icon="gtk-media-pause"/>
|
||||
<button name="case_escalate" string="Escalate" states="open,draft,pending" type="object" icon="gtk-go-up"/>
|
||||
<button name="case_reset" string="Reset to New" states="done,cancel" type="object" icon="gtk-convert"/>
|
||||
<field name="stage_id" widget="selection" readonly="1"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="task_id" invisible="1"/>
|
||||
</tree>
|
||||
|
@ -192,7 +192,7 @@
|
|||
<filter string="Priority" icon="terp-rating-rated" domain="[]"
|
||||
context="{'group_by':'priority'}" />
|
||||
<filter string="Stage" icon="terp-stage" domain="[]"
|
||||
context="{'group_by':'type_id'}" />
|
||||
context="{'group_by':'stage_id'}" />
|
||||
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]"
|
||||
context="{'group_by':'state'}" />
|
||||
<separator orientation="vertical" />
|
||||
|
@ -224,9 +224,9 @@
|
|||
<field name="model">project.issue</field>
|
||||
<field name="type">kanban</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban default_group_by="type_id">
|
||||
<kanban default_group_by="stage_id">
|
||||
<field name="color"/>
|
||||
<field name="state"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
<field name="priority"/>
|
||||
<field name="user_email"/>
|
||||
<field name="user_id"/>
|
||||
|
@ -270,8 +270,7 @@
|
|||
<a string="Convert To Task" name="convert_issue_task" icon="gtk-index" type="object"/>
|
||||
</div>
|
||||
<div class="oe_kanban_right">
|
||||
<a name="case_open" string="Open" states="draft,pending" type="object" icon="kanban-apply" />
|
||||
<a name="case_pending" string="Pending" states="draft,open" type="object" icon="kanban-pause"/>
|
||||
<a name="case_open" string="Open" states="draft,pending" type="object" icon="kanban-apply"/>
|
||||
<a name="case_close" string="Close" states="open,draft,pending" type="object" icon="kanban-stop"/>
|
||||
</div>
|
||||
<div class="oe_kanban_clear"/>
|
||||
|
@ -304,18 +303,10 @@
|
|||
<field name="name" string="Feature description"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="priority" string="Priority"/>
|
||||
<field name="type_id" widget="selection" readonly="1"/>
|
||||
<button name="prev_type" string="Previous" type="object" icon="gtk-go-back" help="Change to Previous Stage"/>
|
||||
<button name="next_type" string="Next" type="object" icon="gtk-go-forward" help="Change to Next Stage"/>
|
||||
<field name="version_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state"/>
|
||||
<button name="case_cancel" string="Cancel" states="draft,open,pending" type="object" icon="gtk-cancel"/>
|
||||
<button name="case_close" string="Done" states="open,draft,pending" type="object" icon="gtk-jump-to"/>
|
||||
<button name="case_open" string="Open" states="draft,pending" type="object" icon="gtk-go-forward"/>
|
||||
<button name="case_pending" string="Pending" states="draft,open" type="object" icon="gtk-media-pause"/>
|
||||
<button name="case_escalate" string="Escalate" states="open,draft,pending" type="object" icon="gtk-go-up"/>
|
||||
<button name="case_reset" string="Reset to New" states="done,cancel" type="object" icon="gtk-convert"/>
|
||||
<field name="stage_id" widget="selection" readonly="1"/>
|
||||
<field name="state" groups="base.group_no_one"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -326,13 +317,13 @@
|
|||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Feature Tracker Search">
|
||||
<filter icon="terp-go-today" string="Today"
|
||||
<filter icon="terp-go-today" string="Today"
|
||||
domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Today's features"/>
|
||||
<separator orientation="vertical"/>
|
||||
<group>
|
||||
<field name="name" string="Feature description"/>
|
||||
<field name="user_id"/>
|
||||
<field name="state">
|
||||
<field name="state" groups="base.group_no_one">
|
||||
<filter icon="terp-check" domain="[('state','in',('open','draft'))]" help="Current Features" name="current_feature"/>
|
||||
<filter icon="terp-camera_test" domain="[('state','=','open')]" help="Open Features"/>
|
||||
</field>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue