[MERGE] with trunk

bzr revid: fka@tinyerp.com-20130605051516-9ueeaj5by0z861v0
This commit is contained in:
Foram Katharotiya (OpenERP)
2013-06-05 10:45:16 +05:30
51 changed files with 4749 additions and 374 deletions
+16 -16
View File
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-12-11 13:00+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2013-06-03 07:47+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: Russian <ru@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: 2013-03-16 05:51+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: account_check_writing
#: selection:res.company,check_layout:0
@@ -25,13 +25,13 @@ msgstr ""
#. module: account_check_writing
#: report:account.print.check.top:0
msgid "Open Balance"
msgstr ""
msgstr "Открытый баланс"
#. module: account_check_writing
#: view:account.check.write:0
#: view:account.voucher:0
msgid "Print Check"
msgstr ""
msgstr "Напечатать чек"
#. module: account_check_writing
#: selection:res.company,check_layout:0
@@ -82,7 +82,7 @@ msgstr "Описание"
#. module: account_check_writing
#: model:ir.model,name:account_check_writing.model_account_journal
msgid "Journal"
msgstr ""
msgstr "Журнал"
#. module: account_check_writing
#: model:ir.actions.act_window,name:account_check_writing.action_write_check
@@ -95,14 +95,14 @@ 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
#: report:account.print.check.middle:0
#: report:account.print.check.top:0
msgid "Original Amount"
msgstr ""
msgstr "Первоначальная сумма"
#. module: account_check_writing
#: field:res.company,check_layout:0
@@ -119,7 +119,7 @@ msgstr ""
#: report:account.print.check.middle:0
#: report:account.print.check.top:0
msgid "Payment"
msgstr ""
msgstr "Платеж"
#. module: account_check_writing
#: field:account.journal,use_preprint_check:0
@@ -153,7 +153,7 @@ msgstr ""
#: report:account.print.check.middle:0
#: report:account.print.check.top:0
msgid "Due Date"
msgstr ""
msgstr "Дата исполнения"
#. module: account_check_writing
#: model:ir.actions.report.xml,name:account_check_writing.account_print_check_middle
@@ -163,13 +163,13 @@ msgstr ""
#. module: account_check_writing
#: model:ir.model,name:account_check_writing.model_res_company
msgid "Companies"
msgstr ""
msgstr "Компании"
#. module: account_check_writing
#: code:addons/account_check_writing/wizard/account_check_batch_printing.py:59
#, python-format
msgid "Error!"
msgstr ""
msgstr "Ошибка!"
#. module: account_check_writing
#: help:account.check.write,check_number:0
@@ -202,12 +202,12 @@ msgstr ""
#. module: account_check_writing
#: view:account.check.write:0
msgid "or"
msgstr ""
msgstr "или"
#. module: account_check_writing
#: field:account.voucher,amount_in_word:0
msgid "Amount in Word"
msgstr ""
msgstr "Сумма прописью"
#. module: account_check_writing
#: model:ir.model,name:account_check_writing.model_account_check_write
@@ -217,7 +217,7 @@ msgstr ""
#. module: account_check_writing
#: view:account.check.write:0
msgid "Cancel"
msgstr ""
msgstr "Отмена"
#. module: account_check_writing
#: field:account.check.write,check_number:0
+17 -12
View File
@@ -23,6 +23,7 @@ import random
from urllib import urlencode
from urlparse import urljoin
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import osv, fields
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
@@ -103,6 +104,9 @@ class res_partner(osv.Model):
def action_signup_prepare(self, cr, uid, ids, context=None):
return self.signup_prepare(cr, uid, ids, context=context)
def signup_cancel(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'signup_token': False, 'signup_type': False, 'signup_expiration': False}, context=context)
def signup_prepare(self, cr, uid, ids, signup_type="signup", expiration=False, context=None):
""" generate a new token for the partners with the given validity, if necessary
:param expiration: the expiration datetime of the token (string, optional)
@@ -202,7 +206,7 @@ class res_users(osv.Model):
})
if partner.company_id:
values['company_id'] = partner.company_id.id
values['company_ids'] = [(6,0,[partner.company_id.id])]
values['company_ids'] = [(6, 0, [partner.company_id.id])]
self._signup_create_user(cr, uid, values, context=context)
else:
# no token, sign up an external user
@@ -259,25 +263,26 @@ class res_users(osv.Model):
pass
if not bool(template):
template = self.pool.get('ir.model.data').get_object(cr, uid, 'auth_signup', 'reset_password_email')
mail_obj = self.pool.get('mail.mail')
assert template._name == 'email.template'
for user in self.browse(cr, uid, ids, context):
if not user.email:
raise osv.except_osv(_("Cannot send email: user has no email address."), user.name)
mail_id = self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, True, context=context)
mail_state = mail_obj.read(cr, uid, mail_id, ['state'], context=context)
if mail_state and mail_state['state'] == 'exception':
raise self.pool.get('res.config.settings').get_config_warning(cr, _("Cannot send email: no outgoing email server configured.\nYou can configure it under %(menu:base_setup.menu_general_configuration)s."), context)
else:
return True
try:
self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, force_send=True, raise_exception=True, context=context)
except Exception:
raise
def create(self, cr, uid, values, context=None):
if context is None:
context = {}
# overridden to automatically invite user to sign up
user_id = super(res_users, self).create(cr, uid, values, context=context)
user = self.browse(cr, uid, user_id, context=context)
if context and context.get('reset_password') and user.email:
ctx = dict(context, create_user=True)
self.action_reset_password(cr, uid, [user.id], context=ctx)
if user.email and not context.get('no_reset_password'):
context.update({'create_user': True})
try:
self.action_reset_password(cr, uid, [user.id], context=context)
except MailDeliveryException:
self.pool.get('res.partner').signup_cancel(cr, uid, [user.partner_id.id], context=context)
return user_id
+2
View File
@@ -31,9 +31,11 @@
<!-- add Reset Password button -->
<xpath expr="//div[@class='oe_right oe_button_box']//button" position="replace">
<button string="Send Reset Password Instructions"
class="oe_link"
type="object" name="action_reset_password"
attrs="{'invisible': [('state', '!=', 'active')]}"/>
<button string="Send an Invitation Email"
class="oe_link"
type="object" name="action_reset_password" context="{'create_user': 1}"
attrs="{'invisible': [('state', '!=', 'new')]}"/>
</xpath>
+33 -20
View File
@@ -50,6 +50,7 @@ class base_action_rule(osv.osv):
_name = 'base.action.rule'
_description = 'Action Rules'
_order = 'sequence'
_columns = {
'name': fields.char('Rule Name', size=64, required=True),
@@ -61,6 +62,9 @@ class base_action_rule(osv.osv):
help="When unchecked, the rule is hidden and will not be executed."),
'sequence': fields.integer('Sequence',
help="Gives the sequence order when displaying a list of rules."),
'kind': fields.selection(
[('on_create', 'On Creation'), ('on_write', 'On Update'), ('on_time', 'Based on Timed Condition')],
string='When to Run'),
'trg_date_id': fields.many2one('ir.model.fields', string='Trigger Date',
domain="[('model_id', '=', model_id), ('ttype', 'in', ('date', 'datetime'))]"),
'trg_date_range': fields.integer('Delay after trigger date',
@@ -78,10 +82,10 @@ class base_action_rule(osv.osv):
ondelete='restrict',
domain="[('model_id', '=', model_id.model)]",
help="If present, this condition must be satisfied before the update of the record."),
'filter_id': fields.many2one('ir.filters', string='After Update Filter',
'filter_id': fields.many2one('ir.filters', string='Filter',
ondelete='restrict',
domain="[('model_id', '=', model_id.model)]",
help="If present, this condition must be satisfied after the update of the record."),
help="If present, this condition must be satisfied before executing the action rule."),
'last_run': fields.datetime('Last Run', readonly=1),
}
@@ -90,7 +94,15 @@ class base_action_rule(osv.osv):
'trg_date_range_type': 'day',
}
_order = 'sequence'
def onchange_kind(self, cr, uid, ids, kind, context=None):
clear_fields = []
if kind == 'on_create':
clear_fields = ['filter_pre_id', 'trg_date_id', 'trg_date_range', 'trg_date_range_type']
elif kind == 'on_write':
clear_fields = ['trg_date_id', 'trg_date_range', 'trg_date_range_type']
elif kind == 'on_time':
clear_fields = ['filter_pre_id']
return {'value': dict.fromkeys(clear_fields, False)}
def _filter(self, cr, uid, action, action_filter, record_ids, context=None):
""" filter the list record_ids that satisfy the action filter """
@@ -105,14 +117,7 @@ class base_action_rule(osv.osv):
def _process(self, cr, uid, action, record_ids, context=None):
""" process the given action on the records """
# execute server actions
model = self.pool[action.model_id.model]
if action.server_action_ids:
server_action_ids = map(int, action.server_action_ids)
for record in model.browse(cr, uid, record_ids, context):
action_server_obj = self.pool.get('ir.actions.server')
ctx = dict(context, active_model=model._name, active_ids=[record.id], active_id=record.id)
action_server_obj.run(cr, uid, server_action_ids, context=ctx)
# modify records
values = {}
@@ -127,13 +132,21 @@ class base_action_rule(osv.osv):
follower_ids = map(int, action.act_followers)
model.message_subscribe(cr, uid, record_ids, follower_ids, context=context)
# execute server actions
if action.server_action_ids:
server_action_ids = map(int, action.server_action_ids)
for record in model.browse(cr, uid, record_ids, context):
action_server_obj = self.pool.get('ir.actions.server')
ctx = dict(context, active_model=model._name, active_ids=[record.id], active_id=record.id)
action_server_obj.run(cr, uid, server_action_ids, context=ctx)
return True
def _wrap_create(self, old_create, model):
""" Return a wrapper around `old_create` calling both `old_create` and
`_process`, in that order.
"""
def wrapper(cr, uid, vals, context=None):
def create(cr, uid, vals, context=None):
# avoid loops or cascading actions
if context and context.get('action'):
return old_create(cr, uid, vals, context=context)
@@ -141,8 +154,8 @@ class base_action_rule(osv.osv):
context = dict(context or {}, action=True)
new_id = old_create(cr, uid, vals, context=context)
# as it is a new record, we do not consider the actions that have a prefilter
action_dom = [('model', '=', model), ('trg_date_id', '=', False), ('filter_pre_id', '=', False)]
# retrieve the action rules to run on creation
action_dom = [('model', '=', model), ('kind', '=', 'on_create')]
action_ids = self.search(cr, uid, action_dom, context=context)
# check postconditions, and execute actions on the records that satisfy them
@@ -151,13 +164,13 @@ class base_action_rule(osv.osv):
self._process(cr, uid, action, [new_id], context=context)
return new_id
return wrapper
return create
def _wrap_write(self, old_write, model):
""" Return a wrapper around `old_write` calling both `old_write` and
`_process`, in that order.
"""
def wrapper(cr, uid, ids, vals, context=None):
def write(cr, uid, ids, vals, context=None):
# avoid loops or cascading actions
if context and context.get('action'):
return old_write(cr, uid, ids, vals, context=context)
@@ -165,8 +178,8 @@ class base_action_rule(osv.osv):
context = dict(context or {}, action=True)
ids = [ids] if isinstance(ids, (int, long, str)) else ids
# retrieve the action rules to possibly execute
action_dom = [('model', '=', model), ('trg_date_id', '=', False)]
# retrieve the action rules to run on update
action_dom = [('model', '=', model), ('kind', '=', 'on_write')]
action_ids = self.search(cr, uid, action_dom, context=context)
actions = self.browse(cr, uid, action_ids, context=context)
@@ -185,7 +198,7 @@ class base_action_rule(osv.osv):
self._process(cr, uid, action, post_ids, context=context)
return True
return wrapper
return write
def _register_hook(self, cr, ids=None):
""" Wrap the methods `create` and `write` of the models specified by
@@ -224,8 +237,8 @@ class base_action_rule(osv.osv):
def _check(self, cr, uid, automatic=False, use_new_cursor=False, context=None):
""" This Function is called by scheduler. """
context = context or {}
# retrieve all the action rules that have a trg_date_id and no precondition
action_dom = [('trg_date_id', '!=', False), ('filter_pre_id', '=', False)]
# retrieve all the action rules to run based on a timed condition
action_dom = [('kind', '=', 'on_time')]
action_ids = self.search(cr, uid, action_dom, context=context)
for action in self.browse(cr, uid, action_ids, context=context):
now = datetime.now()
@@ -26,24 +26,32 @@
<notebook>
<page string="Conditions">
<group>
<group name="filter" string="Filter Condition">
<field name="filter_pre_id" domain="[('model_id','=',model)]" context="{'default_model_id': model}"/>
<field name="filter_id" domain="[('model_id','=',model)]" context="{'default_model_id': model}"/>
</group>
<group name="timing" string="Timer">
<field name="trg_date_id"/>
<label for="trg_date_range" string="Delay After Trigger Date" attrs="{'invisible': [('trg_date_id','=',False)]}"/>
<div attrs="{'invisible': [('trg_date_id','=',False)]}">
<field name="trg_date_range" class="oe_inline"/>
<field name="trg_date_range_type" class="oe_inline" attrs="{'required': [('trg_date_id','!=',False)]}"/>
</div>
</group>
<field name="kind" required="1"
on_change="onchange_kind(kind)"/>
<field name="filter_pre_id"
domain="[('model_id','=',model), ('user_id', '=', False)]"
context="{'default_model_id': model}"
attrs="{'invisible': [('kind', '!=', 'on_write')]}"/>
<field name="filter_id"
domain="[('model_id','=',model), ('user_id', '=', False)]"
context="{'default_model_id': model}"/>
<field name="trg_date_id"
attrs="{'invisible': [('kind', '!=', 'on_time')], 'required': [('kind', '=', 'on_time')]}"/>
<label for="trg_date_range" string="Delay After Trigger Date"
attrs="{'invisible': [('trg_date_id','=',False)]}"/>
<div attrs="{'invisible': [('trg_date_id','=',False)]}">
<field name="trg_date_range" class="oe_inline"/>
<field name="trg_date_range_type" class="oe_inline" attrs="{'required': [('trg_date_id','!=',False)]}"/>
</div>
</group>
<p class="oe_grey">
<b>Select a filter or a timer as condition.</b><br/> An action rule is checked when you create or modify the "Related Document Model". The precondition filter is checked right before the modification while the postcondition filter is checked after the modification. A precondition filter will therefore not work during a creation.<br/>
<b>To create a new filter:</b><br/>
- Go to your "Related Document Model" page and set the filter parameters in the "Search" view (Example of filter based on Leads/Opportunities: Creation Date "is equal to" 01/01/2012)<br/>
- In this same "Search" view, select the menu "Save Current Filter", enter the name (Ex: Create the 01/01/2012) and add the option "Share with all users"<br/>
<p>
Select when the action must be run, and add filters and/or timing conditions.
<br/>
In order to create a new filter:
<ul>
<li>Go to your "Related Document Model" page and set the filter parameters in the "Search" view (Example of filter based on Leads/Opportunities: Creation Date "is equal to" 01/01/2012)</li>
<li>In this same "Search" view, select the menu "Save Current Filter", enter the name (Ex: Create the 01/01/2012) and add the option "Share with all users"</li>
</ul>
The filter must therefore be available in this page.
</p>
</page>
@@ -76,6 +84,7 @@
<tree string="Action Rule">
<field name="sequence"/>
<field name="name"/>
<field name="kind"/>
<field name="filter_id"/>
</tree>
</field>
@@ -19,8 +19,8 @@ class base_action_rule_test(common.TransactionCase):
'name': "Lead is in done state",
'is_default': False,
'model_id': 'base.action.rule.lead.test',
'domain' : "[('state','=','done')]",
}, context=context)
'domain': "[('state','=','done')]",
}, context=context)
def create_filter_draft(self, cr, uid, context=None):
filter_pool = self.registry('ir.filters')
@@ -40,16 +40,16 @@ class base_action_rule_test(common.TransactionCase):
'user_id': self.admin,
}, context=context)
def create_rule(self, cr, uid, filter_id=False, filter_pre_id=False, context=None):
def create_rule(self, cr, uid, kind, filter_id=False, filter_pre_id=False, context=None):
"""
The "Rule 1" says that when a lead goes to the 'draft' state, the responsible for that lead changes to user "demo"
"""
return self.base_action_rule.create(cr,uid,{
'name' : "Rule 1",
'name': "Rule 1",
'model_id': self.registry('ir.model').search(cr, uid, [('model','=','base.action.rule.lead.test')], context=context)[0],
'active' : 1,
'filter_pre_id' : filter_pre_id,
'filter_id' : filter_id,
'kind': kind,
'filter_pre_id': filter_pre_id,
'filter_id': filter_id,
'act_user_id': self.demo,
}, context=context)
@@ -64,7 +64,7 @@ class base_action_rule_test(common.TransactionCase):
"""
cr, uid = self.cr, self.uid
filter_draft = self.create_filter_draft(cr, uid)
self.create_rule(cr, uid, filter_pre_id=filter_draft)
self.create_rule(cr, uid, 'on_write', filter_pre_id=filter_draft)
new_lead_id = self.create_lead_test_1(cr, uid)
new_lead = self.model.browse(cr, uid, new_lead_id)
self.assertEquals(new_lead.state, 'draft')
@@ -73,11 +73,11 @@ class base_action_rule_test(common.TransactionCase):
def test_01_check_to_state_draft_post(self):
"""
Check that a new record (with state = draft) changes its responsible when there is a postcondition filter which check that the state is draft.
Check that a new record changes its responsible when there is a postcondition filter which check that the state is draft.
"""
cr, uid = self.cr, self.uid
filter_draft = self.create_filter_draft(cr, uid)
self.create_rule(cr, uid, filter_id=filter_draft)
self.create_rule(cr, uid, 'on_create')
new_lead_id = self.create_lead_test_1(cr, uid)
new_lead = self.model.browse(cr, uid, new_lead_id)
self.assertEquals(new_lead.state, 'draft')
@@ -95,7 +95,7 @@ class base_action_rule_test(common.TransactionCase):
cr, uid = self.cr, self.uid
filter_draft = self.create_filter_draft(cr, uid)
filter_done = self.create_filter_done(cr, uid)
self.create_rule(cr, uid, filter_pre_id=filter_draft, filter_id=filter_done)
self.create_rule(cr, uid, 'on_write', filter_pre_id=filter_draft, filter_id=filter_done)
new_lead_id = self.create_lead_test_1(cr, uid)
new_lead = self.model.browse(cr, uid, new_lead_id)
self.assertEquals(new_lead.state, 'draft')
@@ -133,7 +133,7 @@ class base_action_rule_test(common.TransactionCase):
cr, uid = self.cr, self.uid
filter_draft = self.create_filter_draft(cr, uid)
filter_done = self.create_filter_done(cr, uid)
self.create_rule(cr, uid, filter_pre_id=filter_draft, filter_id=filter_done)
self.create_rule(cr, uid, 'on_write', filter_pre_id=filter_draft, filter_id=filter_done)
new_lead_id = self.create_lead_test_1(cr, uid)
new_lead = self.model.browse(cr, uid, new_lead_id)
self.assertEquals(new_lead.state, 'draft')
+4 -3
View File
@@ -81,8 +81,6 @@ Dashboard for CRM will include:
'crm_lead_view.xml',
'crm_lead_menu.xml',
'crm_case_section_view.xml',
'crm_meeting_menu.xml',
'crm_phonecall_view.xml',
@@ -98,6 +96,8 @@ Dashboard for CRM will include:
'res_config_view.xml',
'base_partner_merge_view.xml',
'crm_case_section_view.xml',
],
'demo': [
'crm_demo.xml',
@@ -121,7 +121,8 @@ Dashboard for CRM will include:
'static/src/css/crm.css'
],
'js': [
'static/src/js/crm.js'
'static/lib/sparkline/jquery.sparkline.js',
'static/src/js/crm_case_section.js',
],
'installable': True,
'application': True,
+59 -12
View File
@@ -19,13 +19,12 @@
#
##############################################################################
import base64
import time
from lxml import etree
from datetime import date, datetime
from dateutil import relativedelta
from openerp import tools
from openerp.osv import fields
from openerp.osv import osv
from openerp import tools
from openerp.tools.translate import _
MAX_LEVEL = 15
AVAILABLE_STATES = [
@@ -106,10 +105,57 @@ class crm_case_section(osv.osv):
_inherit = "mail.thread"
_description = "Sales Teams"
_order = "complete_name"
# number of periods for lead/opportunities/... tracking in salesteam kanban dashboard/kanban view
_period_number = 5
def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
return dict(self.name_get(cr, uid, ids, context=context))
def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, context=None):
""" Generic method to generate data for bar chart values using SparklineBarWidget.
This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field).
:param obj: the target model (i.e. crm_lead)
:param domain: the domain applied to the read_group
:param list read_fields: the list of fields to read in the read_group
:param str value_field: the field used to compute the value of the bar slice
:param str groupby_field: the fields used to group
:return list section_result: a list of dicts: [
{ 'value': (int) bar_column_value,
'tootip': (str) bar_column_tooltip,
}
]
"""
month_begin = date.today().replace(day=1)
section_result = [{
'value': 0,
'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B'),
} for i in range(self._period_number - 1, -1, -1)]
group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
for group in group_obj:
group_begin_date = datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATE_FORMAT)
month_delta = relativedelta.relativedelta(month_begin, group_begin_date)
section_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group_begin_date.strftime('%B')}
return section_result
def _get_opportunities_data(self, cr, uid, ids, field_name, arg, context=None):
""" Get opportunities-related data for salesteam kanban view
monthly_open_leads: number of open lead during the last months
monthly_planned_revenue: planned revenu of opportunities during the last months
"""
obj = self.pool.get('crm.lead')
res = dict.fromkeys(ids, False)
month_begin = date.today().replace(day=1)
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
for id in ids:
res[id] = dict()
lead_domain = [('type', '=', 'lead'), ('section_id', '=', id), ('create_date', '>=', groupby_begin)]
res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date'], 'create_date_count', 'create_date', context=context)
opp_domain = [('type', '=', 'opportunity'), ('section_id', '=', id), ('create_date', '>=', groupby_begin)]
res[id]['monthly_planned_revenue'] = self.__get_bar_values(cr, uid, obj, opp_domain, ['planned_revenue', 'create_date'], 'planned_revenue', 'create_date', context=context)
return res
_columns = {
'name': fields.char('Sales Team', size=64, required=True, translate=True),
'complete_name': fields.function(get_full_name, type='char', size=256, readonly=True, store=True),
@@ -129,15 +175,16 @@ class crm_case_section(osv.osv):
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
help="The email address associated with this team. New emails received will automatically "
"create new leads assigned to the team."),
'open_lead_ids': fields.one2many('crm.lead', 'section_id',
string='Open Leads', readonly=True,
domain=['&', ('type', '!=', 'opportunity'), ('state', 'not in', ['done', 'cancel'])]),
'open_opportunity_ids': fields.one2many('crm.lead', 'section_id',
string='Open Opportunities', readonly=True,
domain=['&', '|', ('type', '=', 'opportunity'), ('type', '=', 'both'), ('state', 'not in', ['done', 'cancel'])]),
'color': fields.integer('Color Index'),
'use_leads': fields.boolean('Leads',
help="This enables the management of leads in the sales team. Otherwise the sales team manages only opportunities."),
help="The first contact you get with a potential customer is a lead you qualify before converting it into a real business opportunity. Check this box to manage leads in this sales team."),
'monthly_open_leads': fields.function(_get_opportunities_data,
type="string", readonly=True, multi='_get_opportunities_data',
string='Open Leads per Month'),
'monthly_planned_revenue': fields.function(_get_opportunities_data,
type="string", readonly=True, multi='_get_opportunities_data',
string='Planned Revenue per Month')
}
def _get_stage_common(self, cr, uid, context):
+3 -4
View File
@@ -26,6 +26,7 @@ Description: [[object.description]]
<field name="name">Set Auto Reminder on leads which are not open since 5 days.</field>
<field name="model_id" ref="model_crm_lead"/>
<field name="sequence">1</field>
<field name="kind">on_time</field>
<field name="filter_id" ref="filter_draft_lead"/>
<field name="trg_date_id" ref="field_crm_lead_create_date"/>
<field name="trg_date_range">5</field>
@@ -54,12 +55,10 @@ object.write({'section_id': sales_team.id})
<field name="name">Set Auto Followers on leads which are urgent and come from USA.</field>
<field name="model_id" ref="model_crm_lead"/>
<field name="sequence">2</field>
<field name="kind">on_create</field>
<field name="filter_id" ref="filter_usa_lead"/>
<field name="act_followers" eval="[(6,0,[ref('base.res_partner_4'), ref('base.res_partner_5'), ref('base.res_partner_6')])]"/>
<field name="act_user_id" ref="base.user_root"/>
<field name="trg_date_id" ref="field_crm_lead_create_date"/>
<field name="trg_date_range">0</field>
<field name="trg_date_range_type">minutes</field>
<field name="act_followers" eval="[(6,0,[ref('base.res_partner_4'), ref('base.res_partner_5'), ref('base.res_partner_6')])]"/>
<field name="server_action_ids" eval="[(6,0,[ref('action_set_team_sales_department')])]"/>
</record>
</data>
+44 -35
View File
@@ -78,12 +78,12 @@
<field name="note"/>
<field name="alias_id"/>
<field name="color"/>
<field name="open_lead_ids"/>
<field name="open_opportunity_ids"/>
<field name="monthly_open_leads"/>
<field name="monthly_planned_revenue"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_project oe_kanban_global_click oe_kanban_crm_salesteams">
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click oe_kanban_crm_salesteams">
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_sale_manager">
<span class="oe_e">í</span>
<ul class="oe_dropdown_menu">
<li t-if="widget.view.is_action_enabled('edit')"><a type="edit">Sales Teams Settings</a></li>
@@ -92,25 +92,19 @@
</ul>
</div>
<div class="oe_kanban_content">
<h4><field name="name"/></h4>
<div class="oe_kanban_alias" t-if="record.use_leads.raw_value and record.alias_id.value">
<span class="oe_e">%%</span><small><field name="alias_id"/></small>
<h4 class="oe_center"><field name="name"/></h4>
<div class="oe_kanban_alias oe_center" t-if="record.use_leads.raw_value and record.alias_id.value">
<small><span class="oe_e" style="float: none;">%%</span><t t-raw="record.alias_id.raw_value[1]"/></small>
</div>
<div class="oe_items_list">
<a t-if="record.use_leads.raw_value" name="%(crm_case_form_view_salesteams_lead)d" type="action">
<t t-raw="record.open_lead_ids.raw_value.length"/>
<t t-if="record.open_lead_ids.raw_value.length &gt;= 2">Leads</t>
<t t-if="record.open_lead_ids.raw_value.length &lt; 2">Lead</t></a>
<a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">
<t t-raw="record.open_opportunity_ids.raw_value.length"/>
<t t-if="record.open_opportunity_ids.raw_value.length &gt;= 2">Opportunities</t>
<t t-if="record.open_opportunity_ids.raw_value.length &lt; 2">Opportunity</t></a>
</div>
<div class="oe_avatars">
<img t-if="record.user_id.raw_value" t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-data-member_id="record.user_id.raw_value"/>
<t t-foreach="record.member_ids.raw_value.slice(0,11)" t-as="member">
<img t-att-src="kanban_image('res.users', 'image_small', member)" t-att-data-member_id="member"/>
</t>
<div class="oe_salesteams_leads" t-if="record.use_leads.raw_value">
<a name="%(crm_case_form_view_salesteams_lead)d" type="action">Leads</a>
<a name="%(action_report_crm_lead)d" type="action" class="oe_sparkline_bar_link"><field name="monthly_open_leads" widget="sparkline_bar">Open Leads per Month<br/>Click to see a detailed analysis of leads.</field></a>
</div>
<div class="oe_salesteams_opportunities">
<a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">Opportunities</a>
<a name="%(action_report_crm_opportunity)d" type="action"><field name="monthly_planned_revenue" widget="sparkline_bar">Planned Revenue per Month<br/>Click to see a detailed analysis of opportunities.</field></a>
</div>
</div>
</div>
</div>
@@ -120,6 +114,27 @@
</field>
</record>
<!-- Case Sections Search view -->
<record id="crm_case_section_salesteams_search" model="ir.ui.view">
<field name="name">Case Sections - Search</field>
<field name="model">crm.case.section</field>
<field name="arch" type="xml">
<search string="Salesteams Search">
<field name="name"/>
<field name="parent_id"/>
<field name="user_id"/>
<field name="note"/>
<field name="code"/>
<filter name="personal" string="My Salesteams" domain="['|', ('member_ids', '=', uid), ('user_id', '=', uid)]"/>
<group expand="0" string="Group By...">
<filter string="Team Leader" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Parent Sales Teams" domain="[]" context="{'group_by':'parent_id'}"/>
</group>
</search>
</field>
</record>
<!-- Case Sections Action -->
<record id="crm_case_section_salesteams_act" model="ir.actions.act_window">
@@ -127,6 +142,7 @@
<field name="res_model">crm.case.section</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context">{'search_default_personal': True}</field>
<field name="view_id" ref="crm_case_section_salesteams_view_kanban"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
@@ -148,9 +164,9 @@
<form string="Sales Team" version="7.0">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Project Name"/>
<label for="name" class="oe_edit_only" string="Sales team"/>
<h1>
<field name="name" string="Project Name"/>
<field name="name" string="Salesteam"/>
</h1>
<div name="group_alias"
attrs="{'invisible': [('alias_domain', '=', False)]}">
@@ -168,25 +184,18 @@
</div>
</div>
<group>
<group>
<field name="parent_id"/>
<field name="resource_calendar_id"/>
<field name="active"/>
</group>
<group>
<field name="user_id"/>
<field name="code"/>
</group>
<group colspan="4" attrs="{'invisible': [('use_leads', '=', False)]}">
<group>
<field name="parent_id"/>
<field name="change_responsible"/>
<field name="active"/>
</group>
</group>
<notebook colspan="4">
<page string="Sales Team">
<group>
<field name="change_responsible"/>
</group>
<separator string="Team Members"/>
<page string="Team Members">
<field name="member_ids" widget="many2many_kanban">
<kanban quick_create="false" create="true">
<field name="name"/>
+3 -2
View File
@@ -27,9 +27,10 @@
</record>
<record model="crm.case.section" id="section_sales_department">
<field name="name">Sales</field>
<field name="code">Sales</field>
<field name="name">Direct Sales</field>
<field name="code">DM</field>
<field name="use_leads">True</field>
<field name="alias_name">info</field>
<field name="member_ids" eval="[(4, ref('base.user_root'))]"/>
</record>
+3 -17
View File
@@ -7,27 +7,13 @@
</record>
<record model="crm.case.section" id="crm_case_section_1">
<field name="name">Sales Marketing Department</field>
<field name="code">SMD</field>
<field name="parent_id" ref="crm.section_sales_department"/>
<field name="name">Indirect Sales</field>
<field name="code">IM</field>
</record>
<record model="crm.case.section" id="crm_case_section_2">
<field name="name">Support Department</field>
<field name="name">Marketing</field>
<field name="code">SPD</field>
<field name="parent_id" ref="crm.section_sales_department"/>
</record>
<record model="crm.case.section" id="crm_case_section_3">
<field name="name">Direct Marketing</field>
<field name="code">DM</field>
<field name="parent_id" ref="crm.section_sales_department"/>
</record>
<record model="crm.case.section" id="crm_case_section_4">
<field name="name">Online Support</field>
<field name="code">OS</field>
<field name="parent_id" ref="crm.crm_case_section_2"/>
</record>
<record model="crm.segmentation" id="crm_segmentation0">
+2 -2
View File
@@ -367,8 +367,8 @@ class crm_lead(base_stage, format_address, osv.osv):
def on_change_user(self, cr, uid, ids, user_id, context=None):
""" When changing the user, also set a section_id or restrict section id
to the ones user_id is member of. """
section_id = False
if user_id:
section_id = self._get_default_section_id(cr, uid, context=context) or False
if user_id and not section_id:
section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context)
if section_ids:
section_id = section_ids[0]
+36 -25
View File
@@ -20,7 +20,7 @@
<field name="categ_ids" eval="[(6, 0, [categ_oppor6])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">1</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="stage_lead1"/>
<field name="description">Hello,
@@ -44,7 +44,7 @@ Can you send me the details ?</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor2])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">4</field>
<field name="section_id" ref="crm_case_section_3"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="stage_lead1"/>
<field eval="1" name="active"/>
@@ -63,7 +63,7 @@ Can you send me the details ?</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">2</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="stage_lead2"/>
<field eval="1" name="active"/>
@@ -82,7 +82,7 @@ Can you send me the details ?</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor5])]"/>
<field name="channel_id" ref=""/>
<field name="priority">3</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref=""/>
<field name="stage_id" ref="stage_lead7"/>
<field eval="1" name="active"/>
@@ -133,7 +133,7 @@ Contact: +1 813 494 5005</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3,categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">3</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="stage_lead1"/>
<field eval="1" name="active"/>
@@ -152,7 +152,7 @@ Contact: +1 813 494 5005</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">5</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="stage_lead7"/>
<field eval="1" name="active"/>
@@ -197,6 +197,9 @@ Contact: +1 813 494 5005</field>
<field name="stage_id" ref="stage_lead1"/>
<field eval="1" name="active"/>
</record>
<record id="crm_case_9" model="crm.lead">
<field name="create_date" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_10" model="crm.lead">
<field name="type">lead</field>
@@ -211,7 +214,7 @@ Contact: +1 813 494 5005</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">2</field>
<field name="section_id" ref="crm_case_section_3"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref=""/>
<field name="stage_id" ref="stage_lead1"/>
<field name="description">Hi,
@@ -235,7 +238,7 @@ Andrew</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_direct"/>
<field name="priority">3</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="stage_lead1"/>
<field eval="1" name="active"/>
@@ -291,7 +294,7 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-25')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-12')" name="date_action"/>
<field name="title_action">Meeting for pricing information.</field>
<field name="section_id" ref="crm_case_section_3"/>
<field name="section_id" ref="section_sales_department"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead3"/>
<field eval="1" name="active"/>
@@ -317,7 +320,7 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
<field name="title_action">Send Catalogue by Email</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="section_sales_department"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead3"/>
<field eval="1" name="active"/>
@@ -326,7 +329,7 @@ Andrew</field>
<record id="crm_case_15" model="crm.lead">
<field name="type">opportunity</field>
<field name="name">Plan to buy RedHat servers</field>
<field eval="35000" name="planned_revenue"/>
<field eval="25000" name="planned_revenue"/>
<field eval="30.0" name="probability"/>
<field name="street">69 rue de Chimay</field>
<field name="country_id" ref="base.be"/>
@@ -339,10 +342,11 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-12')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
<field name="title_action">Call to ask system requirement</field>
<field name="section_id" ref="crm_case_section_3"/>
<field name="section_id" ref="section_sales_department"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead4"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(months=2)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_16" model="crm.lead">
@@ -367,6 +371,7 @@ Andrew</field>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(hours=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_17" model="crm.lead">
@@ -388,10 +393,11 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-8')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-3')" name="date_action"/>
<field name="title_action">Send price list regarding our interventions</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead3"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(hours=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_18" model="crm.lead">
@@ -412,7 +418,7 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-13')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-4')" name="date_action"/>
<field name="title_action">Call to define real needs about training</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead3"/>
<field eval="1" name="active"/>
@@ -438,8 +444,9 @@ Andrew</field>
<field name="title_action">Ask for the good receprion of the proposition</field>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead4"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(months=3)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_20" model="crm.lead">
@@ -468,10 +475,11 @@ Andrew</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_phone"/>
<field name="priority">3</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead8"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_22" model="crm.lead">
@@ -486,7 +494,7 @@ Andrew</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">3</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead8"/>
<field eval="1" name="active"/>
@@ -504,14 +512,15 @@ Andrew</field>
<field name="priority">5</field>
<field name="section_id" ref="section_sales_department"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead5"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(hours=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_24" model="crm.lead">
<field name="type">opportunity</field>
<field name="name">Need 20 Days of Consultancy</field>
<field eval="5025" name="planned_revenue"/>
<field eval="6025" name="planned_revenue"/>
<field eval="90.0" name="probability"/>
<field name="email_from">info@mycompany.net</field>
<field name="country_id" ref="base.pe"/>
@@ -525,6 +534,7 @@ Andrew</field>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(month=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="crm_case_25" model="crm.lead">
@@ -544,7 +554,7 @@ Andrew</field>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="priority">2</field>
<field name="title_action">Conf call with technical service</field>
<field name="section_id" ref="crm_case_section_2"/>
<field name="section_id" ref="crm_case_section_1"/>
<field name="user_id" ref="base.user_root"/>
<field name="stage_id" ref="crm.stage_lead4"/>
<field eval="1" name="active"/>
@@ -569,10 +579,11 @@ Andrew</field>
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
<field name="title_action">Send Catalogue by Email</field>
<field name="section_id" ref="crm_case_section_4"/>
<field name="section_id" ref="crm_case_section_2"/>
<field name="user_id" ref="base.user_demo"/>
<field name="stage_id" ref="crm.stage_lead3"/>
<field name="stage_id" ref="crm.stage_lead6"/>
<field eval="1" name="active"/>
<field name="date_closed" eval="(DateTime.today() - relativedelta(hours=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<!-- Unsubscribe Admin from case15, subscribe Demo -->
+7 -6
View File
@@ -157,7 +157,8 @@
<label for="section_id" groups="base.group_multi_salesteams"/>
<div groups="base.group_multi_salesteams">
<field name="section_id"/>
<button name="case_escalate" string="Escalate" type="object"
<button name="case_escalate" string="Escalate"
type="object" class="oe_link"
attrs="{'invisible': ['|', ('section_id','=',False), ('state', 'not in', ['draft','open','pending'])]}"/>
</div>
<field name="type" invisible="1"/>
@@ -343,7 +344,7 @@
help="Leads that are assigned to me"/>
<filter string="Assigned to My Team(s)"
domain="[('section_id.member_ids', 'in', [uid])]" context="{'invisible_section': False}"
help="Leads that are assigned to any sales teams I am member of"/>
help="Leads that are assigned to any sales teams I am member of" groups="base.group_multi_salesteams"/>
<separator />
<filter string="Available for mass mailing"
name='not_opt_out' domain="[('opt_out', '=', False)]"
@@ -351,7 +352,7 @@
<separator />
<group expand="0" string="Group By...">
<filter string="Salesperson" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Team" domain="[]" context="{'group_by':'section_id'}"/>
<filter string="Team" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
<filter string="Stage" domain="[]" context="{'group_by':'stage_id'}"/>
<filter string="Customer" help="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Country" domain="[]" context="{'group_by':'country_id'}"/>
@@ -362,7 +363,7 @@
</group>
<group string="Display">
<filter string="Show Countries" context="{'invisible_country': False}" help="Show Countries"/>
<filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team"/>
<filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team" groups="base.group_multi_salesteams"/>
</group>
</search>
</field>
@@ -556,7 +557,7 @@
<filter string="Lost" name="lost" domain="[('state','=','cancel')]"/>
<filter string="Unassigned" name="unassigned" domain="[('user_id','=', False)]" help="No salesperson"/>
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/>
<filter string="Mine" name="assigned_to_me"
<filter string="My Opportunities" name="assigned_to_me"
domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
help="Opportunities that are assigned to me"/>
<filter string="Assigned to My Team(s)"
@@ -577,7 +578,7 @@
<filter string="Creation" domain="[]" context="{'group_by':'create_date'}"/>
</group>
<group string="Display">
<filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team"/>
<filter string="Show Sales Team" context="{'invisible_section': False}" domain="[]" help="Show Sales Team" groups="base.group_multi_salesteams"/>
<filter string="Show Countries" context="{'invisible_country': False}" help="Show Countries"/>
</group>
</search>
+3 -3
View File
@@ -37,7 +37,7 @@
<field name="name">Ask for convenient time of meeting</field>
<field name="state">open</field>
<field name="partner_phone">+1 786 525 0724</field>
<field name="section_id" ref="crm.crm_case_section_3"/>
<field name="section_id" ref="crm.crm_case_section_2"/>
<field eval="1" name="active"/>
<field name="categ_id" ref="crm.categ_phone2"/>
<field eval="5.0" name="duration"/>
@@ -50,7 +50,7 @@
<field name="state">done</field>
<field name="partner_phone">(077) 582-4035</field>
<field name="partner_mobile">(077) 341-3591</field>
<field name="section_id" ref="crm.crm_case_section_4"/>
<field name="section_id" ref="crm.crm_case_section_2"/>
<field eval="1" name="active"/>
<field name="categ_id" ref="crm.categ_phone1"/>
<field eval="5.45" name="duration"/>
@@ -74,7 +74,7 @@
<field name="name">Proposal for discount offer</field>
<field name="state">open</field>
<field name="partner_phone">+34 230 953 485</field>
<field name="section_id" ref="crm.crm_case_section_3"/>
<field name="section_id" ref="crm.crm_case_section_2"/>
<field eval="time.strftime('%Y-%m-28 14:15:30')" name="date"/>
<field name="categ_id" ref="crm.categ_phone2"/>
<field eval="8.56" name="duration"/>
+1 -1
View File
@@ -101,7 +101,7 @@
<field name="type"/>
<field name="on_change"/>
<field name="sequence"/>
<field name="case_default"/>
<field name="case_default" groups="base.group_multi_salesteams"/>
<field name="fold"/>
</group>
<separator string="Requirements"/>
+1 -1
View File
@@ -75,7 +75,7 @@
<filter icon="terp-dialog-close" string="Closed" domain="[('state','=','done')]" help="Leads/Opportunities which are in done state"/>
<separator/>
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]"
help="Leads/Opportunities that are assigned to one of the sale teams I manage"/>
help="Leads/Opportunities that are assigned to one of the sale teams I manage" groups="base.group_multi_salesteams"/>
<separator/>
<filter icon="terp-personal" string="My Case(s)" help="Leads/Opportunities that are assigned to me" domain="[('user_id','=',uid)]"/>
<field name="section_id" context="{'invisible_section': False}"
@@ -57,7 +57,7 @@
help="Phone calls which are in pending state"/>
<separator/>
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]"
help="Phone calls that are assigned to one of the sale teams I manage"/>
help="Phone calls that are assigned to one of the sale teams I manage" groups="base.group_multi_salesteams"/>
<separator/>
<filter icon="terp-personal" string="My Phone Calls" help="Phone Calls that are assigned to me" domain="[('user_id','=',uid)]" />
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"
+2 -2
View File
@@ -22,9 +22,9 @@
</div>
</div>
</group>
<separator string="Sales Teams Configuration"/>
<separator string="Sales Teams"/>
<group>
<label for="id" string="Use Sales Teams"/>
<label for="id" string="Manage Sales Teams"/>
<div>
<field name="group_multi_salesteams" class="oe_inline"/>
<label for="group_multi_salesteams"/>
+1 -1
View File
@@ -12,7 +12,7 @@ access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.grou
access_crm_case_categ,crm.case.categ,model_crm_case_categ,base.group_user,1,0,0,0
access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0
access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0
access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,1,1,0
access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,0,0,0
access_crm_case_section_manager,crm.case.section.manager,model_crm_case_section,base.group_sale_manager,1,1,1,1
access_crm_case_stage,crm.case.stage,model_crm_case_stage,,1,0,0,0
access_crm_case_stage_manager,crm.case.stage,model_crm_case_stage,base.group_sale_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
12 access_crm_case_categ crm.case.categ model_crm_case_categ base.group_user 1 0 0 0
13 access_crm_lead crm.lead model_crm_lead base.group_sale_salesman 1 1 1 0
14 access_crm_phonecall crm.phonecall model_crm_phonecall base.group_sale_salesman 1 1 1 0
15 access_crm_case_section_user crm.case.section.user model_crm_case_section base.group_sale_salesman 1 1 0 1 0 0
16 access_crm_case_section_manager crm.case.section.manager model_crm_case_section base.group_sale_manager 1 1 1 1
17 access_crm_case_stage crm.case.stage model_crm_case_stage 1 0 0 0
18 access_crm_case_stage_manager crm.case.stage model_crm_case_stage base.group_sale_manager 1 1 1 1
File diff suppressed because it is too large Load Diff
+25 -3
View File
@@ -20,15 +20,27 @@
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list {
margin: 10px 0;
position: relative;
margin: 10px;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list a {
width: 110px;
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div {
width: 160px;
height: 22px;
margin: 0 !important;
position: relative;
display: inline-block;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list a:hover {
text-decoration: underline !important;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div a:nth-child(2n) {
position: absolute;
left: 90px;
top: 0;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list div:nth-child(2n) a:nth-child(2n) {
left: 110px;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center {
text-align: center;
margin: 3px 0;
@@ -40,3 +52,13 @@
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center .oe_subsum {
font-size: 10px;
}
.openerp .oe_kanban_view .oe_justgage {
color: black;
display: inline-block;
}
.openerp .oe_kanban_view .oe_sparkline_bar {
height: 20px;
width: 36px;
}
-11
View File
@@ -1,11 +0,0 @@
openerp.crm = function(openerp) {
openerp.web_kanban.KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'crm.case.section') {
this.$('.oe_kanban_crm_salesteams_list a').first().click();
} else {
this._super.apply(this, arguments);
}
},
});
};
@@ -0,0 +1,34 @@
openerp.crm = function(openerp) {
openerp.web_kanban.KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'crm.case.section') {
this.$('.oe_kanban_crm_salesteams_list a').first().click();
} else {
this._super.apply(this, arguments);
}
},
});
openerp.crm.SparklineBarWidget = openerp.web_kanban.AbstractField.extend({
className: "oe_sparkline_bar",
start: function() {
var self = this;
var title = this.$node.html();
setTimeout(function () {
var value = _.pluck(self.field.value, 'value');
var tooltips = _.pluck(self.field.value, 'tooltip');
self.$el.sparkline(value, {
type: 'bar',
barWidth: 5,
tooltipFormat: '{{offset:offset}} {{value}}',
tooltipValueLookups: {
'offset': tooltips
},
});
self.$el.tipsy({'delayIn': 0, 'html': true, 'title': function(){return title}, 'gravity': 'n'});
}, 0);
},
});
openerp.web_kanban.fields_registry.add("sparkline_bar", "openerp.crm.SparklineBarWidget");
};
+4 -2
View File
@@ -1,7 +1,9 @@
-
I cancel unqualified lead.
I set a new sale team (with Marketing at parent) and I cancel unqualified lead .
-
!python {model: crm.lead}: |
section_id = self.pool.get('crm.case.section').create(cr, uid, {'name': "Phone Marketing", 'parent_id': ref("crm.crm_case_section_2")})
self.write(cr, uid, [ref("crm_case_1")], {'section_id': section_id})
self.case_cancel(cr, uid, [ref("crm_case_1")])
-
I check cancelled lead.
@@ -42,4 +44,4 @@
I check the lead is correctly escalated to the parent team.
-
!assert {model: crm.lead, id: crm.crm_case_1, string: Escalate lead to parent team}:
- section_id.name == "Support Department"
- section_id.name == "Marketing"
@@ -55,7 +55,7 @@
<filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]"/>
<filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]"/>
<separator/>
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" />
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" groups="base.group_multi_salesteams"/>
<separator/>
<filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/>
<separator/>
@@ -78,7 +78,7 @@
</group>
<group expand="1" string="Group By...">
<filter string="Salesperson" name="Salesperson" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}" />
<filter string="Sales Team" icon="terp-personal+" domain="[]" context="{'group_by':'section_id'}" />
<filter string="Sales Team" icon="terp-personal+" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
<filter string="Partner" name="partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}" />
<filter string="Stage" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}" />
<filter string="Priority" icon="terp-rating-rated" domain="[]" context="{'group_by':'priority'}" />
+2 -2
View File
@@ -151,14 +151,14 @@
<filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]" help="All pending Helpdesk Request" />
<separator/>
<filter string="Assigned to Me or My Sales Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('section_id.member_ids', 'in', [uid])]"
help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" />
help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" groups="base.group_multi_salesteams"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<field name="section_id" string="Sales Team" groups="base.group_multi_salesteams"/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" help="Partner" context="{'group_by':'partner_id'}" />
<filter string="Responsible" icon="terp-personal" domain="[]" help="Responsible User" context="{'group_by':'user_id'}" />
<filter string="Sales Team" icon="terp-personal+" domain="[]" help="Sales Team" context="{'group_by':'section_id'}" />
<filter string="Sales Team" icon="terp-personal+" domain="[]" help="Sales Team" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
<filter string="Priority" icon="terp-rating-rated" domain="[]" context="{'group_by':'priority'}" />
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}" />
<filter string="Date" icon="terp-go-month" domain="[]" help="Request Date" context="{'group_by':'date'}" />
@@ -56,7 +56,7 @@
<separator/>
<filter icon="terp-personal" string="My Case(s)" help="My Case(s)" domain="[('user_id','=',uid)]" />
<separator/>
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" />
<filter string="My Sales Team(s)" icon="terp-personal+" context="{'invisible_section': False}" domain="[('section_id.user_id','=',uid)]" help="My Sales Team(s)" groups="base.group_multi_salesteams"/>
<separator/>
<filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/>
<field name="user_id" string="Salesperson"/>
@@ -71,7 +71,7 @@
</group>
<group expand="1" string="Group By...">
<filter string="Salesperson" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Sales Team" icon="terp-personal+" domain="[]" context="{'group_by':'section_id'}" />
<filter string="Sales Team" icon="terp-personal+" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}" />
<filter string="Channel" icon="terp-call-start" domain="[]" context="{'group_by':'channel_id'}" />
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}" />
@@ -3,7 +3,7 @@ Date: Tue, 25 Oct 2011 13:41:17 +0530
From: Mr. John Right <info@customer.com>
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8
MIME-Version: 1.0
To: info@my.com
To: _helpdesk@my.com
Subject: Where is download link of user manual of your product ?
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 8bit
+2 -2
View File
@@ -358,7 +358,7 @@ class email_template(osv.osv):
values['attachment_ids'] = attachment_ids
return values
def send_mail(self, cr, uid, template_id, res_id, force_send=False, context=None):
def send_mail(self, cr, uid, template_id, res_id, force_send=False, raise_exception=False, context=None):
"""Generates a new mail message for the given template and record,
and schedules it for delivery through the ``mail`` module's scheduler.
@@ -400,7 +400,7 @@ class email_template(osv.osv):
mail_mail.write(cr, uid, msg_id, {'attachment_ids': [(6, 0, attachment_ids)]}, context=context)
if force_send:
mail_mail.send(cr, uid, [msg_id], context=context)
mail_mail.send(cr, uid, [msg_id], raise_exception=raise_exception, context=context)
return msg_id
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+14 -14
View File
@@ -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: 2013-06-03 06:02+0000\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: fleet
@@ -35,7 +35,7 @@ msgstr "Ersatz Kälteklimakompressor"
#. module: fleet
#: help:fleet.vehicle,vin_sn:0
msgid "Unique number written on the vehicle motor (VIN/SN number)"
msgstr "Eindeutige Fahrzeug-Identifizierungsnummer (FIN)"
msgstr "Fahrgestellnummer"
#. module: fleet
#: selection:fleet.service.type,category:0
@@ -157,7 +157,7 @@ msgstr "Batterie Inspektion"
#. module: fleet
#: field:fleet.vehicle,company_id:0
msgid "Company"
msgstr "Unternehmen"
msgstr "Firma"
#. module: fleet
#: view:fleet.vehicle.log.contract:0
@@ -919,7 +919,7 @@ msgstr "Kaufdatum des Fahrzeugs"
#. module: fleet
#: view:fleet.vehicle.model:0
msgid "Models"
msgstr "Modell"
msgstr "Modelle"
#. module: fleet
#: view:fleet.vehicle.log.contract:0
@@ -1057,7 +1057,7 @@ msgstr "Kraftstoffart"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_22
msgid "Fuel Injector Replacement"
msgstr "Ersatz Einfüllstutzen"
msgstr "Ersatz Einspritzdüse"
#. module: fleet
#: model:ir.actions.act_window,name:fleet.fleet_vehicle_state_act
@@ -1103,7 +1103,7 @@ msgstr "Datum Vertragsbeginn"
#. module: fleet
#: selection:fleet.vehicle,fuel_type:0
msgid "Electric"
msgstr "Elektrisch"
msgstr "Elektrik"
#. module: fleet
#: field:fleet.vehicle,tag_ids:0
@@ -1176,7 +1176,7 @@ msgstr "Ersatz Lichtmaschine"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_3
msgid "A/C Diagnosis"
msgstr "Diagnose Batterie"
msgstr "Diagnose Klimaanlage"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_23
@@ -1201,7 +1201,7 @@ msgstr "Ersatz Wärmepumpe"
#. module: fleet
#: view:fleet.vehicle:0
msgid "show all the costs for this vehicle"
msgstr "gesamte Kostenübersicht der Fahrzeuge"
msgstr "gesamte Kostenübersicht des Fahrzeugs"
#. module: fleet
#: view:fleet.vehicle.odometer:0
@@ -1536,7 +1536,7 @@ msgstr "Achsvermessung"
#. module: fleet
#: model:fleet.vehicle.tag,name:fleet.vehicle_tag_purchased
msgid "Purchased"
msgstr "Ersatzteil"
msgstr "Eingekauft"
#. module: fleet
#: model:ir.actions.act_window,help:fleet.fleet_vehicle_odometer_act
@@ -1749,7 +1749,7 @@ msgstr "Preis"
#: field:fleet.vehicle.cost,odometer:0
#: field:fleet.vehicle.odometer,value:0
msgid "Odometer Value"
msgstr "Tachostand"
msgstr "Kilometerstand"
#. module: fleet
#: view:fleet.vehicle:0
@@ -1807,7 +1807,7 @@ msgstr "Schreiben Sie hier alle erforderlichen Zusatzinformationen auf."
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_29
msgid "Ignition Coil Replacement"
msgstr "Ersatz Zündkerzen"
msgstr "Ersatz Zündspule"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_service_16
@@ -1817,7 +1817,7 @@ msgstr "Optionen"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_contract_repairing
msgid "Repairing"
msgstr "Reparieren"
msgstr "Wird repariert"
#. module: fleet
#: model:ir.actions.act_window,name:fleet.action_fleet_reporting_costs
@@ -1855,7 +1855,7 @@ msgstr "Getriebe"
#. module: fleet
#: field:fleet.vehicle,vin_sn:0
msgid "Chassis Number"
msgstr "Fahrzeuqinformationsnummer"
msgstr "Fahrgestellnummer"
#. module: fleet
#: help:fleet.vehicle,color:0
@@ -2011,7 +2011,7 @@ msgstr "Reifenwechsel"
#. module: fleet
#: model:fleet.service.type,name:fleet.type_service_42
msgid "Starter Replacement"
msgstr "Erstinspektion"
msgstr "Ersatz Anlasser"
#. module: fleet
#: view:fleet.vehicle.cost:0
+12 -2
View File
@@ -27,6 +27,7 @@ from urlparse import urljoin
from openerp import tools
from openerp import SUPERUSER_ID
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import fields, osv
from openerp.tools.translate import _
@@ -292,7 +293,7 @@ class mail_mail(osv.Model):
'email_to': email_to,
}
def send(self, cr, uid, ids, auto_commit=False, context=None):
def send(self, cr, uid, ids, auto_commit=False, raise_exception=False, context=None):
""" Sends the selected emails immediately, ignoring their current
state (mails that have already been sent should not be passed
unless they should actually be re-sent).
@@ -303,6 +304,8 @@ class mail_mail(osv.Model):
:param bool auto_commit: whether to force a commit of the mail status
after sending each mail (meant only for scheduler processing);
should never be True during normal transactions (default: False)
:param bool raise_exception: whether to raise an exception if the
email sending process has failed
:return: True
"""
ir_mail_server = self.pool.get('ir.mail_server')
@@ -348,9 +351,16 @@ class mail_mail(osv.Model):
# see revid:odo@openerp.com-20120622152536-42b2s28lvdv3odyr in 6.1
if mail_sent:
self._postprocess_sent_message(cr, uid, mail, context=context)
except Exception:
except Exception as e:
_logger.exception('failed sending mail.mail %s', mail.id)
mail.write({'state': 'exception'})
if raise_exception:
if isinstance(e, AssertionError):
# get the args of the original error, wrap into a value and throw a MailDeliveryException
# that is an except_orm, with name and value as arguments
value = '. '.join(e.args)
raise MailDeliveryException(_("Mail Delivery Failed"), value)
raise
if auto_commit == True:
cr.commit()
+1 -1
View File
@@ -26,7 +26,7 @@
<field name="signature" position="before">
<field name="notification_email_send"/>
</field>
<field name="email" position="after">
<field name="signature" position="before">
<field name="alias_domain" invisible="1"/>
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
</field>
+56 -57
View File
@@ -8,14 +8,14 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-07-21 12:33+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"PO-Revision-Date: 2013-06-04 04:00+0000\n"
"Last-Translator: erdenebold <erdenebold10@gmail.com>\n"
"Language-Team: Mongolian <mn@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: 2013-03-16 05:01+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: mrp
#: help:mrp.config.settings,module_mrp_repair:0
@@ -48,7 +48,7 @@ msgstr "Дамжлагуудын Ашиглалт"
#. module: mrp
#: view:mrp.routing.workcenter:0
msgid "Routing Work Centers"
msgstr "Дамжлагуудын маршрут"
msgstr "Шугамын дамжлагууд"
#. module: mrp
#: field:mrp.production.workcenter.line,cycle:0
@@ -86,12 +86,12 @@ msgstr ""
#: model:ir.actions.act_window,name:mrp.mrp_routing_action
#: model:ir.ui.menu,name:mrp.menu_mrp_routing_action
msgid "Routings"
msgstr "Маршрут"
msgstr "Шугам"
#. module: mrp
#: view:mrp.bom:0
msgid "Search Bill Of Material"
msgstr "Жор Хайх"
msgstr "Орц Хайх"
#. module: mrp
#: model:process.node,note:mrp.process_node_stockproduct1
@@ -112,8 +112,8 @@ msgid ""
"Number of iterations this work center has to do in the specified operation "
"of the routing."
msgstr ""
"Үйлдвэрлэлийн нэг маршрутын хувьд уг дамжлага өөрийн үйлдлийг давтан "
"гүйцэтгэх давтамжын тоо."
"Үйлдвэрлэлийн нэг шугамын хувьд уг дамжлага өөрийн үйлдлийг давтан гүйцэтгэх "
"давтамжын тоо."
#. module: mrp
#: view:product.product:0
@@ -214,7 +214,7 @@ msgstr ""
#: code:addons/mrp/mrp.py:633
#, python-format
msgid "Cannot cancel manufacturing order!"
msgstr ""
msgstr "Үйлдвэрийн захиалгыг цуцлах боломжгүй!"
#. module: mrp
#: field:mrp.workcenter,costs_cycle_account_id:0
@@ -337,7 +337,7 @@ msgstr "Бараа Үйлдвэрлэх"
#. module: mrp
#: constraint:mrp.bom:0
msgid "Error ! You cannot create recursive BoM."
msgstr "Алдаа ! Тойрог хамааралтай жор үүсгэж болохгүй."
msgstr "Алдаа ! Тойрог хамааралтай орц үүсгэж болохгүй."
#. module: mrp
#: model:ir.model,name:mrp.model_mrp_routing_workcenter
@@ -423,7 +423,7 @@ msgstr ""
#: field:mrp.production,product_qty:0
#: field:mrp.production.product.line,product_qty:0
msgid "Product Quantity"
msgstr ""
msgstr "Барааны тоо"
#. module: mrp
#: help:mrp.production,picking_id:0
@@ -491,13 +491,13 @@ msgstr "Товлогдсон огноо"
#: code:addons/mrp/procurement.py:124
#, python-format
msgid "Manufacturing Order <em>%s</em> created."
msgstr ""
msgstr "Үйлдвэрлэлийн захиалга <em>%s</em> үүсгэгдлээ."
#. module: mrp
#: view:mrp.bom:0
#: report:mrp.production.order:0
msgid "Bill Of Material"
msgstr "Жор"
msgstr "Орц"
#. module: mrp
#: help:mrp.routing,location_id:0
@@ -518,7 +518,7 @@ msgstr "Нөөцийн Үнийн Хазайлт"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action2
msgid "Bill of Materials Structure"
msgstr "Жорын Бүтэц"
msgstr "Орцын Бүтэц"
#. module: mrp
#: model:process.node,note:mrp.process_node_serviceproduct0
@@ -560,7 +560,7 @@ msgstr ""
msgid ""
"The Bill of Material is linked to a routing, i.e. the succession of work "
"centers."
msgstr "Жор нь маршруттай холбогдсон, ө.х. дамжлагуудын цуваанууд"
msgstr "Орц нь шугамтай холбогдсон, ө.х. дамжлагуудын цуваанууд"
#. module: mrp
#: view:mrp.production:0
@@ -592,7 +592,7 @@ msgstr "Нөөцийн үнэ"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.action_product_bom_structure
msgid "Product BoM Structure"
msgstr "Барааны Жорын Бүтэц"
msgstr "Барааны Орцын Бүтэц"
#. module: mrp
#: view:mrp.production:0
@@ -603,12 +603,12 @@ msgstr "Үйлдвэрлэл Хайх"
#: help:mrp.routing.workcenter,sequence:0
msgid ""
"Gives the sequence order when displaying a list of routing Work Centers."
msgstr "Маршруутын дамжлагуудыг жагсаалтаар харуулах дэс дарааллыг өгнө."
msgstr "Шугамын дамжлагуудыг жагсаалтаар харуулах дэс дарааллыг өгнө."
#. module: mrp
#: field:mrp.bom,child_complete_ids:0
msgid "BoM Hierarchy"
msgstr "Жорын удамшил"
msgstr "Орцын удамшил"
#. module: mrp
#: model:process.transition,name:mrp.process_transition_stockproduction0
@@ -637,7 +637,7 @@ msgstr "Бэлтгэлтийн Сондгойрол"
#. module: mrp
#: field:mrp.bom,bom_lines:0
msgid "BoM Lines"
msgstr "Жорын мөрүүд"
msgstr "Орцын мөрүүд"
#. module: mrp
#: field:mrp.workcenter,time_start:0
@@ -650,13 +650,13 @@ msgid ""
"If the active field is set to False, it will allow you to hide the routing "
"without removing it."
msgstr ""
"Идэвхтэй талбар нь худал буюу тэмдэглэгдээгүй байвал машрутыг устгалгүйгээр "
"Идэвхтэй талбар нь худал буюу тэмдэглэгдээгүй байвал шугамыг устгалгүйгээр "
"нуудаг."
#. module: mrp
#: model:process.transition,name:mrp.process_transition_billofmaterialrouting0
msgid "Material Routing"
msgstr "Материалын Машрут"
msgstr "Материалын Шугам"
#. module: mrp
#: view:mrp.production:0
@@ -676,13 +676,13 @@ msgstr "Дамжлагын Ачаалал"
#: code:addons/mrp/procurement.py:50
#, python-format
msgid "No BoM defined for this product !"
msgstr "Энэ бараанд жор тодорхойлогдоогүй байна !"
msgstr "Энэ бараанд орц тодорхойлогдоогүй байна !"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.mrp_bom_form_action2
#: model:ir.ui.menu,name:mrp.menu_mrp_bom_form_action2
msgid "Bill of Material Components"
msgstr "Жорын бүрдэлүүд"
msgstr "Орцын бүрдэлүүд"
#. module: mrp
#: model:ir.model,name:mrp.model_stock_move
@@ -708,7 +708,7 @@ msgid ""
"operations and to plan future loads on work centers based on production "
"plannification."
msgstr ""
"Эцсийн барааг үйлдвэрлэх үйлдлүүд (дамжлагууд)-н жагсаалт. Машрут гэдэг нь "
"Эцсийн барааг үйлдвэрлэх үйлдлүүд (дамжлагууд)-н жагсаалт. Шугам гэдэг нь "
"үндсэндээ дамжлагуудын өртөгийг тооцоолох болон ажлын ачааллыг тооцоолоход "
"үйлдвэрлэлийн төлөвлөгөөн дээр суурилан бодоход хэрэглэгддэг."
@@ -734,7 +734,7 @@ msgstr ""
#. module: mrp
#: constraint:mrp.bom:0
msgid "BoM line product should not be same as BoM product."
msgstr "Жорын мөр нь жорын бараатайгаа ижил байж болохгүй."
msgstr "Орцын мөр нь орцын бараатайгаа ижил байж болохгүй."
#. module: mrp
#: view:mrp.production:0
@@ -744,7 +744,7 @@ msgstr "Үйлдвэрлэгдэж буй"
#. module: mrp
#: model:ir.ui.menu,name:mrp.menu_mrp_property
msgid "Master Bill of Materials"
msgstr "Мастер жор"
msgstr "Мастер орц"
#. module: mrp
#: help:mrp.config.settings,module_product_manufacturer:0
@@ -907,7 +907,7 @@ msgid ""
"All product quantities must be greater than 0.\n"
"You should install the mrp_byproduct module if you want to manage extra "
"products on BoMs !"
msgstr ""
msgstr "Бүх бүтээгдэхүүнийг тоог 0-оос эхэлж үүсгэнэ."
#. module: mrp
#: view:mrp.production:0
@@ -954,7 +954,7 @@ msgstr ""
#. module: mrp
#: field:mrp.bom,type:0
msgid "BoM Type"
msgstr "Жорын төрөл"
msgstr "Орцын төрөл"
#. module: mrp
#: code:addons/mrp/procurement.py:52
@@ -962,7 +962,7 @@ msgstr "Жорын төрөл"
msgid ""
"Procurement '%s' has an exception: 'No BoM defined for this product !'"
msgstr ""
"'%s' татан авалтад сондгойрол байна: 'Бараанд жор тодорхойлогдоогүй !'"
"'%s' татан авалтад сондгойрол байна: 'Бараанд орц тодорхойлогдоогүй !'"
#. module: mrp
#: view:mrp.property:0
@@ -1077,7 +1077,7 @@ msgstr "Нөөцлүүлэх"
#. module: mrp
#: report:bom.structure:0
msgid "BOM Name"
msgstr "Жорын нэр"
msgstr "Орцын нэр"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.act_product_manufacturing_open
@@ -1167,7 +1167,7 @@ msgstr "Хийгдэж байгаа үйлдвэрлэлийн захиалгу
#. module: mrp
#: model:ir.actions.client,name:mrp.action_client_mrp_menu
msgid "Open MRP Menu"
msgstr ""
msgstr "Нээлттэй MRP цэс"
#. module: mrp
#: model:ir.actions.act_window,name:mrp.mrp_production_action4
@@ -1194,7 +1194,7 @@ msgstr "Циклийн Өртөг"
#: code:addons/mrp/wizard/change_production_qty.py:88
#, python-format
msgid "Cannot find bill of material for this product."
msgstr ""
msgstr "Энэ бараа материалаар хайх боломжгүй."
#. module: mrp
#: selection:mrp.workcenter.load,measure_unit:0
@@ -1216,8 +1216,7 @@ msgstr "Нөөцүүд"
msgid ""
"Time in hours for this Work Center to achieve the operation of the specified "
"routing."
msgstr ""
"Заагдсан маршрутын үйлдлийг гүйцэтгэхэд энэ дамжлагын хугацаа цагаар."
msgstr "Заагдсан шугамын үйлдлийг гүйцэтгэхэд энэ дамжлагын хугацаа цагаар."
#. module: mrp
#: field:mrp.workcenter,costs_journal_id:0
@@ -1272,7 +1271,7 @@ msgstr "Үйлдвэрлэлийг эхлүүлэхэд бэлэн Үйлдвэ
#: field:mrp.production,bom_id:0
#: model:process.node,name:mrp.process_node_billofmaterial0
msgid "Bill of Material"
msgstr "Жор"
msgstr "Орц"
#. module: mrp
#: view:mrp.workcenter.load:0
@@ -1304,9 +1303,9 @@ msgid ""
"Routing is indicated then,the third tab of a production order (Work Centers) "
"will be automatically pre-completed."
msgstr ""
"Маршрут нь дамжлагууд ямар хугацаагаар хэдэн циклээр ашиглагдахыг "
"илэрхийлдэг. Хэрэв маршрут байгаа бол гурав дахь үйлдвэрлэлийн дарааллын "
"хавтас автоматаар бөглөгддөг."
"Шугам нь дамжлагууд ямар хугацаагаар хэдэн циклээр ашиглагдахыг илэрхийлдэг. "
"Хэрэв шугам байгаа бол гурав дахь үйлдвэрлэлийн дарааллын хавтас автоматаар "
"бөглөгддөг."
#. module: mrp
#: code:addons/mrp/mrp.py:505
@@ -1431,7 +1430,7 @@ msgstr "Үйлдвэрлэлийн дамжлагыг хайх"
#. module: mrp
#: view:mrp.bom:0
msgid "BoM Structure"
msgstr "Жорын бүтэц"
msgstr "Орцын бүтэц"
#. module: mrp
#: field:mrp.production,date_start:0
@@ -1541,7 +1540,7 @@ msgstr "БЗ Дугаар"
#: code:addons/mrp/mrp.py:505
#, python-format
msgid "Cannot delete a manufacturing order in state '%s'."
msgstr ""
msgstr "Үйлдвэрлэлийн захиалгын '%s' төлөвт устгах боломжгүй."
#. module: mrp
#: selection:mrp.production,state:0
@@ -1689,7 +1688,7 @@ msgstr "Нөөц"
#: help:mrp.bom,date_stop:0
msgid "Validity of this BoM or component. Keep empty if it's always valid."
msgstr ""
"Энэ жор эсвэл бүрэлдхүүний зөв эсэхийн шалгалт. Хэрэв байнга зөв бол хоосон "
"Орц эсвэл бүрэлдэхүүний зөв эсэхийн шалгалт. Хэрэв байнга зөв бол хоосон "
"үлдээнэ."
#. module: mrp
@@ -1710,7 +1709,7 @@ msgid ""
"operations and to plan future loads on work centers based on production "
"planning."
msgstr ""
"Барааг үйлдвэрлэх үйлдлийн жагсаалт (дамжлагын жагсаалт). Машрут нь "
"Барааг үйлдвэрлэх үйлдлийн жагсаалт (дамжлагын жагсаалт). Шугам нь "
"үйлдвэрлэлийн захиалга дээр үндэслэн дамжлагуудын өртөгийг тооцох, ажлын "
"ирээдүйн ачааллыг тооцоолох зэрэгт голчлон хэрэглэгддэг."
@@ -1816,8 +1815,8 @@ msgid ""
"are products themselves) can also have their own Bill of Material (multi-"
"level)."
msgstr ""
"Жор гэдэг нь барааны задаргаа юм. Бүрэлдхүүнүүд (мөн бараанууд) нь мөн "
"өөрийн жортой буюу олон түвшний жор байж болно."
"Орц гэдэг нь барааны задаргаа юм. Бүрэлдэхүүнүүд (мөн бараанууд) нь мөн "
"өөрийн орцтой буюу олон түвшний орц байж болно."
#. module: mrp
#: field:mrp.bom,company_id:0
@@ -1882,7 +1881,7 @@ msgstr "Бүрэлдэхүүнүүд"
#: report:bom.structure:0
#: model:ir.actions.report.xml,name:mrp.report_bom_structure
msgid "BOM Structure"
msgstr "Жорын бүтэц"
msgstr "Орцын бүтэц"
#. module: mrp
#: field:mrp.config.settings,module_mrp_jit:0
@@ -1902,7 +1901,7 @@ msgstr "Хүчинтэй байх эхлэл"
#. module: mrp
#: selection:mrp.bom,type:0
msgid "Normal BoM"
msgstr "Хэвийн жор"
msgstr "Хэвийн орц"
#. module: mrp
#: field:res.company,manufacturing_lead:0
@@ -1958,7 +1957,7 @@ msgid ""
"If the active field is set to False, it will allow you to hide the bills of "
"material without removing it."
msgstr ""
"Идэвхтэй талбар худал буюу тэмдэглэгдээгүй бол жорыг устгалгүйгээр нууна."
"Идэвхтэй талбар худал буюу тэмдэглэгдээгүй бол орцыг устгалгүйгээр нууна."
#. module: mrp
#: field:mrp.bom,product_rounding:0
@@ -2083,7 +2082,7 @@ msgstr ""
#. module: mrp
#: field:procurement.order,bom_id:0
msgid "BoM"
msgstr "Жор"
msgstr "Орц"
#. module: mrp
#: model:ir.model,name:mrp.model_report_mrp_inout
@@ -2145,12 +2144,12 @@ msgstr "Хангах болон Үйлдвэрлэх"
#. module: mrp
#: field:mrp.bom,bom_id:0
msgid "Parent BoM"
msgstr "Эцэг жор"
msgstr "Эцэг орц"
#. module: mrp
#: report:bom.structure:0
msgid "BOM Ref"
msgstr "Жорын код"
msgstr "Орцын код"
#. module: mrp
#: code:addons/mrp/mrp.py:765
@@ -2190,7 +2189,7 @@ msgstr "Тоо хэмжээг сонго"
#: view:product.product:0
#: field:product.product,bom_ids:0
msgid "Bill of Materials"
msgstr "Жорууд"
msgstr "Орцууд"
#. module: mrp
#: code:addons/mrp/mrp.py:610
@@ -2322,7 +2321,7 @@ msgstr ""
msgid ""
"a manufacturing\n"
" order"
msgstr ""
msgstr "үйлдвэрлэл"
#. module: mrp
#: field:mrp.config.settings,group_mrp_properties:0
@@ -2344,7 +2343,7 @@ msgstr "Үзүүлэлтийн бүлэгүүд"
#: view:mrp.routing:0
#: model:process.node,name:mrp.process_node_routing0
msgid "Routing"
msgstr "Маршрут"
msgstr "Шугам"
#. module: mrp
#: model:process.transition,note:mrp.process_transition_procurestockableproduct0
@@ -2390,8 +2389,8 @@ msgid ""
"the BOM, through a run of the schedulers (MRP)."
msgstr ""
"Түүхий эдийг хангахын тулд (худалдан авах эсвэл үйлдвэрлэх) үйлдвэрлэлийн "
"захиалга нь жорд тодорхойлогдсон бүрдлүүдээр татан авах захиалга үүсгэдэг ба "
"энэ нь товлогчийг ажиллахад үүсдэг."
"захиалга нь орцонд тодорхойлогдсон бүрдлүүдээр татан авах захиалга үүсгэдэг "
"ба энэ нь товлогчийг ажиллахад үүсдэг."
#. module: mrp
#: help:mrp.product_price,number:0
@@ -2423,7 +2422,7 @@ msgstr "Нөөцийн Амралт, Чөлөө"
#. module: mrp
#: help:mrp.bom,sequence:0
msgid "Gives the sequence order when displaying a list of bills of material."
msgstr "Жорын жагсаалтыг харуулах дэс дарааллыг өгдөг."
msgstr "Орцын жагсаалтыг харуулах дэс дарааллыг өгдөг."
#. module: mrp
#: model:ir.model,name:mrp.model_mrp_config_settings
+1 -1
View File
@@ -172,7 +172,7 @@ class wizard_user(osv.osv_memory):
@return: browse record of model res.users
"""
res_users = self.pool.get('res.users')
create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation
create_context = dict(context or {}, noshortcut=True, no_reset_password=True) # to prevent shortcut creation
values = {
'login': extract_email(wizard_user.email),
'partner_id': wizard_user.partner_id.id,
+1 -1
View File
@@ -34,7 +34,7 @@ with the effect of creating, editing and deleting either ways.
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ['images/invoice_task_work.jpeg', 'images/my_timesheet.jpeg', 'images/working_hour.jpeg'],
'depends': ['project', 'hr_timesheet_sheet', 'hr_timesheet_invoice', 'account_analytic_analysis'],
'depends': ['resource', 'project', 'hr_timesheet_sheet', 'hr_timesheet_invoice', 'account_analytic_analysis'],
'data': [
'security/ir.model.access.csv',
'security/project_timesheet_security.xml',
+8 -5
View File
@@ -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-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-12-28 14:12+0000\n"
"PO-Revision-Date: 2013-06-03 07:54+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:22+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: sale
#: model:res.groups,name:sale.group_analytic_accounting
@@ -89,6 +89,8 @@ msgid ""
"${(object.name or '').replace('/','_')}_${object.state == 'draft' and "
"'draft' or ''}"
msgstr ""
"${(object.name or '').replace('/','_')}_${object.state == 'draft' and "
"'draft' or ''}"
#. module: sale
#: view:sale.order.line:0
@@ -558,6 +560,7 @@ msgstr "Подготовить счета основанные на распис
#, python-format
msgid "You cannot cancel a sales order line that has already been invoiced."
msgstr ""
"Нельзя отменить позиции заказа продажи на которые был выставлен счет."
#. module: sale
#: view:account.invoice.report:0
@@ -1550,7 +1553,7 @@ msgstr "Искать позиции без счетов"
#. module: sale
#: model:ir.model,name:sale.model_account_config_settings
msgid "account.config.settings"
msgstr ""
msgstr "account.config.settings"
#. module: sale
#: sql_constraint:sale.order:0
@@ -1876,7 +1879,7 @@ msgstr ""
#. module: sale
#: view:res.partner:0
msgid "sale.group_delivery_invoice_address"
msgstr ""
msgstr "sale.group_delivery_invoice_address"
#. module: sale
#: code:addons/sale/sale.py:781
+2
View File
@@ -288,6 +288,8 @@
</record>
<!-- Confirm some Sale Orders-->
<workflow action="order_confirm" model="sale.order" ref="sale_order_4"/>
<workflow action="order_confirm" model="sale.order" ref="sale_order_7"/>
<record id="message_sale_1" model="mail.message">
+1 -1
View File
@@ -307,7 +307,7 @@
<filter icon="terp-dolar_ok!" string="To Invoice" domain="[('state','=','manual')]" help="Sales Order ready to be invoiced"/>
<filter icon="terp-dolar_ok!" string="Done" domain="[('state','=','done')]" help="Sales Order done"/>
<separator/>
<filter string="My Sales Orders" domain="[('user_id','=',uid)]" help="My Sales Orders" icon="terp-personal" name="my_sale_orders_filter"/>
<filter string="My" domain="[('user_id','=',uid)]" help="My Sales Orders" icon="terp-personal" name="my_sale_orders_filter"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="user_id"/>
<field name="project_id"/>
+4 -4
View File
@@ -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-12-21 17:06+0000\n"
"PO-Revision-Date: 2010-12-25 22:14+0000\n"
"PO-Revision-Date: 2013-06-03 08:05+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:32+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: sale_analytic_plans
#: field:sale.order.line,analytics_id:0
@@ -24,7 +24,7 @@ msgstr "Разнесение аналитики"
#. module: sale_analytic_plans
#: model:ir.model,name:sale_analytic_plans.model_sale_order
msgid "Sales Order"
msgstr ""
msgstr "Заказ продаж"
#. module: sale_analytic_plans
#: model:ir.model,name:sale_analytic_plans.model_sale_order_line
+5 -1
View File
@@ -47,7 +47,11 @@ modules.
'security/ir.model.access.csv',
'report/sale_crm_account_invoice_report_view.xml',
],
'demo': [],
'js': [
'static/lib/justgage.js',
'static/src/js/sale_crm.js',
],
'demo': ['sale_crm_demo.xml'],
'test': ['test/sale_crm.yml'],
'installable': True,
'auto_install': True,
+16 -16
View File
@@ -7,20 +7,20 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:06+0000\n"
"PO-Revision-Date: 2011-03-23 13:50+0000\n"
"PO-Revision-Date: 2013-06-03 08:05+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:10+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: sale_crm
#: code:addons/sale_crm/wizard/crm_make_sale.py:90
#, python-format
msgid "Insufficient Data!"
msgstr ""
msgstr "Недостаточно данных!"
#. module: sale_crm
#: view:crm.lead:0
@@ -31,12 +31,12 @@ msgstr "Преобразовать в предложение"
#. module: sale_crm
#: model:ir.model,name:sale_crm.model_account_invoice_report
msgid "Invoices Statistics"
msgstr ""
msgstr "Статистика по счетам"
#. module: sale_crm
#: field:crm.make.sale,close:0
msgid "Mark Won"
msgstr ""
msgstr "Отметить \"Выиграна\""
#. module: sale_crm
#: field:res.users,default_section_id:0
@@ -51,23 +51,23 @@ msgstr "Мои отделы продаж"
#. module: sale_crm
#: model:ir.model,name:sale_crm.model_res_users
msgid "Users"
msgstr ""
msgstr "Пользователи"
#. module: sale_crm
#: help:crm.make.sale,close:0
msgid ""
"Check this to close the opportunity after having created the sales order."
msgstr ""
msgstr "Отметьте, для закрытия предложения после создания заказа продажи."
#. module: sale_crm
#: model:mail.message.subtype,name:sale_crm.mt_salesteam_order_sent
msgid "Quotation Send"
msgstr ""
msgstr "Отправить предложение"
#. module: sale_crm
#: field:sale.order,categ_ids:0
msgid "Categories"
msgstr ""
msgstr "Категории"
#. module: sale_crm
#: code:addons/sale_crm/wizard/crm_make_sale.py:124
@@ -94,7 +94,7 @@ msgstr "Продать"
#. module: sale_crm
#: model:ir.model,name:sale_crm.model_account_invoice
msgid "Invoice"
msgstr ""
msgstr "Счет"
#. module: sale_crm
#: code:addons/sale_crm/wizard/crm_make_sale.py:93
@@ -106,7 +106,7 @@ msgstr "Предложение: %s"
#: code:addons/sale_crm/wizard/crm_make_sale.py:110
#, python-format
msgid "Opportunity has been <b>converted</b> to the quotation <em>%s</em>."
msgstr ""
msgstr "Предложение <b>преобразовано</b> в заявку <em>%s</em>."
#. module: sale_crm
#: field:crm.make.sale,shop_id:0
@@ -117,12 +117,12 @@ msgstr "Магазин"
#: code:addons/sale_crm/wizard/crm_make_sale.py:90
#, python-format
msgid "No addresse(s) defined for this customer."
msgstr ""
msgstr "Не задан адрес для этого заказчика"
#. module: sale_crm
#: model:mail.message.subtype,name:sale_crm.mt_salesteam_order_confirmed
msgid "Sales Order Confirmed"
msgstr ""
msgstr "Заказ продаж подтвержден"
#. module: sale_crm
#: view:account.invoice:0
@@ -136,7 +136,7 @@ msgstr "Отдел продаж"
#. module: sale_crm
#: view:crm.lead:0
msgid "Create Quotation"
msgstr ""
msgstr "Создать заявку"
#. module: sale_crm
#: model:ir.actions.act_window,name:sale_crm.action_crm_make_sale
@@ -156,7 +156,7 @@ msgstr "Заказ продаж"
#. module: sale_crm
#: view:crm.make.sale:0
msgid "or"
msgstr ""
msgstr "или"
#~ msgid "Create"
#~ msgstr "Создать"
+43 -20
View File
@@ -19,7 +19,10 @@
#
##############################################################################
from datetime import datetime
from datetime import date
from dateutil import relativedelta
from openerp import tools
from openerp.osv import osv, fields
@@ -41,31 +44,51 @@ class sale_order(osv.osv):
class crm_case_section(osv.osv):
_inherit = 'crm.case.section'
def _get_sum_month_invoice(self, cr, uid, ids, field_name, arg, context=None):
res = dict.fromkeys(ids, 0)
def _get_sale_orders_data(self, cr, uid, ids, field_name, arg, context=None):
obj = self.pool.get('sale.order')
res = dict.fromkeys(ids, False)
month_begin = date.today().replace(day=1)
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
for id in ids:
res[id] = dict()
created_domain = [('section_id', '=', id), ('state', 'in', ['draft', 'sent']), ('date_order', '>=', groupby_begin)]
res[id]['monthly_quoted'] = self.__get_bar_values(cr, uid, obj, created_domain, ['amount_total', 'date_order'], 'amount_total', 'date_order', context=context)
validated_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'sent']), ('date_confirm', '>=', groupby_begin)]
res[id]['monthly_confirmed'] = self.__get_bar_values(cr, uid, obj, validated_domain, ['amount_total', 'date_confirm'], 'amount_total', 'date_confirm', context=context)
return res
def _get_invoices_data(self, cr, uid, ids, field_name, arg, context=None):
obj = self.pool.get('account.invoice.report')
when = datetime.today()
for section_id in ids:
invoice_ids = obj.search(cr, uid, [("section_id", "=", section_id), ('state', 'not in', ['draft', 'cancel']), ('year', '=', when.year), ('month', '=', when.month > 9 and when.month or "0%s" % when.month)], context=context)
for invoice in obj.browse(cr, uid, invoice_ids, context=context):
res[section_id] += invoice.price_total
res = dict.fromkeys(ids, False)
month_begin = date.today().replace(day=1)
groupby_begin = (month_begin + relativedelta.relativedelta(months=-4)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
for id in ids:
created_domain = [('section_id', '=', id), ('state', 'not in', ['draft', 'cancel']), ('date', '>=', groupby_begin)]
res[id] = self.__get_bar_values(cr, uid, obj, created_domain, ['price_total', 'date'], 'price_total', 'date', context=context)
return res
_columns = {
'quotation_ids': fields.one2many('sale.order', 'section_id',
string='Quotations', readonly=True,
domain=[('state', 'in', ['draft', 'sent', 'cancel'])]),
'sale_order_ids': fields.one2many('sale.order', 'section_id',
string='Sale Orders', readonly=True,
domain=[('state', 'not in', ['draft', 'sent', 'cancel'])]),
'invoice_ids': fields.one2many('account.invoice', 'section_id',
string='Invoices', readonly=True,
domain=[('state', 'not in', ['draft', 'cancel'])]),
'sum_month_invoice': fields.function(_get_sum_month_invoice,
string='Total invoiced this month',
type='integer', readonly=True),
'invoiced_forecast': fields.integer(string='Invoice Forecast',
help="Forecast of the invoice revenue for the current month. This is the amount the sales \n"
"team should invoice this month. It is used to compute the progression ratio \n"
" of the current and forecast revenue on the kanban view."),
'invoiced_target': fields.integer(string='Invoice Target',
help="Target of invoice revenue for the current month. This is the amount the sales \n"
"team estimates to be able to invoice this month."),
'monthly_quoted': fields.function(_get_sale_orders_data,
type='string', readonly=True, multi='_get_sale_orders_data',
string='Rate of created quotation per duration'),
'monthly_confirmed': fields.function(_get_sale_orders_data,
type='string', readonly=True, multi='_get_sale_orders_data',
string='Rate of validate sales orders per duration'),
'monthly_invoiced': fields.function(_get_invoices_data,
type='string', readonly=True,
string='Rate of sent invoices per duration'),
}
def action_forecast(self, cr, uid, id, value, context=None):
return self.write(cr, uid, [id], {'invoiced_forecast': value}, context=context)
class res_users(osv.Model):
_inherit = 'res.users'
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="crm.case.section" id="crm.section_sales_department">
<field name="invoiced_forecast">52700</field>
<field name="invoiced_target">60000</field>
</record>
<record model="crm.case.section" id="crm.crm_case_section_1">
<field name="name">Indirect Sales</field>
<field name="code">IM</field>
<field name="invoiced_forecast">36000</field>
<field name="invoiced_target">40000</field>
</record>
<!-- Invoice for Direct Marketing -->
<record id="test_crm_sale_invoice_1" model="account.invoice">
<field name="currency_id" ref="base.EUR"/>
<field name="company_id" ref="base.main_company"/>
<field name="partner_id" ref="base.res_partner_1"/>
<field name="journal_id" ref="account.sales_journal"/>
<field name="section_id" ref="crm.section_sales_department"/>
<field name="state">draft</field>
<field name="type">out_invoice</field>
<field name="account_id" ref="account.a_recv"/>
<field name="name">Test invoice 1</field>
</record>
<record id="test_crm_sale_invoice_1_line_1" model="account.invoice.line">
<field name="name">Basic computer with Dvorak keyboard and left-handed mouse</field>
<field name="invoice_id" ref="test_crm_sale_invoice_1"/>
<field name="price_unit">250</field>
<field name="quantity">1</field>
<field name="account_id" ref="account.a_sale"/>
</record>
<record id="test_crm_sale_invoice_1_line_2" model="account.invoice.line">
<field name="name">Little server with raid 1 and 512ECC ram</field>
<field name="invoice_id" ref="test_crm_sale_invoice_1"/>
<field name="price_unit">800</field>
<field name="quantity">2</field>
<field name="account_id" ref="account.a_sale"/>
</record>
<record id="test_crm_sale_invoice_1_line_2" model="account.invoice.line">
<field name="name">Server with raid 10 and 2048ECC ram</field>
<field name="invoice_id" ref="test_crm_sale_invoice_1"/>
<field name="price_unit">4800</field>
<field name="quantity">4</field>
<field name="account_id" ref="account.a_sale"/>
</record>
<workflow action="invoice_open" model="account.invoice" ref="test_crm_sale_invoice_1"/>
<function model="account.invoice" name="pay_and_reconcile">
<!-- ids = --> <value eval="[ref('test_crm_sale_invoice_1')]"/>
<!-- pay_amount = --> <value eval="1850"/>
<!-- pay_account_id = --> <value eval="ref('account.cash')"/>
<!-- period_id = --> <value eval="ref('account.period_' + str(int(time.strftime('%m'))))"/>
<!-- pay_journal_id = --> <value eval="ref('account.bank_journal')"/>
<!-- writeoff_acc_id = --> <value eval="ref('account.cash')"/>
<!-- writeoff_period_id = --> <value eval="ref('account.period_' + str(int(time.strftime('%m'))))"/>
<!-- writeoff_journal_id = --> <value eval="ref('account.bank_journal')"/>
<!-- context = --> <value eval="{}"/>
<!-- name = --> <value eval="str('Payment from ASUStek')"/>
</function>
<!-- Invoice for Indirect Marketing -->
<record id="test_crm_sale_invoice_2" model="account.invoice">
<field name="currency_id" ref="base.EUR"/>
<field name="company_id" ref="base.main_company"/>
<field name="partner_id" ref="base.res_partner_1"/>
<field name="journal_id" ref="account.sales_journal"/>
<field name="section_id" ref="crm.crm_case_section_1"/>
<field name="state">draft</field>
<field name="type">out_invoice</field>
<field name="account_id" ref="account.a_recv"/>
<field name="name">Test invoice 1</field>
</record>
<record id="test_crm_sale_invoice_2_line_1" model="account.invoice.line">
<field name="name">Basic formation with Dvorak</field>
<field name="invoice_id" ref="test_crm_sale_invoice_2"/>
<field name="price_unit">500</field>
<field name="quantity">1</field>
<field name="account_id" ref="account.a_sale"/>
</record>
<workflow action="invoice_open" model="account.invoice" ref="test_crm_sale_invoice_2"/>
<function model="account.invoice" name="pay_and_reconcile">
<!-- ids = --> <value eval="[ref('test_crm_sale_invoice_2')]"/>
<!-- pay_amount = --> <value eval="500"/>
<!-- pay_account_id = --> <value eval="ref('account.cash')"/>
<!-- period_id = --> <value eval="ref('account.period_' + str(int(time.strftime('%m'))))"/>
<!-- pay_journal_id = --> <value eval="ref('account.bank_journal')"/>
<!-- writeoff_acc_id = --> <value eval="ref('account.cash')"/>
<!-- writeoff_period_id = --> <value eval="ref('account.period_' + str(int(time.strftime('%m'))))"/>
<!-- writeoff_journal_id = --> <value eval="ref('account.bank_journal')"/>
<!-- context = --> <value eval="{}"/>
<!-- name = --> <value eval="str('Payment from ASUStek')"/>
</function>
<record id="sale.sale_order_1" model="sale.order">
<field name="section_id" ref="crm.section_sales_department"/>
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="sale.sale_order_2" model="sale.order">
<field name="section_id" ref="crm.section_sales_department"/>
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="sale.sale_order_3" model="sale.order">
<field name="section_id" ref="crm.section_sales_department"/>
</record>
<record id="sale.sale_order_4" model="sale.order">
<field name="section_id" ref="crm.section_sales_department"/>
</record>
<record id="sale.sale_order_5" model="sale.order">
<field name="section_id" ref="crm.crm_case_section_1"/>
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="sale.sale_order_6" model="sale.order">
<field name="section_id" ref="crm.crm_case_section_1"/>
</record>
<record id="sale.sale_order_7" model="sale.order">
<field name="section_id" ref="crm.section_sales_department"/>
<field name="date_confirm" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
</record>
<record id="sale.sale_order_8" model="sale.order">
<field name="section_id" ref="crm.crm_case_section_1"/>
</record>
</data>
</openerp>
+59 -30
View File
@@ -43,7 +43,7 @@
<filter string="My Sales Team(s)"
icon="terp-personal+"
domain="[('section_id.user_id','=',uid)]"
help="My Sales Team(s)"/>
help="My Sales Team(s)" groups="base.group_multi_salesteams"/>
</xpath>
<xpath expr="//field[@name='user_id']" position="after">
<field name="section_id" string="Sales Team" groups="base.group_multi_salesteams"/>
@@ -75,7 +75,7 @@
<field name="section_id"/>
</xpath>
<xpath expr="//group/filter[@string='Due Date']" position="after">
<filter string="Sales Team" domain="[]" context="{'group_by':'section_id'}"/>
<filter string="Sales Team" domain="[]" context="{'group_by':'section_id'}" groups="base.group_multi_salesteams"/>
</xpath>
</field>
</record>
@@ -101,7 +101,7 @@
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//field[@name='email']" position="after">
<xpath expr="//field[@name='tz']" position="after">
<field name="default_section_id"/>
</xpath>
</data>
@@ -135,7 +135,6 @@
<field name="context">{
'search_default_section_id': [active_id],
'default_section_id': active_id,
'search_default_my_sale_orders_filter': 1,
}
</field>
<field name="help" type="html">
@@ -158,8 +157,8 @@
<field name="view_mode">tree,form,calendar,graph</field>
<field name="context">{
'search_default_section_id': [active_id],
'default_section_id': active_id, 'show_address': 1,
'search_default_my_sale_orders_filter': 1
'default_section_id': active_id,
'show_address': 1,
}
</field>
<field name="domain">[('state','in',('draft','sent','cancel'))]</field>
@@ -190,7 +189,7 @@
('type', '=', 'out_invoice')]</field>
<field name="context">{
'search_default_section_id': [active_id],
'default_section_id': active_id},
'default_section_id': active_id,
'default_type':'out_invoice',
'type':'out_invoice',
'journal_type': 'sale',
@@ -212,38 +211,68 @@
<field name="act_window_id" ref="sale_crm.action_invoice_salesteams"/>
</record>
<record id="crm_case_section_salesteams_view_form" model="ir.ui.view">
<field name="name">crm.case.section.form</field>
<field name="model">crm.case.section</field>
<field name="inherit_id" ref="crm.crm_case_section_view_form"/>
<field name="arch" type="xml">
<data>
<xpath expr="//field[@name='code']" position="after">
<field name="invoiced_target"/>
<field name="invoiced_forecast"/>
</xpath>
</data>
</field>
</record>
<record id="crm_case_section_salesteams_view_kanban" model="ir.ui.view">
<field name="name">crm.case.section.kanban</field>
<field name="model">crm.case.section</field>
<field name="inherit_id" ref="crm.crm_case_section_salesteams_view_kanban"/>
<field name="arch" type="xml">
<data>
<xpath expr="//field[@name='open_opportunity_ids']" position="after">
<field name="quotation_ids"/>
<field name="sale_order_ids"/>
<field name="invoice_ids"/>
<xpath expr="//field[@name='name']" position="after">
<field name="monthly_quoted"/>
<field name="monthly_confirmed"/>
<field name="monthly_invoiced"/>
<field name="invoiced_forecast"/>
<field name="invoiced_target"/>
</xpath>
<xpath expr="//div[@class='oe_items_list']" position="inside">
<a name="%(action_quotations_salesteams)d" type="action">
<t t-raw="record.quotation_ids.raw_value.length"/>
<t t-if="record.quotation_ids.raw_value.length &gt;= 2">Quotations</t>
<t t-if="record.quotation_ids.raw_value.length &lt; 2">Quotation</t>
</a>
<a name="%(action_orders_salesteams)d" type="action">
<t t-raw="record.sale_order_ids.raw_value.length"/>
<t t-if="record.sale_order_ids.raw_value.length &gt;= 2">Sales Orders</t>
<t t-if="record.sale_order_ids.raw_value.length &lt; 2">Sales Order</t>
</a>
<a name="%(action_invoice_salesteams)d" type="action" groups="account.group_account_invoice">
<t t-raw="record.invoice_ids.raw_value.length"/>
<t t-if="record.invoice_ids.raw_value.length &gt;= 2">Invoices</t>
<t t-if="record.invoice_ids.raw_value.length &lt; 2">Invoice</t>
</a>
<xpath expr="//div[@class='oe_salesteams_leads']" position="after">
<div class="oe_salesteams_orders">
<a name="%(action_orders_salesteams)d" type="action">Sales Orders</a>
<a name="%(sale.action_order_report_all)d" type="action" class="oe_sparkline_bar_link">
<field name="monthly_confirmed" widget="sparkline_bar">
Revenue of confirmed sales orders per month.<br/>Click the acces to Sales Analysis
</field>
</a>
</div>
</xpath>
<xpath expr="//div[@class='oe_salesteams_opportunities']" position="after">
<div class="oe_salesteams_invoices">
<a name="%(action_invoice_salesteams)d" type="action" groups="account.group_account_invoice">Invoices</a>
<a name="%(account.action_account_invoice_report_all)d" type="action" class="oe_sparkline_bar_link">
<field name="monthly_invoiced" widget="sparkline_bar">
Revenue of sent invoices per month.<br/>Click to see a detailed analysis of invoices.
</field>
</a>
</div>
<div class="oe_salesteams_quotations">
<a name="%(action_quotations_salesteams)d" type="action" class="oe_sparkline_bar_link">Quotations</a>
<a name="%(sale.action_order_report_all)d" type="action" class="oe_sparkline_bar_link">
<field name="monthly_quoted" widget="sparkline_bar">
Revenue of created quotation per month.<br/>Click to see a detailed analysis of sales.
</field>
</a>
</div>
</xpath>
<xpath expr="//div[@class='oe_items_list']" position="after">
<div class="oe_center">
<div class="oe_sum"><field name="sum_month_invoice"/></div>
<div class="oe_subsum">Invoiced this month</div>
<div class="oe_center" t-if="record.invoiced_target.raw_value">
<field name="monthly_invoiced" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'invoiced_target'}">Invoiced</field>
<field name="invoiced_forecast" widget="gage" style="width:160px; height: 120px;" options="{'max_field': 'invoiced_target', 'action_change': 'action_forecast'}">Forecast</field>
</div>
<div class="oe_center" style="color:#bbbbbb;" t-if="!record.invoiced_target.raw_value">
<br/>Define an invoicing target in the sales team settings to see the period's achievement and forecast at a glance.
</div>
</xpath>
</data>
+883
View File
@@ -0,0 +1,883 @@
/**
* JustGage - this is work-in-progress, unreleased, unofficial code, so it might not work top-notch :)
* Check http://www.justgage.com for official releases
* Licensed under MIT.
* @author Bojan Djuricic (@Toorshia)
*
* LATEST UPDATES
* -----------------------------
* April 01, 2013.
* -----------------------------
* fix - https://github.com/toorshia/justgage/issues/46
* -----------------------------
* March 26, 2013.
* -----------------------------
* customSectors - define specific color for value range (0-10 : red, 10-30 : blue etc.)
* -----------------------------
* March 23, 2013.
* -----------------------------
* counter - option to animate value in counting fashion
* fix - https://github.com/toorshia/justgage/issues/45
* -----------------------------
* March 13, 2013.
* -----------------------------
* refresh method - added optional 'max' parameter to use when you need to update max value
* -----------------------------
* February 26, 2013.
* -----------------------------
* decimals - option to define/limit number of decimals when not using humanFriendly or customRenderer to display value
* fixed a missing parameters bug when calling generateShadow() for IE < 9
* -----------------------------
* December 31, 2012.
* -----------------------------
* fixed text y-position for hidden divs - workaround for Raphael <tspan> 'dy' bug - https://github.com/DmitryBaranovskiy/raphael/issues/491
* 'show' parameters, like showMinMax are now 'hide' because I am lame developer - please update these in your setups
* Min and Max labels are now auto-off when in donut mode
* Start angle in donut mode is now 90
* donutStartAngle - option to define start angle for donut
* -----------------------------
* November 25, 2012.
* -----------------------------
* Option to define custom rendering function for displayed value
* -----------------------------
* November 19, 2012.
* -----------------------------
* Config.value is now updated after gauge refresh
* -----------------------------
* November 13, 2012.
* -----------------------------
* Donut display mode added
* Option to hide value label
* Option to enable responsive gauge size
* Removed default title attribute
* Option to accept min and max defined as string values
* Option to configure value symbol
* Fixed bad aspect ratio calculations
* Option to configure minimum font size for all texts
* Option to show shorthand big numbers (human friendly)
*/
JustGage = function(config) {
if (!config.id) {alert("Missing id parameter for gauge!"); return false;}
if (!config.node) {
if (!document.getElementById(config.id)) {alert("No element with id: \""+config.id+"\" found!"); return false;}
config.node = document.getElementById(config.id);
}
var obj = this;
// configurable parameters
obj.config =
{
// id : string
// this is container element id
id : config.id,
// node : string
// the node to use instead of DOM
node : config.node,
// title : string
// gauge title
title : (config.title) ? config.title : "",
// titleFontColor : string
// color of gauge title
titleFontColor : (config.titleFontColor) ? config.titleFontColor : "#999999",
// value : int
// value gauge is showing
value : (config.value) ? config.value : 0,
// valueFontColor : string
// color of label showing current value
valueFontColor : (config.valueFontColor) ? config.valueFontColor : "#010101",
// symbol : string
// special symbol to show next to value
symbol : (config.symbol) ? config.symbol : "",
// min : int
// min value
min : (config.min) ? parseFloat(config.min) : 0,
// max : int
// max value
max : (config.max) ? parseFloat(config.max) : 100,
// humanFriendlyDecimal : int
// number of decimal places for our human friendly number to contain
humanFriendlyDecimal : (config.humanFriendlyDecimal) ? config.humanFriendlyDecimal : 0,
// textRenderer: func
// function applied before rendering text
textRenderer : (config.textRenderer) ? config.textRenderer : null,
// gaugeWidthScale : float
// width of the gauge element
gaugeWidthScale : (config.gaugeWidthScale) ? config.gaugeWidthScale : 1.0,
// gaugeColor : string
// background color of gauge element
gaugeColor : (config.gaugeColor) ? config.gaugeColor : "#edebeb",
// label : string
// text to show below value
label : (config.label) ? config.label : "",
// labelFontColor : string
// color of label showing label under value
labelFontColor : (config.labelFontColor) ? config.labelFontColor : "#b3b3b3",
// shadowOpacity : int
// 0 ~ 1
shadowOpacity : (config.shadowOpacity) ? config.shadowOpacity : 0.2,
// shadowSize: int
// inner shadow size
shadowSize : (config.shadowSize) ? config.shadowSize : 5,
// shadowVerticalOffset : int
// how much shadow is offset from top
shadowVerticalOffset : (config.shadowVerticalOffset) ? config.shadowVerticalOffset : 3,
// levelColors : string[]
// colors of indicator, from lower to upper, in RGB format
levelColors : (config.levelColors) ? config.levelColors : [
"#a9d70b",
"#f9c802",
"#ff0000"
],
// startAnimationTime : int
// length of initial animation
startAnimationTime : (config.startAnimationTime) ? config.startAnimationTime : 700,
// startAnimationType : string
// type of initial animation (linear, >, <, <>, bounce)
startAnimationType : (config.startAnimationType) ? config.startAnimationType : ">",
// refreshAnimationTime : int
// length of refresh animation
refreshAnimationTime : (config.refreshAnimationTime) ? config.refreshAnimationTime : 700,
// refreshAnimationType : string
// type of refresh animation (linear, >, <, <>, bounce)
refreshAnimationType : (config.refreshAnimationType) ? config.refreshAnimationType : ">",
// donutStartAngle : int
// angle to start from when in donut mode
donutStartAngle : (config.donutStartAngle) ? config.donutStartAngle : 90,
// valueMinFontSize : int
// absolute minimum font size for the value
valueMinFontSize : config.valueMinFontSize || 16,
// titleMinFontSize
// absolute minimum font size for the title
titleMinFontSize : config.titleMinFontSize || 10,
// labelMinFontSize
// absolute minimum font size for the label
labelMinFontSize : config.labelMinFontSize || 10,
// minLabelMinFontSize
// absolute minimum font size for the minimum label
minLabelMinFontSize : config.minLabelMinFontSize || 10,
// maxLabelMinFontSize
// absolute minimum font size for the maximum label
maxLabelMinFontSize : config.maxLabelMinFontSize || 10,
// hideValue : bool
// hide value text
hideValue : (config.hideValue) ? config.hideValue : false,
// hideMinMax : bool
// hide min and max values
hideMinMax : (config.hideMinMax) ? config.hideMinMax : false,
// hideInnerShadow : bool
// hide inner shadow
hideInnerShadow : (config.hideInnerShadow) ? config.hideInnerShadow : false,
// humanFriendly : bool
// convert large numbers for min, max, value to human friendly (e.g. 1234567 -> 1.23M)
humanFriendly : (config.humanFriendly) ? config.humanFriendly : false,
// noGradient : bool
// whether to use gradual color change for value, or sector-based
noGradient : (config.noGradient) ? config.noGradient : false,
// donut : bool
// show full donut gauge
donut : (config.donut) ? config.donut : false,
// relativeGaugeSize : bool
// whether gauge size should follow changes in container element size
relativeGaugeSize : (config.relativeGaugeSize) ? config.relativeGaugeSize : false,
// counter : bool
// animate level number change
counter : (config.counter) ? config.counter : false,
// decimals : int
// number of digits after floating point
decimals : (config.decimals) ? config.decimals : 0,
// customSectors : [] of objects
// number of digits after floating point
customSectors : (config.customSectors) ? config.customSectors : []
};
// variables
var
canvasW,
canvasH,
widgetW,
widgetH,
aspect,
dx,
dy,
titleFontSize,
titleX,
titleY,
valueFontSize,
valueX,
valueY,
labelFontSize,
labelX,
labelY,
minFontSize,
minX,
minY,
maxFontSize,
maxX,
maxY;
// overflow values
if (this.config.value > this.config.max) this.config.value = this.config.max;
if (this.config.value < this.config.min) this.config.value = this.config.min;
this.originalValue = config.value;
// canvas
this.canvas = Raphael(this.config.node, "100%", "100%");
if (this.config.relativeGaugeSize === true) {
this.canvas.setViewBox(0, 0, 200, 150, true);
}
// canvas dimensions
if (this.config.relativeGaugeSize === true) {
canvasW = 200;
canvasH = 150;
} else {
canvasW = getStyle(this.config.node, "width").slice(0, -2) * 1;
canvasH = getStyle(this.config.node, "height").slice(0, -2) * 1;
}
// widget dimensions
if (this.config.donut === true) {
// DONUT *******************************
// width more than height
if(canvasW > canvasH) {
widgetH = canvasH;
widgetW = widgetH;
// width less than height
} else if (canvasW < canvasH) {
widgetW = canvasW;
widgetH = widgetW;
// if height don't fit, rescale both
if(widgetH > canvasH) {
aspect = widgetH / canvasH;
widgetH = widgetH / aspect;
widgetW = widgetH / aspect;
}
// equal
} else {
widgetW = canvasW;
widgetH = widgetW;
}
// delta
dx = (canvasW - widgetW)/2;
dy = (canvasH - widgetH)/2;
// title
titleFontSize = ((widgetH / 8) > 10) ? (widgetH / 10) : 10;
titleX = dx + widgetW / 2;
titleY = dy + widgetH / 11;
// value
valueFontSize = ((widgetH / 6.4) > 16) ? (widgetH / 5.4) : 18;
valueX = dx + widgetW / 2;
if(this.config.label !== '') {
valueY = dy + widgetH / 1.85;
} else {
valueY = dy + widgetH / 1.7;
}
// label
labelFontSize = ((widgetH / 16) > 10) ? (widgetH / 16) : 10;
labelX = dx + widgetW / 2;
labelY = valueY + labelFontSize;
// min
minFontSize = ((widgetH / 16) > 10) ? (widgetH / 16) : 10;
minX = dx + (widgetW / 10) + (widgetW / 6.666666666666667 * this.config.gaugeWidthScale) / 2 ;
minY = labelY;
// max
maxFontSize = ((widgetH / 16) > 10) ? (widgetH / 16) : 10;
maxX = dx + widgetW - (widgetW / 10) - (widgetW / 6.666666666666667 * this.config.gaugeWidthScale) / 2 ;
maxY = labelY;
} else {
// HALF *******************************
// width more than height
if(canvasW > canvasH) {
widgetH = canvasH;
widgetW = widgetH * 1.25;
//if width doesn't fit, rescale both
if(widgetW > canvasW) {
aspect = widgetW / canvasW;
widgetW = widgetW / aspect;
widgetH = widgetH / aspect;
}
// width less than height
} else if (canvasW < canvasH) {
widgetW = canvasW;
widgetH = widgetW / 1.25;
// if height don't fit, rescale both
if(widgetH > canvasH) {
aspect = widgetH / canvasH;
widgetH = widgetH / aspect;
widgetW = widgetH / aspect;
}
// equal
} else {
widgetW = canvasW;
widgetH = widgetW * 0.75;
}
// delta
dx = (canvasW - widgetW)/2;
dy = (canvasH - widgetH)/2;
// title
titleFontSize = ((widgetH / 8) > this.config.titleMinFontSize) ? (widgetH / 10) : this.config.titleMinFontSize;
titleX = dx + widgetW / 2;
titleY = dy + widgetH / 6.4;
// value
valueFontSize = ((widgetH / 6.5) > this.config.valueMinFontSize) ? (widgetH / 6.5) : this.config.valueMinFontSize;
valueX = dx + widgetW / 2;
valueY = dy + widgetH / 1.275;
// label
labelFontSize = ((widgetH / 16) > this.config.labelMinFontSize) ? (widgetH / 16) : this.config.labelMinFontSize;
labelX = dx + widgetW / 2;
labelY = valueY + valueFontSize / 2 + 5;
// min
minFontSize = ((widgetH / 16) > this.config.minLabelMinFontSize) ? (widgetH / 16) : this.config.minLabelMinFontSize;
minX = dx + (widgetW / 10) + (widgetW / 6.666666666666667 * this.config.gaugeWidthScale) / 2 ;
minY = labelY;
// max
maxFontSize = ((widgetH / 16) > this.config.maxLabelMinFontSize) ? (widgetH / 16) : this.config.maxLabelMinFontSize;
maxX = dx + widgetW - (widgetW / 10) - (widgetW / 6.666666666666667 * this.config.gaugeWidthScale) / 2 ;
maxY = labelY;
}
// parameters
this.params = {
canvasW : canvasW,
canvasH : canvasH,
widgetW : widgetW,
widgetH : widgetH,
dx : dx,
dy : dy,
titleFontSize : titleFontSize,
titleX : titleX,
titleY : titleY,
valueFontSize : valueFontSize,
valueX : valueX,
valueY : valueY,
labelFontSize : labelFontSize,
labelX : labelX,
labelY : labelY,
minFontSize : minFontSize,
minX : minX,
minY : minY,
maxFontSize : maxFontSize,
maxX : maxX,
maxY : maxY
};
// var clear
canvasW, canvasH, widgetW, widgetH, aspect, dx, dy, titleFontSize, titleX, titleY, valueFontSize, valueX, valueY, labelFontSize, labelX, labelY, minFontSize, minX, minY, maxFontSize, maxX, maxY = null
// pki - custom attribute for generating gauge paths
this.canvas.customAttributes.pki = function (value, min, max, w, h, dx, dy, gws, donut) {
var alpha, Ro, Ri, Cx, Cy, Xo, Yo, Xi, Yi, path;
if (donut) {
alpha = (1 - 2 * (value - min) / (max - min)) * Math.PI;
Ro = w / 2 - w / 7;
Ri = Ro - w / 6.666666666666667 * gws;
Cx = w / 2 + dx;
Cy = h / 1.95 + dy;
Xo = w / 2 + dx + Ro * Math.cos(alpha);
Yo = h - (h - Cy) + 0 - Ro * Math.sin(alpha);
Xi = w / 2 + dx + Ri * Math.cos(alpha);
Yi = h - (h - Cy) + 0 - Ri * Math.sin(alpha);
path += "M" + (Cx - Ri) + "," + Cy + " ";
path += "L" + (Cx - Ro) + "," + Cy + " ";
if (value > ((max - min) / 2)) {
path += "A" + Ro + "," + Ro + " 0 0 1 " + (Cx + Ro) + "," + Cy + " ";
}
path += "A" + Ro + "," + Ro + " 0 0 1 " + Xo + "," + Yo + " ";
path += "L" + Xi + "," + Yi + " ";
if (value > ((max - min) / 2)) {
path += "A" + Ri + "," + Ri + " 0 0 0 " + (Cx + Ri) + "," + Cy + " ";
}
path += "A" + Ri + "," + Ri + " 0 0 0 " + (Cx - Ri) + "," + Cy + " ";
path += "Z ";
return { path: path };
} else {
alpha = (1 - (value - min) / (max - min)) * Math.PI;
Ro = w / 2 - w / 10;
Ri = Ro - w / 6.666666666666667 * gws;
Cx = w / 2 + dx;
Cy = h / 1.25 + dy;
Xo = w / 2 + dx + Ro * Math.cos(alpha);
Yo = h - (h - Cy) + 0 - Ro * Math.sin(alpha);
Xi = w / 2 + dx + Ri * Math.cos(alpha);
Yi = h - (h - Cy) + 0 - Ri * Math.sin(alpha);
path += "M" + (Cx - Ri) + "," + Cy + " ";
path += "L" + (Cx - Ro) + "," + Cy + " ";
path += "A" + Ro + "," + Ro + " 0 0 1 " + Xo + "," + Yo + " ";
path += "L" + Xi + "," + Yi + " ";
path += "A" + Ri + "," + Ri + " 0 0 0 " + (Cx - Ri) + "," + Cy + " ";
path += "Z ";
return { path: path };
}
// var clear
alpha, Ro, Ri, Cx, Cy, Xo, Yo, Xi, Yi, path = null;
};
// gauge
this.gauge = this.canvas.path().attr({
"stroke": "none",
"fill": this.config.gaugeColor,
pki: [this.config.max, this.config.min, this.config.max, this.params.widgetW, this.params.widgetH, this.params.dx, this.params.dy, this.config.gaugeWidthScale, this.config.donut]
});
this.gauge.id = this.config.id+"-gauge";
// level
this.level = this.canvas.path().attr({
"stroke": "none",
"fill": getColor(this.config.value, (this.config.value - this.config.min) / (this.config.max - this.config.min), this.config.levelColors, this.config.noGradient, this.config.customSectors),
pki: [this.config.min, this.config.min, this.config.max, this.params.widgetW, this.params.widgetH, this.params.dx, this.params.dy, this.config.gaugeWidthScale, this.config.donut]
});
if(this.config.donut) {
this.level.transform("r" + this.config.donutStartAngle + ", " + (this.params.widgetW/2 + this.params.dx) + ", " + (this.params.widgetH/1.95 + this.params.dy));
}
this.level.id = this.config.id+"-level";
// title
this.txtTitle = this.canvas.text(this.params.titleX, this.params.titleY, this.config.title);
this.txtTitle.attr({
"font-size":this.params.titleFontSize,
"font-weight":"bold",
"font-family":"Arial",
"fill":this.config.titleFontColor,
"fill-opacity":"1"
});
setDy(this.txtTitle, this.params.titleFontSize, this.params.titleY);
this.txtTitle.id = this.config.id+"-txttitle";
// value
this.txtValue = this.canvas.text(this.params.valueX, this.params.valueY, 0);
this.txtValue.attr({
"font-size":this.params.valueFontSize,
"font-weight":"bold",
"font-family":"Arial",
"fill":this.config.valueFontColor,
"fill-opacity":"0"
});
setDy(this.txtValue, this.params.valueFontSize, this.params.valueY);
this.txtValue.id = this.config.id+"-txtvalue";
// label
this.txtLabel = this.canvas.text(this.params.labelX, this.params.labelY, this.config.label);
this.txtLabel.attr({
"font-size":this.params.labelFontSize,
"font-weight":"normal",
"font-family":"Arial",
"fill":this.config.labelFontColor,
"fill-opacity":"0"
});
setDy(this.txtLabel, this.params.labelFontSize, this.params.labelY);
this.txtLabel.id = this.config.id+"-txtlabel";
// min
this.txtMinimum = this.config.min;
if( this.config.humanFriendly ) this.txtMinimum = humanFriendlyNumber( this.config.min, this.config.humanFriendlyDecimal );
this.txtMin = this.canvas.text(this.params.minX, this.params.minY, this.txtMinimum);
this.txtMin.attr({
"font-size":this.params.minFontSize,
"font-weight":"normal",
"font-family":"Arial",
"fill":this.config.labelFontColor,
"fill-opacity": (this.config.hideMinMax || this.config.donut)? "0" : "1"
});
setDy(this.txtMin, this.params.minFontSize, this.params.minY);
this.txtMin.id = this.config.id+"-txtmin";
// max
this.txtMaximum = this.config.max;
if( this.config.humanFriendly ) this.txtMaximum = humanFriendlyNumber( this.config.max, this.config.humanFriendlyDecimal );
this.txtMax = this.canvas.text(this.params.maxX, this.params.maxY, this.txtMaximum);
this.txtMax.attr({
"font-size":this.params.maxFontSize,
"font-weight":"normal",
"font-family":"Arial",
"fill":this.config.labelFontColor,
"fill-opacity": (this.config.hideMinMax || this.config.donut)? "0" : "1"
});
setDy(this.txtMax, this.params.maxFontSize, this.params.maxY);
this.txtMax.id = this.config.id+"-txtmax";
var defs = this.canvas.canvas.childNodes[1];
var svg = "http://www.w3.org/2000/svg";
if (ie < 9) {
onCreateElementNsReady(function() {
this.generateShadow(svg, defs);
});
} else {
this.generateShadow(svg, defs);
}
// var clear
defs, svg = null;
// execute on each animation frame
function onAnimate() {
if (obj.config.counter) {
var currentValue = obj.level.attr("pki");
if(obj.config.textRenderer) {
// this.originalValue = this.config.textRenderer(this.originalValue);
obj.txtValue.attr("text", obj.config.textRenderer(Math.floor(currentValue[0])));
} else if(obj.config.humanFriendly) {
// this.originalValue = humanFriendlyNumber( this.originalValue, this.config.humanFriendlyDecimal ) + this.config.symbol;
obj.txtValue.attr("text", humanFriendlyNumber( Math.floor(currentValue[0]), obj.config.humanFriendlyDecimal ) + obj.config.symbol);
} else {
// this.originalValue += this.config.symbol;
obj.txtValue.attr("text", (currentValue[0] * 1).toFixed(obj.config.decimals) + obj.config.symbol);
}
setDy(obj.txtValue, obj.params.valueFontSize, obj.params.valueY);
currentValue = null;
}
}
if(!obj.config.counter) {
if(obj.config.textRenderer) {
obj.originalValue = obj.config.textRenderer(obj.originalValue);
} else if(obj.config.humanFriendly) {
obj.originalValue = humanFriendlyNumber( obj.originalValue, obj.config.humanFriendlyDecimal ) + obj.config.symbol;
} else {
obj.originalValue = (obj.originalValue * 1).toFixed(obj.config.decimals) + obj.config.symbol;
}
obj.txtValue.attr("text", obj.originalValue);
setDy(obj.txtValue, obj.params.valueFontSize, obj.params.valueY);
}
//event fired on each animation frame
eve.on("raphael.anim.frame.*", onAnimate);
// animate gauge level
this.level.animate({pki: [this.config.value, this.config.min, this.config.max, this.params.widgetW, this.params.widgetH, this.params.dx, this.params.dy, this.config.gaugeWidthScale, this.config.donut]}, this.config.startAnimationTime, this.config.startAnimationType);
// animate value
this.txtValue.animate({"fill-opacity":"1"}, this.config.startAnimationTime, this.config.startAnimationType);
// animate label
this.txtLabel.animate({"fill-opacity":"1"}, this.config.startAnimationTime, this.config.startAnimationType);
};
/** Refresh gauge level */
JustGage.prototype.refresh = function(val, max) {
var originalVal, displayVal, color, max = max || null;
// set new max
if(max !== null) {
this.config.max = max;
this.txtMaximum = this.config.max;
if( this.config.humanFriendly ) this.txtMaximum = humanFriendlyNumber( this.config.max, this.config.humanFriendlyDecimal );
this.txtMax.attr({"text" : this.config.max});
setDy(this.txtMax, this.params.maxFontSize, this.params.maxY);
}
// overflow values
originalVal = val;
displayVal = val;
if ((val * 1) > (this.config.max * 1)) {val = (this.config.max * 1);}
if ((val * 1) < (this.config.min * 1)) {val = (this.config.min * 1);}
color = getColor(val, (val - this.config.min) / (this.config.max - this.config.min), this.config.levelColors, this.config.noGradient, this.config.customSectors);
if(this.config.textRenderer) {
displayVal = this.config.textRenderer(displayVal);
} else if( this.config.humanFriendly ) {
displayVal = humanFriendlyNumber( displayVal, this.config.humanFriendlyDecimal ) + this.config.symbol;
} else {
displayVal = (displayVal * 1).toFixed(this.config.decimals) + this.config.symbol;
}
if(!this.config.counter) {
this.canvas.getById(this.config.id+"-txtvalue").attr({"text":displayVal});
setDy(this.canvas.getById(this.config.id+"-txtvalue"), this.params.valueFontSize, this.params.valueY);
}
this.canvas.getById(this.config.id+"-level").animate({pki: [val, this.config.min, this.config.max, this.params.widgetW, this.params.widgetH, this.params.dx, this.params.dy, this.config.gaugeWidthScale, this.config.donut], "fill":color}, this.config.refreshAnimationTime, this.config.refreshAnimationType);
this.config.value = val * 1;
// var clear
originalVal, displayVal, color, max = null;
};
/** Generate shadow */
JustGage.prototype.generateShadow = function(svg, defs) {
var gaussFilter, feOffset, feGaussianBlur, feComposite1, feFlood, feComposite2, feComposite3;
// FILTER
gaussFilter=document.createElementNS(svg,"filter");
gaussFilter.setAttribute("id", this.config.id + "-inner-shadow");
defs.appendChild(gaussFilter);
// offset
feOffset = document.createElementNS(svg,"feOffset");
feOffset.setAttribute("dx", 0);
feOffset.setAttribute("dy", this.config.shadowVerticalOffset);
gaussFilter.appendChild(feOffset);
// blur
feGaussianBlur = document.createElementNS(svg,"feGaussianBlur");
feGaussianBlur.setAttribute("result","offset-blur");
feGaussianBlur.setAttribute("stdDeviation", this.config.shadowSize);
gaussFilter.appendChild(feGaussianBlur);
// composite 1
feComposite1 = document.createElementNS(svg,"feComposite");
feComposite1.setAttribute("operator","out");
feComposite1.setAttribute("in", "SourceGraphic");
feComposite1.setAttribute("in2","offset-blur");
feComposite1.setAttribute("result","inverse");
gaussFilter.appendChild(feComposite1);
// flood
feFlood = document.createElementNS(svg,"feFlood");
feFlood.setAttribute("flood-color","black");
feFlood.setAttribute("flood-opacity", this.config.shadowOpacity);
feFlood.setAttribute("result","color");
gaussFilter.appendChild(feFlood);
// composite 2
feComposite2 = document.createElementNS(svg,"feComposite");
feComposite2.setAttribute("operator","in");
feComposite2.setAttribute("in", "color");
feComposite2.setAttribute("in2","inverse");
feComposite2.setAttribute("result","shadow");
gaussFilter.appendChild(feComposite2);
// composite 3
feComposite3 = document.createElementNS(svg,"feComposite");
feComposite3.setAttribute("operator","over");
feComposite3.setAttribute("in", "shadow");
feComposite3.setAttribute("in2","SourceGraphic");
gaussFilter.appendChild(feComposite3);
// set shadow
if (!this.config.hideInnerShadow) {
this.canvas.canvas.childNodes[2].setAttribute("filter", "url(#" + this.config.id + "-inner-shadow)");
this.canvas.canvas.childNodes[3].setAttribute("filter", "url(#" + this.config.id + "-inner-shadow)");
}
// var clear
gaussFilter, feOffset, feGaussianBlur, feComposite1, feFlood, feComposite2, feComposite3 = null;
};
/** Get color for value */
function getColor(val, pct, col, noGradient, custSec) {
var no, inc, colors, percentage, rval, gval, bval, lower, upper, range, rangePct, pctLower, pctUpper, color;
var noGradient = noGradient || custSec.length > 0;
if(custSec.length > 0) {
for(var i = 0; i < custSec.length; i++) {
if(val > custSec[i].lo && val <= custSec[i].hi) {
return custSec[i].color;
}
}
}
no = col.length;
if (no === 1) return col[0];
inc = (noGradient) ? (1 / no) : (1 / (no - 1));
colors = [];
for (var i = 0; i < col.length; i++) {
percentage = (noGradient) ? (inc * (i + 1)) : (inc * i);
rval = parseInt((cutHex(col[i])).substring(0,2),16);
gval = parseInt((cutHex(col[i])).substring(2,4),16);
bval = parseInt((cutHex(col[i])).substring(4,6),16);
colors[i] = { pct: percentage, color: { r: rval, g: gval, b: bval } };
}
if(pct === 0) {
return 'rgb(' + [colors[0].color.r, colors[0].color.g, colors[0].color.b].join(',') + ')';
}
for (var j = 0; j < colors.length; j++) {
if (pct <= colors[j].pct) {
if (noGradient) {
return 'rgb(' + [colors[j].color.r, colors[j].color.g, colors[j].color.b].join(',') + ')';
} else {
lower = colors[j - 1];
upper = colors[j];
range = upper.pct - lower.pct;
rangePct = (pct - lower.pct) / range;
pctLower = 1 - rangePct;
pctUpper = rangePct;
color = {
r: Math.floor(lower.color.r * pctLower + upper.color.r * pctUpper),
g: Math.floor(lower.color.g * pctLower + upper.color.g * pctUpper),
b: Math.floor(lower.color.b * pctLower + upper.color.b * pctUpper)
};
return 'rgb(' + [color.r, color.g, color.b].join(',') + ')';
}
}
}
}
/** Fix Raphael display:none tspan dy attribute bug */
function setDy(elem, fontSize, txtYpos) {
if ((!ie || ie > 9) && (elem.node.firstChild.attributes.dy)) {
elem.node.firstChild.attributes.dy.value = 0;
}
}
/** Random integer */
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/** Cut hex */
function cutHex(str) {
return (str.charAt(0)=="#") ? str.substring(1,7):str;
}
/** Human friendly number suffix - From: http://stackoverflow.com/questions/2692323/code-golf-friendly-number-abbreviator */
function humanFriendlyNumber( n, d ) {
var p, d2, i, s;
p = Math.pow;
d2 = p(10, d);
i = 7;
while( i ) {
s = p(10,i--*3);
if( s <= n ) {
n = Math.round(n*d2/s)/d2+"KMGTPE"[i];
}
}
return n;
}
/** Get style */
function getStyle(oElm, strCssRule){
var strValue = "";
if(document.defaultView && document.defaultView.getComputedStyle){
strValue = document.defaultView.getComputedStyle(oElm).getPropertyValue(strCssRule);
}
else if(oElm.currentStyle){
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
return p1.toUpperCase();
});
strValue = oElm.currentStyle[strCssRule];
}
return strValue;
}
/** Create Element NS Ready */
function onCreateElementNsReady(func) {
if (document.createElementNS !== undefined) {
func();
} else {
setTimeout(function() { onCreateElementNsReady(func); }, 100);
}
}
/** Get IE version */
// ----------------------------------------------------------
// A short snippet for detecting versions of IE in JavaScript
// without resorting to user-agent sniffing
// ----------------------------------------------------------
// If you're not in IE (or IE version is less than 5) then:
// ie === undefined
// If you're in IE (>=5) then you can determine which version:
// ie === 7; // IE7
// Thus, to detect IE:
// if (ie) {}
// And to detect the version:
// ie === 6 // IE6
// ie > 7 // IE8, IE9 ...
// ie < 9 // Anything less than IE9
// ----------------------------------------------------------
// UPDATE: Now using Live NodeList idea from @jdalton
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
+108
View File
@@ -0,0 +1,108 @@
openerp.sale_crm = function(openerp) {
var _t = openerp.web._t;
openerp.sale_crm.GaugeWidget = openerp.web_kanban.AbstractField.extend({
className: "oe_gage",
start: function() {
var self = this;
var parent = this.getParent();
var max = this.options.max_field ? parent.record[this.options.max_field].raw_value : 100;
var label = this.options.label_field ? parent.record[this.options.label_field].raw_value : "";
var title = this.$node.html();
var val = this.field.value;
var value = _.isArray(val) && val.length ? val[val.length-1]['value'] : val;
var unique_id = _.uniqueId("JustGage");
this.$el.empty()
.attr('style', this.$node.attr('style') + ';position:relative; display:inline-block;')
.attr('id', unique_id);
this.gage = new JustGage({
id: unique_id,
node: this.$el[0],
title: title,
value: value,
min: 0,
max: max,
relativeGaugeSize: true,
humanFriendly: true,
titleFontColor: '#333333',
valueFontColor: '#333333',
labelFontColor: '#000',
label: label,
levelColors: [
"#ff0000",
"#f9c802",
"#a9d70b"
],
});
var flag_open = false;
if (self.options.action_change) {
var $svg = self.$el.find('svg');
var css = {
'text-align': 'center',
'position': 'absolute',
'width': self.$el.outerWidth() + 'px',
'top': (self.$el.outerHeight()/2-5) + 'px'
};
self.$el.click(function (event) {
event.stopPropagation();
flag_open = false;
if (!parent.view.is_action_enabled('edit')) {
return;
}
if (!self.$el.find(".oe_justgage_edit").size()) {
$div = $('<div class="oe_justgage_edit" style="z-index:1"/>');
$div.css(css);
$input = $('<input/>').val(value);
$input.css({
'text-align': 'center',
'margin': 'auto',
'width': ($svg.outerWidth()-40) + 'px'
});
$div.append($input);
self.$el.prepend($div)
$input.focus()
.keydown(function (event) {
event.stopPropagation();
if (event.keyCode == 13 || event.keyCode == 9) {
if ($input.val() != value) {
parent.view.dataset.call(self.options.action_change, [parent.id, $input.val()]).then(function () {
parent.do_reload();
});
} else {
$div.remove();
}
}
})
.click(function (event) {
event.stopPropagation();
flag_open = false;
})
.blur(function (event) {
if(!flag_open) {
self.$el.find(".oe_justgage_edit").remove();
} else {
flag_open = false;
setTimeout(function () {$input.focus();}, 0);
}
});
}
}).mousedown(function () {
flag_open = true;
});
if (!+value) {
$svg.fadeTo(0, 0.3);
$div = $('<div/>').text(_t("Click to change value"));
$div.css(css);
self.$el.append($div);
}
}
},
});
openerp.web_kanban.fields_registry.add("gage", "openerp.sale_crm.GaugeWidget");
};
+1
View File
@@ -230,6 +230,7 @@ class share_wizard(osv.TransientModel):
current_user = user_obj.browse(cr, UID_ROOT, uid, context=context)
# modify context to disable shortcuts when creating share users
context['noshortcut'] = True
context['no_reset_password'] = True
created_ids = []
existing_ids = []
if wizard_data.user_type == 'emails':
+7 -3
View File
@@ -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-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-01-22 08:16+0000\n"
"PO-Revision-Date: 2013-06-03 12:48+0000\n"
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 04:58+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-06-04 05:20+0000\n"
"X-Generator: Launchpad (build 16660)\n"
#. module: stock
#: field:stock.inventory.line.split,line_exist_ids:0
@@ -660,6 +660,8 @@ msgid ""
"Forces to specify a Serial Number for all moves containing this product and "
"going to a Customer Location"
msgstr ""
"Принудительно установить порядковый номер для всех перемещений этой "
"продукции в место хранения заказчика"
#. module: stock
#: model:ir.ui.menu,name:stock.menu_stock_products_moves
@@ -845,6 +847,8 @@ msgid ""
"Forces to specify a Serial Number for all moves containing this product and "
"coming from a Supplier Location"
msgstr ""
"Принудительно установить порядковый номер для всех перемещений этой "
"продукции из мест хранения поставщика"
#. module: stock
#: help:stock.config.settings,group_uos:0
@@ -191,7 +191,8 @@ Thanks,''') % (name, self.pool.get('ir.config_parameter').get_param(cr, uid, 'we
'action_id': act_id[0],
'survey_id': [[6, 0, survey_ids]]
}
user = user_ref.create(cr, uid, res_data)
create_ctx = dict(context, no_reset_password=True)
user = user_ref.create(cr, uid, res_data, context=create_ctx)
if user not in new_user:
new_user.append(user)
created+= "- %s (Login: %s, Password: %s)\n" % (partner.name or _('Unknown'),\