[MERGE] Merge from trunk
bzr revid: jco@openerp.com-20140214100157-1vbjgifkouh0h4ix
|
@ -729,8 +729,7 @@ class account_journal(osv.osv):
|
|||
'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'),
|
||||
'entry_posted': fields.boolean('Autopost Created Moves', help='Check this box to automatically post entries of this journal. Note that legally, some entries may be automatically posted when the source document is validated (Invoices), whatever the status of this field.'),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True, select=1, help="Company related to this journal"),
|
||||
'allow_date':fields.boolean('Check Date in Period', help= 'If set to True then do not accept the entry if the entry date is not into the period dates'),
|
||||
|
||||
'allow_date':fields.boolean('Check Date in Period', help= 'If checked, the entry won\'t be created if the entry date is not included into the selected period'),
|
||||
'profit_account_id' : fields.many2one('account.account', 'Profit Account'),
|
||||
'loss_account_id' : fields.many2one('account.account', 'Loss Account'),
|
||||
'internal_account_id' : fields.many2one('account.account', 'Internal Transfers Account', select=1),
|
||||
|
|
|
@ -495,6 +495,7 @@ class account_bank_statement(osv.osv):
|
|||
ctx = (context or {}).copy()
|
||||
ctx['journal_id'] = self.browse(cr, uid, ids[0], context=context).journal_id.id
|
||||
return {
|
||||
'name': _('Journal Items'),
|
||||
'view_type':'form',
|
||||
'view_mode':'tree',
|
||||
'res_model':'account.move.line',
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
<field name="journal_id" invisible="1"/>
|
||||
<field name="period_id" invisible="1" groups="account.group_account_user"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<field name="user_id"/>
|
||||
<field name="user_id" string="Responsible"/>
|
||||
<field name="date_due"/>
|
||||
<field name="origin"/>
|
||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||
|
@ -251,7 +251,7 @@
|
|||
<group>
|
||||
<group>
|
||||
<field domain="[('partner_id', '=', partner_id)]" name="partner_bank_id" on_change="onchange_partner_bank(partner_bank_id)"/>
|
||||
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'account.group_account_invoice']}"/>
|
||||
<field name="user_id" string="Responsible" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'account.group_account_invoice']}"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="payment_term" widget="selection"/>
|
||||
</group>
|
||||
|
|
|
@ -1270,12 +1270,11 @@
|
|||
<field name="model">account.move</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Account Entry" version="7.0">
|
||||
<header>
|
||||
<button name="button_validate" states="draft" string="Post" type="object" class="oe_highlight" groups="account.group_account_invoice"/>
|
||||
<button name="button_cancel" states="posted" string="Cancel Entry" type="object" groups="account.group_account_invoice"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet string="Journal Entries" >
|
||||
<header>
|
||||
<button name="button_validate" states="draft" string="Post" type="object" class="oe_highlight" groups="account.group_account_invoice"/>
|
||||
<button name="button_cancel" states="posted" string="Cancel Entry" type="object" groups="account.group_account_invoice"/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<label for="name" class="oe_edit_only" attrs="{'invisible':[('name','=','/')]}"/>
|
||||
<h1>
|
||||
<field name="name" readonly="True" attrs="{'invisible':[('name','=','/')]}"/>
|
||||
|
@ -1384,7 +1383,6 @@
|
|||
<field name="narration" colspan="4" placeholder="Add an internal note..." nolabel="1" height="50"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -2263,7 +2261,7 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="journal_id" on_change="onchange_journal_id(journal_id)" widget="selection" domain="[('type', '=', 'cash')]" />
|
||||
<field name="user_id" readonly="1" string="Responsible"/>
|
||||
<field name="user_id" attrs="{'readonly':[('state','!=','draft')]}" string="Responsible"/>
|
||||
<field name='company_id' widget="selection" groups="base.group_multi_company" />
|
||||
</group>
|
||||
<group>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<label for="fiscalyear"/>
|
||||
<div>
|
||||
<field name="fiscalyear" on_change="onchange_fiscalyear(fiscalyear)" class="oe_inline"/>
|
||||
<label align="0.7" string="(If you do not select Fiscal year it will take all open fiscal years)" class="oe_inline"/>
|
||||
<label align="0.7" string="(If you do not select a specific fiscal year, all open fiscal years will be selected.)" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="target_move"/>
|
||||
<label for="period_from" string="Periods"/>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<label for="period_id"/>
|
||||
<div>
|
||||
<field name="period_id" class="oe_inline"/>
|
||||
<label string="(If you do not select period it will take all open periods)" class="oe_inline"/>
|
||||
<label string="(If you do not select a specific period, all open periods will be selected)" class="oe_inline"/>
|
||||
</div>
|
||||
<field name="target_move"/>
|
||||
</group>
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/sheet/notebook/page/field[@name='line_id']/tree/field[@name='analytic_account_id']" position="replace">
|
||||
<xpath expr="/form/notebook/page/field[@name='line_id']/tree/field[@name='analytic_account_id']" position="replace">
|
||||
<field name="analytics_id" context="{'journal_id':parent.journal_id}" groups="analytic.group_analytic_accounting"/>
|
||||
</xpath>
|
||||
<xpath expr="/form/sheet/notebook/page/field[@name='line_id']/form/notebook/page/group/group/field[@name='analytic_account_id']" position="replace">
|
||||
<xpath expr="/form/notebook/page/field[@name='line_id']/form/notebook/page/group/group/field[@name='analytic_account_id']" position="replace">
|
||||
<field name="analytics_id" context="{'journal_id':parent.journal_id}" groups="analytic.group_analytic_accounting"/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
|
|
@ -352,6 +352,7 @@ class account_asset_asset(osv.osv):
|
|||
context = {}
|
||||
context.update({'search_default_asset_id': ids, 'default_asset_id': ids})
|
||||
return {
|
||||
'name': _('Journal Items'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'account.move.line',
|
||||
|
|
|
@ -26,7 +26,7 @@ class account_journal(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'allow_check_writing': fields.boolean('Allow Check writing', help='Check this if the journal is to be used for writing checks.'),
|
||||
'use_preprint_check': fields.boolean('Use Preprinted Check'),
|
||||
'use_preprint_check': fields.boolean('Use Preprinted Check', help='Check if you use a preformated sheet for check'),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Populate Statement:" version="7.0">
|
||||
<group>
|
||||
<field name="lines"/>
|
||||
<field name="lines" nolabel="1"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="populate_statement" string="ADD" type="object" class="oe_highlight"/>
|
||||
<button name="populate_statement" string="Ok" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
</footer>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<field name="tax_amount" nolabel="1"/>
|
||||
<div class="oe_subtotal_footer_separator">
|
||||
<label for="amount"/>
|
||||
<button type="object" icon="terp-stock_format-scientific" name="compute_tax" class="oe_link oe_edit_only" string="(Update)" attrs="{'invisible': [('state','!=','draft')]}"/>
|
||||
<button type="object" name="compute_tax" class="oe_link oe_edit_only" string="(Update)" attrs="{'invisible': [('state','!=','draft')]}"/>
|
||||
</div>
|
||||
<field name="amount" class="oe_subtotal_footer_separator" nolabel="1"/>
|
||||
</group>
|
||||
|
|
|
@ -253,7 +253,7 @@ class account_analytic_account(osv.osv):
|
|||
def check_recursion(self, cr, uid, ids, context=None, parent=None):
|
||||
return super(account_analytic_account, self)._check_recursion(cr, uid, ids, context=context, parent=parent)
|
||||
|
||||
_order = 'name asc'
|
||||
_order = 'code, name asc'
|
||||
_constraints = [
|
||||
(check_recursion, 'Error! You cannot create recursive analytic accounts.', ['parent_id']),
|
||||
]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<field name="name">Meeting Types Tree</field>
|
||||
<field name="model">calendar.event.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Meeting Types" editable="bottom">
|
||||
<tree string="Meeting Types">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
|
|
@ -49,9 +49,7 @@
|
|||
}
|
||||
</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new opportunity.
|
||||
</p><p>
|
||||
<p>
|
||||
OpenERP helps you keep track of your sales pipeline to follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<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="alias_name">sales</field>
|
||||
<field name="member_ids" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
|
||||
|
@ -56,6 +56,14 @@
|
|||
<field name="section_id" ref="crm.section_sales_department"/>
|
||||
</record>
|
||||
|
||||
<!--default alias for leads-->
|
||||
<record id="mail_alias_lead_info" model="mail.alias">
|
||||
<field name="alias_name">info</field>
|
||||
<field name="alias_model_id" ref="model_crm_lead"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_parent_model_id" ref="model_crm_case_section"/>
|
||||
</record>
|
||||
|
||||
<!-- notify all employees of module installation -->
|
||||
<record model="mail.message" id="module_install_notification">
|
||||
<field name="model">mail.group</field>
|
||||
|
|
|
@ -950,6 +950,14 @@ class crm_lead(format_address, osv.osv):
|
|||
default['stage_id'] = self._get_default_stage_id(cr, uid, local_context)
|
||||
return super(crm_lead, self).copy(cr, uid, id, default, context=context)
|
||||
|
||||
def get_empty_list_help(self, cr, uid, help, context=None):
|
||||
context['empty_list_help_model'] = 'crm.case.section'
|
||||
context['empty_list_help_id'] = context.get('default_section_id', None)
|
||||
context['empty_list_help_document_name'] = _("opportunity")
|
||||
if context.get('default_type') == 'lead':
|
||||
context['empty_list_help_document_name'] = _("lead")
|
||||
return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context)
|
||||
|
||||
# ----------------------------------------
|
||||
# Mail Gateway
|
||||
# ----------------------------------------
|
||||
|
|
|
@ -44,9 +44,7 @@
|
|||
<field name="view_id" eval="False"/>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new opportunity.
|
||||
</p><p>
|
||||
<p>
|
||||
OpenERP helps you keep track of your sales pipeline to follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
|
|
|
@ -264,14 +264,16 @@ class crm_phonecall(osv.osv):
|
|||
Open meeting's calendar view to schedule a meeting on current phonecall.
|
||||
:return dict: dictionary value for created meeting view
|
||||
"""
|
||||
partner_ids = []
|
||||
phonecall = self.browse(cr, uid, ids[0], context)
|
||||
if phonecall.partner_id and phonecall.partner_id.email:
|
||||
partner_ids.append(phonecall.partner_id.id)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'calendar', 'action_calendar_event', context)
|
||||
res['context'] = {
|
||||
'default_phonecall_id': phonecall.id,
|
||||
'default_partner_id': phonecall.partner_id and phonecall.partner_id.id or False,
|
||||
'default_partner_ids': partner_ids,
|
||||
'default_user_id': uid,
|
||||
'default_email_from': phonecall.email_from,
|
||||
'default_state': 'open',
|
||||
'default_name': phonecall.name,
|
||||
}
|
||||
return res
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
<field name="view_mode">tree,calendar</field>
|
||||
<field name="view_id" ref="crm_case_inbound_phone_tree_view"/>
|
||||
<field name="domain">[]</field>
|
||||
<field name="context">{'default_state': 'done'}</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_phonecalls_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
|
@ -106,7 +106,7 @@
|
|||
<field name="view_mode">tree,calendar</field>
|
||||
<field name="view_id" ref="crm_case_phone_tree_view"/>
|
||||
<field name="domain">[('state','!=','done')]</field>
|
||||
<field name="context" eval="'{\'default_state\':\'open\'}'"/>
|
||||
<field name="context">{}</field>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_phonecalls_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
|
@ -66,7 +67,42 @@ class crm_configuration(osv.TransientModel):
|
|||
'group_multi_salesteams': fields.boolean("Organize Sales activities into multiple Sales Teams",
|
||||
implied_group='base.group_multi_salesteams',
|
||||
help="""Allows you to use Sales Teams to manage your leads and opportunities."""),
|
||||
'alias_prefix': fields.char('Default Alias Name for Leads'),
|
||||
'alias_domain' : fields.char('Alias Domain'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'alias_domain': lambda self, cr, uid, context: self.pool['mail.alias']._get_alias_domain(cr, SUPERUSER_ID, [1], None, None)[1],
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
def _find_default_lead_alias_id(self, cr, uid, context=None):
|
||||
alias_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'crm.mail_alias_lead_info')
|
||||
if not alias_id:
|
||||
alias_ids = self.pool['mail.alias'].search(
|
||||
cr, uid, [
|
||||
('alias_model_id.model', '=', 'crm.lead'),
|
||||
('alias_force_thread_id', '=', False),
|
||||
('alias_parent_model_id.model', '=', 'crm.case.section'),
|
||||
('alias_parent_thread_id', '=', False),
|
||||
('alias_defaults', '=', '{}')
|
||||
], context=context)
|
||||
alias_id = alias_ids and alias_ids[0] or False
|
||||
return alias_id
|
||||
|
||||
def get_default_alias_prefix(self, cr, uid, ids, context=None):
|
||||
alias_name = False
|
||||
alias_id = self._find_default_lead_alias_id(cr, uid, context=context)
|
||||
if alias_id:
|
||||
alias_name = self.pool['mail.alias'].browse(cr, uid, alias_id, context=context).alias_name
|
||||
return {'alias_prefix': alias_name}
|
||||
|
||||
def set_default_alias_prefix(self, cr, uid, ids, context=None):
|
||||
mail_alias = self.pool['mail.alias']
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
alias_id = self._find_default_lead_alias_id(cr, uid, context=context)
|
||||
if not alias_id:
|
||||
create_ctx = dict(context, alias_model_name='crm.lead', alias_parent_model_name='crm.case.section')
|
||||
alias_id = self.pool['mail.alias'].create(cr, uid, {'alias_name': record.alias_prefix}, context=create_ctx)
|
||||
else:
|
||||
mail_alias.write(cr, uid, alias_id, {'alias_name': record.alias_prefix}, context=context)
|
||||
return True
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<field name="model">sale.config.settings</field>
|
||||
<field name="inherit_id" ref="base_setup.view_sale_config_settings"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<div name="config_sale" position="before">
|
||||
<separator string="After-Sale Services"/>
|
||||
<group>
|
||||
|
@ -26,11 +27,31 @@
|
|||
<group>
|
||||
<label for="id" string="Manage Sales Teams"/>
|
||||
<div>
|
||||
<field name="group_multi_salesteams" class="oe_inline"/>
|
||||
<label for="group_multi_salesteams"/>
|
||||
<div>
|
||||
<field name="group_multi_salesteams" class="oe_inline"/>
|
||||
<label for="group_multi_salesteams"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</group>
|
||||
</div>
|
||||
<xpath expr="//group[@name='On Mail Client']" position="before">
|
||||
<group name="default_alias">
|
||||
<label for="id" string="Leads Email Alias"/>
|
||||
<div attrs="{'invisible': [('alias_domain', '=', False)]}">
|
||||
<div>
|
||||
<field name="alias_prefix" class="oe_inline" attrs="{'required': [('alias_domain', '!=', False)]}"/>
|
||||
@
|
||||
<field name="alias_domain" class="oe_inline" readonly="1"/>
|
||||
</div>
|
||||
<p>
|
||||
All emails sent to this address and processed by the mailgateway
|
||||
will create a new lead.
|
||||
</p>
|
||||
</div>
|
||||
</group>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * gamification_sale_crm
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 8.0alpha1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-02-13 15:09+0000\n"
|
||||
"PO-Revision-Date: 2014-02-13 15:09+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_lead_delay_close
|
||||
msgid "Days to Close a Deal"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_new_leads
|
||||
msgid "New Leads"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_call
|
||||
msgid "calls"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_lead_delay_open
|
||||
msgid "Time to Qualify a Lead"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_sale_order_created
|
||||
msgid "New Sales Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_customer_refunds
|
||||
msgid "invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_customer_refunds
|
||||
msgid "Customer Refunds"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.challenge,name:gamification_sale_crm.challenge_crm_sale
|
||||
msgid "Monthly Sales Targets"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_tot_customer_refunds
|
||||
msgid "Total Customer Refunds"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_new_opportunities
|
||||
msgid "opportunities"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_lead_delay_close
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_lead_delay_open
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_new_opportunities
|
||||
msgid "New Opportunities"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_call
|
||||
msgid "Logged Calls"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_nbr_paid_sale_order
|
||||
msgid "Paid Sales Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.challenge,name:gamification_sale_crm.challenge_crm_marketing
|
||||
msgid "Lead Acquisition"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_tot_paid_sale_order
|
||||
msgid "Total Paid Sales Orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_new_leads
|
||||
msgid "leads"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_paid_sale_order
|
||||
#: model:gamification.goal.definition,suffix:gamification_sale_crm.definition_crm_nbr_sale_order_created
|
||||
msgid "orders"
|
||||
msgstr ""
|
||||
|
||||
#. module: gamification_sale_crm
|
||||
#: model:gamification.goal.definition,name:gamification_sale_crm.definition_crm_tot_invoices
|
||||
msgid "Total Invoiced"
|
||||
msgstr ""
|
||||
|
|
@ -21,16 +21,15 @@
|
|||
|
||||
import logging
|
||||
|
||||
from openerp import tools
|
||||
from openerp.modules.module import get_module_resource
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp import tools
|
||||
from openerp.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class hr_employee_category(osv.osv):
|
||||
class hr_employee_category(osv.Model):
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not ids:
|
||||
|
@ -73,9 +72,9 @@ class hr_employee_category(osv.osv):
|
|||
]
|
||||
|
||||
|
||||
class hr_job(osv.osv):
|
||||
class hr_job(osv.Model):
|
||||
|
||||
def _no_of_employee(self, cr, uid, ids, name, args, context=None):
|
||||
def _get_nbr_employees(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for job in self.browse(cr, uid, ids, context=context):
|
||||
nb_employees = len(job.employee_ids or [])
|
||||
|
@ -93,59 +92,81 @@ class hr_job(osv.osv):
|
|||
return res
|
||||
|
||||
_name = "hr.job"
|
||||
_description = "Job Description"
|
||||
_inherit = ['mail.thread']
|
||||
_description = "Job Position"
|
||||
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
||||
_columns = {
|
||||
'name': fields.char('Job Name', size=128, required=True, select=True),
|
||||
'expected_employees': fields.function(_no_of_employee, string='Total Forecasted Employees',
|
||||
'expected_employees': fields.function(_get_nbr_employees, string='Total Forecasted Employees',
|
||||
help='Expected number of employees for this job position after new recruitment.',
|
||||
store = {
|
||||
'hr.job': (lambda self,cr,uid,ids,c=None: ids, ['no_of_recruitment'], 10),
|
||||
'hr.employee': (_get_job_position, ['job_id'], 10),
|
||||
}, type='integer',
|
||||
multi='no_of_employee'),
|
||||
'no_of_employee': fields.function(_no_of_employee, string="Current Number of Employees",
|
||||
multi='_get_nbr_employees'),
|
||||
'no_of_employee': fields.function(_get_nbr_employees, string="Current Number of Employees",
|
||||
help='Number of employees currently occupying this job position.',
|
||||
store = {
|
||||
'hr.employee': (_get_job_position, ['job_id'], 10),
|
||||
}, type='integer',
|
||||
multi='no_of_employee'),
|
||||
'no_of_recruitment': fields.integer('Expected in Recruitment', help='Number of new employees you expect to recruit.'),
|
||||
multi='_get_nbr_employees'),
|
||||
'no_of_recruitment': fields.integer('Expected New Employees', help='Number of new employees you expect to recruit.'),
|
||||
'no_of_hired_employee': fields.integer('Hired Employees', help='Number of hired employees for this job position during recruitment phase.'),
|
||||
'employee_ids': fields.one2many('hr.employee', 'job_id', 'Employees', groups='base.group_user'),
|
||||
'description': fields.text('Job Description'),
|
||||
'requirements': fields.text('Requirements'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'state': fields.selection([('open', 'No Recruitment'), ('recruit', 'Recruitement in Progress')], 'Status', readonly=True, required=True,
|
||||
help="By default 'In position', set it to 'In Recruitment' if recruitment process is going on for this job position."),
|
||||
'state': fields.selection([('open', 'Recruitment Closed'), ('recruit', 'Recruitment in Progress')],
|
||||
string='Status', readonly=True, required=True,
|
||||
track_visibility='always',
|
||||
help="By default 'Closed', set it to 'In Recruitment' if recruitment process is going on for this job position."),
|
||||
'write_date': fields.datetime('Update Date', readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'hr.job', context=c),
|
||||
'no_of_recruitment': 0,
|
||||
'company_id': lambda self, cr, uid, ctx=None: self.pool.get('res.company')._company_default_get(cr, uid, 'hr.job', context=ctx),
|
||||
'state': 'open',
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
('name_company_uniq', 'unique(name, company_id, department_id)', 'The name of the job position must be unique per department in company!'),
|
||||
('hired_employee_check', "CHECK ( no_of_hired_employee <= no_of_recruitment )", "Number of hired employee must be less than expected number of employee in recruitment."),
|
||||
]
|
||||
|
||||
|
||||
def on_change_expected_employee(self, cr, uid, ids, no_of_recruitment, no_of_employee, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
return {'value': {'expected_employees': no_of_recruitment + no_of_employee}}
|
||||
|
||||
def job_recruitement(self, cr, uid, ids, *args):
|
||||
for job in self.browse(cr, uid, ids):
|
||||
def set_recruit(self, cr, uid, ids, context=None):
|
||||
for job in self.browse(cr, uid, ids, context=context):
|
||||
no_of_recruitment = job.no_of_recruitment == 0 and 1 or job.no_of_recruitment
|
||||
self.write(cr, uid, [job.id], {'state': 'recruit', 'no_of_recruitment': no_of_recruitment})
|
||||
self.write(cr, uid, [job.id], {'state': 'recruit', 'no_of_recruitment': no_of_recruitment}, context=context)
|
||||
return True
|
||||
|
||||
def job_open(self, cr, uid, ids, *args):
|
||||
self.write(cr, uid, ids, {'state': 'open', 'no_of_recruitment': 0})
|
||||
def set_open(self, cr, uid, ids, context=None):
|
||||
self.write(cr, uid, ids, {
|
||||
'state': 'open',
|
||||
'no_of_recruitment': 0,
|
||||
'no_of_hired_employee': 0
|
||||
}, context=context)
|
||||
return True
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({
|
||||
'employee_ids': [],
|
||||
'no_of_recruitment': 0,
|
||||
'no_of_hired_employee': 0,
|
||||
})
|
||||
if 'name' in default:
|
||||
job = self.browse(cr, uid, id, context=context)
|
||||
default['name'] = _("%s (copy)") % (job.name)
|
||||
return super(hr_job, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
# ----------------------------------------
|
||||
# Compatibility methods
|
||||
# ----------------------------------------
|
||||
_no_of_employee = _get_nbr_employees # v7 compatibility
|
||||
job_open = set_open # v7 compatibility
|
||||
job_recruitment = set_recruit # v7 compatibility
|
||||
|
||||
|
||||
class hr_employee(osv.osv):
|
||||
_name = "hr.employee"
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
</group>
|
||||
<group string="Position">
|
||||
<field name="department_id" on_change="onchange_department_id(department_id)"/>
|
||||
<field name="job_id" options='{"no_open": True}' domain="[('state','!=','old')]" context="{'form_view_ref': 'hr.view_hr_job_employee_form'}"/>
|
||||
<field name="job_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="coach_id"/>
|
||||
</group>
|
||||
|
@ -333,8 +333,8 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Job" version="7.0">
|
||||
<header>
|
||||
<button name="job_recruitement" string="Launch Recruitement" states="open" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="job_open" string="Stop Recruitment" states="recruit" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="set_recruit" string="Launch Recruitment" states="open" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<button name="set_open" string="Stop Recruitment" states="recruit" type="object" class="oe_highlight" groups="base.group_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="recruit,open"/>
|
||||
</header>
|
||||
<sheet>
|
||||
|
@ -342,20 +342,20 @@
|
|||
<label for="name" class="oe_edit_only"/>
|
||||
<h1><field name="name" class="oe_inline"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group name="job_data">
|
||||
<field name="no_of_employee" groups="base.group_user"/>
|
||||
<field name="no_of_recruitment" on_change="on_change_expected_employee(no_of_recruitment,no_of_employee)"/>
|
||||
<field name="expected_employees" groups="base.group_user"/>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
<field name="department_id"/>
|
||||
</group>
|
||||
<div class="oe_right" name="buttons"/>
|
||||
<group name="employee_data">
|
||||
<field name="department_id" class="oe_inline"/>
|
||||
<label for="no_of_employee"/>no_of_recruitment
|
||||
<div>
|
||||
<field name="no_of_employee" class="oe_inline"/>
|
||||
<p><field name="no_of_recruitment" groups="base.group_user" colspan="0" class="oe_inline" style="padding-top: 1px"/> new employee(s) expected</p>
|
||||
</div>
|
||||
</group>
|
||||
<div>
|
||||
<div attrs="{'invisible': [('state', '!=', 'recruit')]}">
|
||||
<label for="description"/>
|
||||
<field name="description"/>
|
||||
</div>
|
||||
<div>
|
||||
<div attrs="{'invisible': [('state', '!=', 'recruit')]}">
|
||||
<label for="requirements"/>
|
||||
<field name="requirements"/>
|
||||
</div>
|
||||
|
@ -378,6 +378,7 @@
|
|||
<field name="no_of_employee"/>
|
||||
<field name="no_of_recruitment"/>
|
||||
<field name="expected_employees"/>
|
||||
<field name="no_of_hired_employee"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -389,34 +390,18 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Jobs">
|
||||
<field name="name" string="Job"/>
|
||||
<filter icon="terp-camera_test" domain="[('state','=','open')]" string="In Position" help="In Position"/>
|
||||
<filter icon="terp-personal+" domain="[('state','=','recruit')]" string="In Recruitment" help="In Recruitment"/>
|
||||
<filter domain="[('state','=','open')]" string="In Position"/>
|
||||
<filter domain="[('state','=','recruit')]" string="In Recruitment" name="in_recruitment"/>
|
||||
<field name="department_id"/>
|
||||
<group expand="0" string="Group By...">
|
||||
<filter string="Department" icon="terp-personal+" domain="[]" context="{'group_by':'department_id'}"/>
|
||||
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Department" domain="[]" context="{'group_by':'department_id'}"/>
|
||||
<filter string="Status" domain="[]" context="{'group_by':'state'}"/>
|
||||
<filter string="Company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_job_employee_form" model="ir.ui.view">
|
||||
<field name="name">hr.job.employee.form</field>
|
||||
<field name="model">hr.job</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Job" version="7.0">
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
</group>
|
||||
<label for="description"/>
|
||||
<field name="description"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_hr_job">
|
||||
<field name="name">Job Positions</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
|
@ -441,7 +426,6 @@
|
|||
</record>
|
||||
|
||||
<menuitem name="Recruitment" id="base.menu_crm_case_job_req_main" parent="menu_hr_root" groups="base.group_hr_user"/>
|
||||
<menuitem parent="hr.menu_hr_configuration" id="menu_hr_job" action="action_hr_job" sequence="6"/>
|
||||
|
||||
<!-- hr.department -->
|
||||
<record id="view_department_form" model="ir.ui.view">
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<group name="recruitment_grp">
|
||||
<label for="id" string="Talent Management"/>
|
||||
<div name="recruitment">
|
||||
<div>
|
||||
<div name="hr_recruitment">
|
||||
<field name="module_hr_recruitment" class="oe_inline"/>
|
||||
<label for="module_hr_recruitment"/>
|
||||
</div>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
name: HR Officer
|
||||
login: hro
|
||||
password: hro
|
||||
email: hro@example.com
|
||||
-
|
||||
I added groups for HR Officer.
|
||||
-
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
- state == 'open'
|
||||
- no_of_recruitment == 0
|
||||
-
|
||||
Now, Recruitement is started so I start recruitement of Job Postion of "Developer" Profile.
|
||||
Now, Recruitment is started so I start recruitment of Job Postion of "Developer" Profile.
|
||||
-
|
||||
!python {model: hr.job}: |
|
||||
self.job_recruitement(cr, uid, [ref('job_developer')])
|
||||
self.job_recruitment(cr, uid, [ref('job_developer')])
|
||||
-
|
||||
I check 'state' and number of 'Expected in Recruitment' after initiating the recruitment
|
||||
-
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="employee_id" on_change="onchange_employee_id(employee_id)"/>
|
||||
<field name="job_id" context="{'form_view_ref': 'hr.view_hr_job_employee_form'}"/>
|
||||
<field name="job_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="type_id"/>
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * hr_gamification
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 8.0alpha1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-02-13 15:10+0000\n"
|
||||
"PO-Revision-Date: 2014-02-13 15:10+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "Grant a Badge"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.actions.act_window,help:hr_gamification.goals_menu_groupby_action2
|
||||
msgid "<p class=\"oe_view_nocontent_create\">\n"
|
||||
" Click to create a goal. \n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" A goal is defined by a user and a goal type.\n"
|
||||
" Goals can be created automatically by using challenges.\n"
|
||||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.ui.menu,name:hr_gamification.menu_hr_gamification
|
||||
msgid "Engagement"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
msgid "Reward Employee with"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: code:addons/hr_gamification/wizard/grant_badge.py:45
|
||||
#, python-format
|
||||
msgid "You can send badges only to employees linked to a user."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
#: model:ir.actions.act_window,name:hr_gamification.action_reward_wizard
|
||||
msgid "Reward Employee"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: field:gamification.badge.user,employee_id:0
|
||||
#: field:gamification.badge.user.wizard,employee_id:0
|
||||
#: model:ir.model,name:hr_gamification.model_hr_employee
|
||||
msgid "Employee"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.model,name:hr_gamification.model_gamification_badge
|
||||
msgid "Gamification badge"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.model,name:hr_gamification.model_gamification_badge_user_wizard
|
||||
msgid "gamification.badge.user.wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "to reward this employee for a good action"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.actions.act_window,name:hr_gamification.goals_menu_groupby_action2
|
||||
#: model:ir.ui.menu,name:hr_gamification.gamification_goal_menu_hr
|
||||
msgid "Goals History"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: field:hr.employee,badge_ids:0
|
||||
msgid "Employee Badges"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: code:addons/hr_gamification/wizard/grant_badge.py:48
|
||||
#, python-format
|
||||
msgid "You can not send a badge to yourself"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
msgid "Describe what they did and why it matters (will be public)"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "Click to grant this employee his first badge"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.actions.act_window,help:hr_gamification.challenge_list_action2
|
||||
msgid "<p class=\"oe_view_nocontent_create\">\n"
|
||||
" Click to create a challenge. \n"
|
||||
" </p>\n"
|
||||
" <p>\n"
|
||||
" Assign a list of goals to chosen users to evaluate them.\n"
|
||||
" The challenge can use a period (weekly, monthly...) for automatic creation of goals.\n"
|
||||
" The goals are created for the specified users or member of the group.\n"
|
||||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "Goals"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
msgid "What are you thank for?"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: constraint:gamification.badge.user:0
|
||||
msgid "The selected employee does not correspond to the selected user."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: field:hr.employee,has_badges:0
|
||||
msgid "Has Badges"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "Badges are rewards of good work. Give them to people you believe deserve it."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:hr.employee:0
|
||||
msgid "Received Badges"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: field:hr.employee,goal_ids:0
|
||||
msgid "Employee HR Goals"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.model,name:hr_gamification.model_gamification_badge_user
|
||||
msgid "Gamification user badge"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge:0
|
||||
msgid "Granted Employees"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.actions.act_window,name:hr_gamification.challenge_list_action2
|
||||
#: model:ir.ui.menu,name:hr_gamification.gamification_challenge_menu_hr
|
||||
msgid "Challenges"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: code:addons/hr_gamification/wizard/grant_badge.py:45
|
||||
#: code:addons/hr_gamification/wizard/grant_badge.py:48
|
||||
#, python-format
|
||||
msgid "Warning!"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: view:gamification.badge.user.wizard:0
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_gamification
|
||||
#: model:ir.ui.menu,name:hr_gamification.gamification_badge_menu_hr
|
||||
msgid "Badges"
|
||||
msgstr ""
|
||||
|
|
@ -37,13 +37,14 @@ You can define the different phases of interviews and easily rate the applicant
|
|||
""",
|
||||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'images': ['images/hr_recruitment_analysis.jpeg','images/hr_recruitment_applicants.jpeg'],
|
||||
'images': ['images/hr_recruitment_analysis.jpeg','images/hr_recruitment_applicants.jpeg','static/src/img/down1.png'],
|
||||
'depends': [
|
||||
'decimal_precision',
|
||||
'hr',
|
||||
'survey',
|
||||
'calendar',
|
||||
'fetchmail',
|
||||
'web_kanban_gauge',
|
||||
],
|
||||
'data': [
|
||||
'wizard/hr_recruitment_create_partner_job_view.xml',
|
||||
|
@ -58,7 +59,11 @@ You can define the different phases of interviews and easily rate the applicant
|
|||
'hr_recruitment_data.xml',
|
||||
],
|
||||
'demo': ['hr_recruitment_demo.xml'],
|
||||
'js': [
|
||||
'static/src/js/job_position.js',
|
||||
],
|
||||
'test': ['test/recruitment_process.yml'],
|
||||
'css':['static/src/css/job_position.css'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': True,
|
||||
|
|
|
@ -19,12 +19,10 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
|
||||
from datetime import datetime
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools import html2plaintext
|
||||
|
||||
|
||||
AVAILABLE_PRIORITIES = [
|
||||
('', ''),
|
||||
|
@ -246,7 +244,8 @@ class hr_applicant(osv.Model):
|
|||
if job_id:
|
||||
job_record = self.pool.get('hr.job').browse(cr, uid, job_id, context=context)
|
||||
department_id = job_record and job_record.department_id and job_record.department_id.id or False
|
||||
return {'value': {'department_id': department_id}}
|
||||
user_id = job_record and job_record.user_id and job_record.user_id.id or False
|
||||
return {'value': {'department_id': department_id, 'user_id': user_id}}
|
||||
|
||||
def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None):
|
||||
if not stage_id:
|
||||
|
@ -331,19 +330,12 @@ class hr_applicant(osv.Model):
|
|||
value = self.pool.get("survey").action_print_survey(cr, uid, ids, context=context)
|
||||
return value
|
||||
|
||||
def action_get_attachment_tree_view(self, cr, uid, ids, context):
|
||||
domain = ['&', ('res_model', '=', 'hr.applicant'), ('res_id', 'in', ids)]
|
||||
return {
|
||||
'name': _('Attachments'),
|
||||
'domain': domain,
|
||||
'res_model': 'ir.attachment',
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_id': False,
|
||||
'view_mode': 'tree,form',
|
||||
'view_type': 'form',
|
||||
'limit': 80,
|
||||
'context': "{'default_res_model': '%s'}" % (self._name)
|
||||
}
|
||||
def action_get_attachment_tree_view(self, cr, uid, ids, context=None):
|
||||
model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'action_attachment')
|
||||
action = self.pool.get(model).read(cr, uid, action_id, context=context)
|
||||
action['context'] = {'default_res_model': self._name, 'default_res_id': ids[0]}
|
||||
action['domain'] = str(['&', ('res_model', '=', self._name), ('res_id', 'in', ids)])
|
||||
return action
|
||||
|
||||
def message_get_suggested_recipients(self, cr, uid, ids, context=None):
|
||||
recipients = super(hr_applicant, self).message_get_suggested_recipients(cr, uid, ids, context=context)
|
||||
|
@ -364,7 +356,7 @@ class hr_applicant(osv.Model):
|
|||
val = msg.get('from').split('<')[0]
|
||||
defaults = {
|
||||
'name': msg.get('subject') or _("No Subject"),
|
||||
'partner_name':val,
|
||||
'partner_name': val,
|
||||
'email_from': msg.get('from'),
|
||||
'email_cc': msg.get('cc'),
|
||||
'user_id': False,
|
||||
|
@ -378,13 +370,20 @@ class hr_applicant(osv.Model):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
context['mail_create_nolog'] = True
|
||||
if vals.get('department_id') and not context.get('default_department_id'):
|
||||
context['default_department_id'] = vals.get('department_id')
|
||||
|
||||
if vals.get('job_id') or context.get('default_job_id'):
|
||||
job_id = vals.get('job_id') or context.get('default_job_id')
|
||||
vals.update(self.onchange_job(cr, uid, [], job_id, context=context)['value'])
|
||||
obj_id = super(hr_applicant, self).create(cr, uid, vals, context=context)
|
||||
applicant = self.browse(cr, uid, obj_id, context=context)
|
||||
if applicant.job_id:
|
||||
self.pool.get('hr.job').message_post(cr, uid, [applicant.job_id.id], body=_('Applicant <b>created</b>'), subtype="hr_recruitment.mt_job_new_applicant", context=context)
|
||||
name = applicant.partner_name if applicant.partner_name else applicant.name
|
||||
self.pool['hr.job'].message_post(
|
||||
cr, uid, [applicant.job_id.id],
|
||||
body=_('New application from %s') % name,
|
||||
subtype="hr_recruitment.mt_job_applicant_new", context=context)
|
||||
return obj_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
|
@ -404,6 +403,15 @@ class hr_applicant(osv.Model):
|
|||
else:
|
||||
res = super(hr_applicant, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
# post processing: if job changed, post a message on the job
|
||||
if vals.get('job_id'):
|
||||
for applicant in self.browse(cr, uid, ids, context=None):
|
||||
name = applicant.partner_name if applicant.partner_name else applicant.name
|
||||
self.pool['hr.job'].message_post(
|
||||
cr, uid, [vals['job_id']],
|
||||
body=_('New application from %s') % name,
|
||||
subtype="hr_recruitment.mt_job_applicant_new", context=context)
|
||||
|
||||
# post processing: if stage changed, post a message in the chatter
|
||||
if vals.get('stage_id'):
|
||||
stage = self.pool['hr.recruitment.stage'].browse(cr, uid, vals['stage_id'], context=context)
|
||||
|
@ -444,7 +452,7 @@ class hr_applicant(osv.Model):
|
|||
address_id = self.pool.get('res.partner').address_get(cr, uid, [applicant.partner_id.id], ['contact'])['contact']
|
||||
contact_name = self.pool.get('res.partner').name_get(cr, uid, [applicant.partner_id.id])[0][1]
|
||||
if applicant.job_id and (applicant.partner_name or contact_name):
|
||||
applicant.job_id.write({'no_of_recruitment': applicant.job_id.no_of_recruitment - 1})
|
||||
applicant.job_id.write({'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1}, context=context)
|
||||
emp_id = hr_employee.create(cr, uid, {'name': applicant.partner_name or contact_name,
|
||||
'job_id': applicant.job_id.id,
|
||||
'address_home_id': address_id,
|
||||
|
@ -454,6 +462,10 @@ class hr_applicant(osv.Model):
|
|||
'work_phone': applicant.department_id and applicant.department_id.company_id and applicant.department_id.company_id.phone or False,
|
||||
})
|
||||
self.write(cr, uid, [applicant.id], {'emp_id': emp_id}, context=context)
|
||||
self.pool['hr.job'].message_post(
|
||||
cr, uid, [applicant.job_id.id],
|
||||
body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name,
|
||||
subtype="hr_recruitment.mt_job_applicant_hired", context=context)
|
||||
else:
|
||||
raise osv.except_osv(_('Warning!'), _('You must define an Applied Job and a Contact Name for this applicant.'))
|
||||
|
||||
|
@ -490,16 +502,37 @@ class hr_job(osv.osv):
|
|||
_inherit = "hr.job"
|
||||
_name = "hr.job"
|
||||
_inherits = {'mail.alias': 'alias_id'}
|
||||
|
||||
def _get_attached_docs(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = {}
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
for job_id in ids:
|
||||
applicant_ids = self.pool.get('hr.applicant').search(cr, uid, [('job_id', '=', job_id)], context=context)
|
||||
res[job_id] = attachment_obj.search(
|
||||
cr, uid, [
|
||||
'|',
|
||||
'&', ('res_model', '=', 'hr.job'), ('res_id', '=', job_id),
|
||||
'&', ('res_model', '=', 'hr.applicant'), ('res_id', 'in', applicant_ids)
|
||||
], context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'survey_id': fields.many2one('survey', 'Interview Form', help="Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job"),
|
||||
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="restrict", required=True,
|
||||
help="Email alias for this job position. New emails will automatically "
|
||||
"create new applicants for this job position."),
|
||||
'address_id': fields.many2one('res.partner', 'Job Location', help="Address where employees are working"),
|
||||
'application_ids': fields.one2many('hr.applicant', 'job_id', 'Applications'),
|
||||
'manager_id': fields.related('department_id', 'manager_id', type='many2one', string='Department Manager', relation='hr.employee', readonly=True, store=True),
|
||||
'document_ids': fields.function(_get_attached_docs, type='one2many', relation='ir.attachment', string='Applications'),
|
||||
'user_id': fields.many2one('res.users', 'Recruitment Responsible', track_visibility='onchange'),
|
||||
'color': fields.integer('Color Index'),
|
||||
}
|
||||
|
||||
def _address_get(self, cr, uid, context=None):
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
return user.company_id.partner_id.id
|
||||
|
||||
_defaults = {
|
||||
'address_id': _address_get
|
||||
}
|
||||
|
@ -541,6 +574,18 @@ class hr_job(osv.osv):
|
|||
'nodestroy': True,
|
||||
}
|
||||
|
||||
def action_get_attachment_tree_view(self, cr, uid, ids, context=None):
|
||||
#open attachments of job and related applicantions.
|
||||
model, action_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'action_attachment')
|
||||
action = self.pool.get(model).read(cr, uid, action_id, context=context)
|
||||
applicant_ids = self.pool.get('hr.applicant').search(cr, uid, [('job_id', 'in', ids)], context=context)
|
||||
action['context'] = {'default_res_model': self._name, 'default_res_id': ids[0]}
|
||||
action['domain'] = str(['|', '&', ('res_model', '=', 'hr.job'), ('res_id', 'in', ids), '&', ('res_model', '=', 'hr.applicant'), ('res_id', 'in', applicant_ids)])
|
||||
return action
|
||||
|
||||
def action_set_no_of_recruitment(self, cr, uid, id, value, context=None):
|
||||
return self.write(cr, uid, [id], {'no_of_recruitment': value}, context=context)
|
||||
|
||||
|
||||
class applicant_category(osv.osv):
|
||||
""" Category of applicant """
|
||||
|
|
|
@ -495,13 +495,9 @@
|
|||
<field name="alias_name">jobs</field>
|
||||
<field name="alias_model_id" ref="model_hr_applicant"/>
|
||||
<field name="alias_user_id" ref="base.user_root"/>
|
||||
<field name="alias_parent_model_id" ref="model_hr_job"/>
|
||||
</record>
|
||||
|
||||
<!-- Job-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_job_new_applicant" model="mail.message.subtype">
|
||||
<field name="name">New Applicant</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
</record>
|
||||
<!-- Applicant-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_applicant_new" model="mail.message.subtype">
|
||||
<field name="name">New Applicant</field>
|
||||
|
@ -515,12 +511,35 @@
|
|||
<field name="default" eval="False"/>
|
||||
<field name="description">Stage changed</field>
|
||||
</record>
|
||||
<record id="mt_applicant_employee" model="mail.message.subtype">
|
||||
<record id="mt_applicant_hired" model="mail.message.subtype">
|
||||
<field name="name">Applicant Hired</field>
|
||||
<field name="res_model">hr.applicant</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Applicant hired</field>
|
||||
</record>
|
||||
<!-- Job-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_job_applicant_new" model="mail.message.subtype">
|
||||
<field name="name">Applicant Created</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_applicant_new')"/>
|
||||
<field name="relation_field">job_id</field>
|
||||
</record>
|
||||
<record id="mt_job_applicant_stage_changed" model="mail.message.subtype">
|
||||
<field name="name">Applicant Stage Changed</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="parent_id" eval="ref('mt_applicant_stage_changed')"/>
|
||||
<field name="relation_field">job_id</field>
|
||||
</record>
|
||||
<record id="mt_job_applicant_hired" model="mail.message.subtype">
|
||||
<field name="name">Applicant Hired</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="parent_id" eval="ref('mt_applicant_hired')"/>
|
||||
<field name="relation_field">job_id</field>
|
||||
</record>
|
||||
|
||||
<!-- Applicant Categories(Tag) -->
|
||||
<record id="tag_applicant_reserve" model="hr.applicant_category">
|
||||
<field name="name">Reserve</field>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
######################## JOB OPPORTUNITIES (menu) ###########################
|
||||
<record model="ir.actions.act_window" id="crm_case_categ0_act_job">
|
||||
<field name="name">Applications</field>
|
||||
|
@ -9,16 +8,15 @@
|
|||
<field name="view_mode">kanban,tree,form,graph,calendar</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="search_view_id" ref="view_crm_case_jobs_filter"/>
|
||||
<field name="context">{'empty_list_help_model': 'hr.job'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to add a new job applicant.
|
||||
<p>
|
||||
OpenERP helps you track applicants in the recruitment
|
||||
process and follow up all operations: meetings, interviews, etc.
|
||||
</p><p>
|
||||
OpenERP helps you track applicants in the recruitment process
|
||||
and follow up all operations: meetings, interviews, etc.
|
||||
Candidates and their cv's are automatically created when they
|
||||
apply for a job. If you install the document management modules,
|
||||
all resumes are indexed automatically, so that you can easily
|
||||
search through their content in the recruitment menu.
|
||||
Applicants and their attached CV are created automatically when an email is sent.
|
||||
If you install the document management modules, all resumes are indexed automatically,
|
||||
so that you can easily search through their content.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -58,15 +56,10 @@
|
|||
sequence="1"/>
|
||||
|
||||
<!-- ALL JOBS REQUESTS -->
|
||||
|
||||
<menuitem parent="base.menu_crm_case_job_req_main" id="hr.menu_hr_job_position" action="action_hr_job" sequence="1"/>
|
||||
<menuitem
|
||||
name="Applications"
|
||||
parent="base.menu_crm_case_job_req_main"
|
||||
id="menu_crm_case_categ0_act_job" action="crm_case_categ0_act_job" sequence="1"/>
|
||||
|
||||
|
||||
<menuitem parent="hr.menu_hr_configuration" id="hr.menu_hr_job" action="hr.action_hr_job" sequence="2"/>
|
||||
|
||||
|
||||
id="menu_crm_case_categ0_act_job" action="crm_case_categ0_act_job" sequence="2"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</record>
|
||||
|
||||
|
||||
<!-- Jobs -->
|
||||
<!-- Applicants -->
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_job">
|
||||
<field name="name">Applicants</field>
|
||||
<field name="model">hr.applicant</field>
|
||||
|
@ -91,10 +91,10 @@
|
|||
<label for="partner_name" class="oe_edit_only"/>
|
||||
<h2 style="display: inline-block;">
|
||||
<field name="partner_name" class="oe_inline"/>
|
||||
<button string="Create Employee" name="create_employee_from_applicant" type="object"
|
||||
class="oe_link oe_inline" style="margin-left: 8px;"
|
||||
attrs="{'invisible': [('emp_id', '!=', False)]}"/>
|
||||
</h2>
|
||||
<button string="Create Employee" name="create_employee_from_applicant" type="object"
|
||||
class="oe_link oe_inline" style="margin-left: 8px;"
|
||||
attrs="{'invisible': [('emp_id', '!=', False)]}"/>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
|
@ -307,46 +307,190 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- HR Job -->
|
||||
<record model="ir.actions.act_window" id="action_hr_job_applications">
|
||||
<field name="name">Applications</field>
|
||||
<field name="res_model">hr.applicant</field>
|
||||
<field name="view_mode">kanban,tree,form,graph,calendar</field>
|
||||
<field name="context">{'search_default_job_id': [active_id], 'default_job_id': active_id, 'empty_list_help_model': 'hr.job'}</field>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
OpenERP helps you track applicants in the recruitment
|
||||
process and follow up all operations: meetings, interviews, etc.
|
||||
</p><p>
|
||||
Applicants and their attached CV are created automatically when an email is sent.
|
||||
If you install the document management modules, all resumes are indexed automatically,
|
||||
so that you can easily search through their content.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Jobs -->
|
||||
<record id="view_job_filter_recruitment" model="ir.ui.view">
|
||||
<field name="name">Job</field>
|
||||
<field name="model">hr.job</field>
|
||||
<field name="inherit_id" ref="hr.view_job_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="department_id" positon="after">
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_job_survey" model="ir.ui.view">
|
||||
<field name="name">hr.job.form1</field>
|
||||
<field name="model">hr.job</field>
|
||||
<field name="inherit_id" ref="hr.view_hr_job_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="job_data" position="inside">
|
||||
<group name="employee_data" position="inside">
|
||||
<label for="survey_id" groups="base.group_user"/>
|
||||
<div groups="base.group_user">
|
||||
<field name="survey_id" class="oe_inline" domain="[('type','=','Human Resources')]"/>
|
||||
<button string="Print Interview" name="action_print_survey" type="object" attrs="{'invisible':[('survey_id','=',False)]}" class="oe_inline oe_link"/>
|
||||
</div>
|
||||
<label for="address_id"/>
|
||||
<div>
|
||||
<field name="address_id" context="{'show_address': 1}"/>
|
||||
<span class="oe_grey">(empty = remote work)</span>
|
||||
</div>
|
||||
</group>
|
||||
<field name="expected_employees" position="after">
|
||||
<label for="survey_id" groups="base.group_user"/>
|
||||
<div groups="base.group_user">
|
||||
<field name="survey_id" class="oe_inline" domain="[('type','=','Human Resources')]"/>
|
||||
<button class="oe_inline"
|
||||
string="Interview"
|
||||
name="action_print_survey" type="object"
|
||||
attrs="{'invisible':[('survey_id','=',False)]}"/>
|
||||
</div>
|
||||
</field>
|
||||
<xpath expr="//group[@name='job_data']" position="after">
|
||||
<group name="group_alias"
|
||||
attrs="{'invisible': [('alias_domain', '=', False)]}">
|
||||
<label for="alias_name" string="Email Alias"/>
|
||||
<div name="alias_def">
|
||||
<xpath expr="//field[@name='department_id']" position="after">
|
||||
<label for="alias_name" string="Specific Email Address" attrs="{'invisible': [('alias_domain', '=', False)]}" help ="Define a specific contact address for this job position. If you keep it empty, the default email address will be used which is in human resources settings"/>
|
||||
<div name="alias_def" attrs="{'invisible': [('alias_domain', '=', False)]}">
|
||||
<field name="alias_id" class="oe_read_only oe_inline"
|
||||
string="Email Alias" required="0"/>
|
||||
<div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
|
||||
<field name="alias_name" class="oe_inline"/>@<field name="alias_domain" class="oe_inline" readonly="1"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="alias_contact" class="oe_inline" string="Accept Emails From"/>
|
||||
</group>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='department_id']" position="after">
|
||||
<field name="user_id" class="oe_inline"/>
|
||||
</xpath>
|
||||
<div name="buttons" position="inside">
|
||||
<button string="Applications" name="%(action_hr_job_applications)d" context="{'default_user_id': user_id}" type="action"/>
|
||||
<button string="Documents" name="action_get_attachment_tree_view" type="object"/>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_job_kanban" model="ir.ui.view">
|
||||
<field name="name">hr.job.kanban</field>
|
||||
<field name="model">hr.job</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban version="7.0" class="oe_background_grey">
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
<field name="no_of_recruitment"/>
|
||||
<field name="color"/>
|
||||
<field name="application_ids"/>
|
||||
<field name="document_ids"/>
|
||||
<field name="no_of_hired_employee"/>
|
||||
<field name="manager_id"/>
|
||||
<field name="survey_id"/>
|
||||
<field name="state"/>
|
||||
<field name="user_id"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_job oe_kanban_card oe_kanban_global_click">
|
||||
<div class="oe_dropdown_toggle oe_dropdown_kanban oe_custom">
|
||||
<span class="oe_e">í</span>
|
||||
<ul class="oe_dropdown_menu">
|
||||
<t t-if="widget.view.is_action_enabled('edit')">
|
||||
<li><a type="edit">Edit...</a></li>
|
||||
</t>
|
||||
<t t-if="widget.view.is_action_enabled('delete')">
|
||||
<li><a type="delete">Delete</a></li>
|
||||
</t>
|
||||
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class = "oe_kanban_content">
|
||||
<t t-if="record.user_id.raw_value">
|
||||
<img t-att-src="kanban_image('res.users', 'image_medium', record.user_id.raw_value[0])" t-att-title="record.user_id.value" class="oe_kanban_avatar oe_job_avatar"/>
|
||||
</t>
|
||||
<t t-if="record.user_id.raw_value === false">
|
||||
<img t-att-src='_s + "/base/static/src/img/avatar.png"' class="oe_kanban_avatar oe_job_avatar"/>
|
||||
</t>
|
||||
<div class="oe_job_detail">
|
||||
<div class="oe_job oe_name oe_kanban_ellipsis">
|
||||
<field name="name"/>
|
||||
</div>
|
||||
<div class="oe_job oe_department oe_kanban_ellipsis">
|
||||
<field name="department_id"/>
|
||||
<span t-if="record.manager_id.value" class="oe_manager_name">
|
||||
(<t t-esc="record.manager_id.value"/>)
|
||||
</span>
|
||||
</div>
|
||||
<div class="oe_job_alias oe_kanban_ellipsis" t-if=" record.alias_id.value and record.state.raw_value == 'recruit'">
|
||||
<span class="oe_e">%%</span><small><field name="alias_id"/></small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<t t-if="record.state.raw_value == 'recruit'">
|
||||
<div class="oe_applications">
|
||||
<a name="%(action_hr_job_applications)d" type="action">
|
||||
<span t-if="record.application_ids.raw_value.length gt 1"><t t-esc="record.application_ids.raw_value.length"/> Applications</span>
|
||||
<span t-if="record.application_ids.raw_value.length lt 2"><t t-esc="record.application_ids.raw_value.length"/> Application</span>
|
||||
</a>
|
||||
<br/>
|
||||
<a t-if="record.document_ids.raw_value.length gt 0" name="action_get_attachment_tree_view" type="object">
|
||||
<span t-if="record.document_ids.raw_value.length gt 1"><t t-esc="record.document_ids.raw_value.length"/> Documents</span>
|
||||
<span t-if="record.document_ids.raw_value.length lt 2"><t t-esc="record.document_ids.raw_value.length"/> Document</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_job_justgage">
|
||||
<field state="recruit" name="no_of_hired_employee" widget="gauge"
|
||||
style="width:160px; height: 120px;"
|
||||
options="{
|
||||
'max_field': 'no_of_recruitment',
|
||||
'label': 'Hired Employees',
|
||||
'on_change': 'action_set_no_of_recruitment',
|
||||
'on_click_label': 'employee(s) to recruit',
|
||||
'force_set': False,
|
||||
'gauge_value_field': 'no_of_recruitment',
|
||||
}">
|
||||
Hired Employees
|
||||
</field>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="record.state.raw_value == 'open'">
|
||||
<div class="oe_start_recruitment">
|
||||
<p><b>click here</b>, To start the recruitment</p>
|
||||
<img src="/hr_recruitment/static/src/img/down1.png"/>
|
||||
</div>
|
||||
</t>
|
||||
<div class="oe_launch_recruitment">
|
||||
<a t-if="record.state.raw_value == 'open'" data-name="job_recruitment" data-type="object" class="oe_kanban_action">Launch Recruitment</a>
|
||||
<a t-if="record.state.raw_value == 'recruit'" data-name="job_open" data-type="object" class="oe_kanban_action">Recruitment Done</a>
|
||||
<a t-if="record.survey_id.raw_value"> | </a>
|
||||
<a t-if="record.survey_id.raw_value" data-name="action_print_survey" data-type="object" class="oe_kanban_action">Print Interview</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- hr related job position menu action -->
|
||||
<record model="ir.actions.act_window" id="action_hr_job">
|
||||
<field name="name">Job Positions</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{'search_default_in_recruitment': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new job or remove the filter on "In Recruitment" to recruit for an on hold job.
|
||||
</p>
|
||||
<p>
|
||||
Define job position profile and manage recruitment in a context of a particular job: print interview survey, define number of expected new employees, and manage its recruitment pipe
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Stage Tree View -->
|
||||
<record model="ir.ui.view" id="hr_recruitment_stage_tree">
|
||||
<field name="name">hr.recruitment.stage.tree</field>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Business Applications
|
||||
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
|
||||
# Copyright (C) 2004-Today OpenERP S.A. (<http://openerp.com>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -19,9 +19,11 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
class hr_applicant_settings(osv.osv_memory):
|
||||
|
||||
class hr_applicant_settings(osv.TransientModel):
|
||||
_name = 'hr.config.settings'
|
||||
_inherit = ['hr.config.settings', 'fetchmail.config.settings']
|
||||
|
||||
|
@ -32,6 +34,44 @@ class hr_applicant_settings(osv.osv_memory):
|
|||
'fetchmail_applicants': fields.boolean('Create applicants from an incoming email account',
|
||||
fetchmail_model='hr.applicant', fetchmail_name='Incoming HR Applications',
|
||||
help='Allow applicants to send their job application to an email address (jobs@mycompany.com), '
|
||||
'and create automatically application documents in the system.'),
|
||||
'and create automatically application documents in the system.',
|
||||
deprecated='Will be removed with OpenERP v8, not applicable anymore. Use aliases instead.'),
|
||||
'alias_prefix': fields.char('Default Alias Name for Jobs'),
|
||||
'alias_domain': fields.char('Alias Domain'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'alias_domain': lambda self, cr, uid, context: self.pool['mail.alias']._get_alias_domain(cr, SUPERUSER_ID, [1], None, None)[1],
|
||||
}
|
||||
|
||||
def _find_default_job_alias_id(self, cr, uid, context=None):
|
||||
alias_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'hr_recruitment.mail_alias_jobs')
|
||||
if not alias_id:
|
||||
alias_ids = self.pool['mail.alias'].search(
|
||||
cr, uid, [
|
||||
('alias_model_id.model', '=', 'hr.applicant'),
|
||||
('alias_force_thread_id', '=', False),
|
||||
('alias_parent_model_id.model', '=', 'hr.job'),
|
||||
('alias_parent_thread_id', '=', False),
|
||||
('alias_defaults', '=', '{}')
|
||||
], context=context)
|
||||
alias_id = alias_ids and alias_ids[0] or False
|
||||
return alias_id
|
||||
|
||||
def get_default_alias_prefix(self, cr, uid, ids, context=None):
|
||||
alias_name = False
|
||||
alias_id = self._find_default_job_alias_id(cr, uid, context=context)
|
||||
if alias_id:
|
||||
alias_name = self.pool['mail.alias'].browse(cr, uid, alias_id, context=context).alias_name
|
||||
return {'alias_prefix': alias_name}
|
||||
|
||||
def set_default_alias_prefix(self, cr, uid, ids, context=None):
|
||||
mail_alias = self.pool.get('mail.alias')
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
alias_id = self._find_default_job_alias_id(cr, uid, context=context)
|
||||
if not alias_id:
|
||||
create_ctx = dict(context, alias_model_name='hr.applicant', alias_parent_model_name='hr.job')
|
||||
alias_id = self.pool['mail.alias'].create(cr, uid, {'alias_name': record.alias_prefix}, context=create_ctx)
|
||||
else:
|
||||
mail_alias.write(cr, uid, alias_id, {'alias_name': record.alias_prefix}, context=context)
|
||||
return True
|
||||
|
|
|
@ -19,6 +19,14 @@
|
|||
<label for="module_document"/>
|
||||
</div>
|
||||
</div>
|
||||
<xpath expr="//div[@name='hr_recruitment']" position="after">
|
||||
<div attrs="{'invisible': ['|',('module_hr_recruitment','=',False),('alias_domain', '=', False)]}">
|
||||
<label string="Default job email address"/>
|
||||
<field name="alias_prefix" class="oe_inline" attrs="{'required': [('alias_domain', '!=', False)]}"/>
|
||||
@
|
||||
<field name="alias_domain" class="oe_inline" readonly="1"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
job_position.css: job_position.sass
|
||||
sass --trace -t expanded job_position.sass job_position.css
|
|
@ -0,0 +1,86 @@
|
|||
.openerp .oe_kanban_job{
|
||||
width: 355px;
|
||||
min-height: 165px !important;
|
||||
}
|
||||
.openerp .oe_job_alias{
|
||||
margin: 3px;
|
||||
}
|
||||
.openerp .oe_job_detail{
|
||||
height: 70px;
|
||||
width: 308px
|
||||
}
|
||||
.openerp .oe_job_alias .oe_e {
|
||||
font-size: 30px;
|
||||
line-height: 6px;
|
||||
vertical-align: top;
|
||||
margin-right: 3px;
|
||||
color: white;
|
||||
text-shadow: 0px 0px 2px black;
|
||||
float: left;
|
||||
}
|
||||
.openerp .oe_job {
|
||||
font-size: 112%;
|
||||
position: inline;
|
||||
margin: 3px 3px;
|
||||
color: #4c4c4c;
|
||||
height: 16px;
|
||||
}
|
||||
.openerp img.oe_job_avatar {
|
||||
position: absolute;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-left: 295px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.openerp .oe_launch_recruitment{
|
||||
float: left;
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
left: 10px;
|
||||
}
|
||||
.openerp div.oe_applications {
|
||||
position: absolute;;
|
||||
margin-top: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.openerp .oe_applications > a > span:hover{
|
||||
margin: 4px 0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.openerp .oe_name {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.openerp .oe_manager_name {
|
||||
width: 135px;
|
||||
font-size: 11px;
|
||||
color: gray;
|
||||
}
|
||||
.openerp .oe_job_justgage {
|
||||
float: right;
|
||||
margin-top: -40px;
|
||||
margin-right: -58px;
|
||||
width:200px;
|
||||
height:130px;
|
||||
}
|
||||
.openerp .oe_department {
|
||||
width: 350px;
|
||||
}
|
||||
.openerp .oe_start_recruitment {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.openerp .oe_start_recruitment p {
|
||||
font-size: 14px;
|
||||
color: gray;
|
||||
padding-left: 50px;
|
||||
}
|
||||
.openerp .oe_start_recruitment img {
|
||||
margin-top: -22px;
|
||||
width: 32px;
|
||||
height: 34px;
|
||||
float: left;
|
||||
padding-left: 12px;
|
||||
}
|
||||
.openerp .oe_job_messages{
|
||||
margin-top: 40px !important;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
.openerp
|
||||
.oe_kanban_job
|
||||
width: 355px
|
||||
min-height: 165px !important
|
||||
.oe_job_alias
|
||||
margin: 3px
|
||||
.oe_job_detail
|
||||
height: 70px
|
||||
width: 308px
|
||||
.oe_job_alias .oe_e
|
||||
font-size: 30px
|
||||
line-height: 6px
|
||||
vertical-align: top
|
||||
margin-right: 3px
|
||||
color: white
|
||||
text-shadow: 0px 0px 2px black
|
||||
float: left
|
||||
.oe_job
|
||||
font-size: 112%
|
||||
position: inline
|
||||
margin: 3px 3px
|
||||
color: #4c4c4c
|
||||
height: 16px
|
||||
img.oe_job_avatar
|
||||
position: absolute
|
||||
width: 24px
|
||||
height: 24px
|
||||
margin-left: 295px
|
||||
margin-top: -5px
|
||||
.oe_launch_recruitment
|
||||
float: left
|
||||
position: absolute
|
||||
bottom: 3px
|
||||
left: 10px
|
||||
div.oe_applications
|
||||
position: absolute
|
||||
margin-top: 16px
|
||||
font-size: 14px
|
||||
.oe_applications > a > span:hover
|
||||
margin: 4px 0
|
||||
text-decoration: underline
|
||||
.oe_name
|
||||
font-size: 14px
|
||||
font-weight: bold
|
||||
.oe_manager_name
|
||||
width: 135px
|
||||
font-size: 11px
|
||||
color: gray
|
||||
.oe_job_justgage
|
||||
float: right
|
||||
margin-top: -40px
|
||||
margin-right: -58px
|
||||
width: 200px
|
||||
height: 130px
|
||||
.oe_department
|
||||
width: 350px
|
||||
.oe_start_recruitment
|
||||
padding-top: 10px
|
||||
p
|
||||
font-size: 14px
|
||||
color: gray
|
||||
padding-left: 50px
|
||||
img
|
||||
margin-top: -22px
|
||||
width: 32px
|
||||
height: 34px
|
||||
float: left
|
||||
padding-left: 12px
|
||||
.oe_job_messages
|
||||
margin-top: 40px !important
|
After Width: | Height: | Size: 4.8 KiB |
|
@ -0,0 +1,13 @@
|
|||
openerp.hr_recruitment = function (openerp) {
|
||||
|
||||
openerp.web_kanban.KanbanRecord.include({
|
||||
on_card_clicked: function() {
|
||||
if (this.view.dataset.model === 'hr.job') {
|
||||
this.$('.oe_applications a').first().click();
|
||||
} else {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
}
|
|
@ -95,7 +95,6 @@ class EscposDriver(Thread):
|
|||
_logger.warning('ESC/POS Device Disconnected: '+message)
|
||||
|
||||
def run(self):
|
||||
self.queue = Queue()
|
||||
while True:
|
||||
try:
|
||||
timestamp, task, data = self.queue.get(True)
|
||||
|
|
|
@ -129,10 +129,6 @@ class Scanner(Thread):
|
|||
self.set_status('error',str(e))
|
||||
return None
|
||||
|
||||
@http.route('/hw_proxy/Vis_scanner_connected', type='json', auth='none', cors='*')
|
||||
def is_scanner_connected(self):
|
||||
return self.get_device() != None
|
||||
|
||||
def get_barcode(self):
|
||||
""" Returns a scanned barcode. Will wait at most 5 seconds to get a barcode, and will
|
||||
return barcode scanned in the past if they are not older than 5 seconds and have not
|
||||
|
|
|
@ -154,6 +154,12 @@ class mail_alias(osv.Model):
|
|||
sequence = (sequence + 1) if sequence else 2
|
||||
return new_name
|
||||
|
||||
def _clean_and_make_unique(self, cr, uid, name, context=None):
|
||||
# when an alias name appears to already be an email, we keep the local part only
|
||||
name = remove_accents(name).lower().split('@')[0]
|
||||
name = re.sub(r'[^\w+.]+', '-', name)
|
||||
return self._find_unique(cr, uid, name, context=context)
|
||||
|
||||
def migrate_to_alias(self, cr, child_model_name, child_table_name, child_model_auto_init_fct,
|
||||
alias_model_name, alias_id_column, alias_key, alias_prefix='', alias_force_key='', alias_defaults={},
|
||||
alias_generate_name=False, context=None):
|
||||
|
@ -199,7 +205,7 @@ class mail_alias(osv.Model):
|
|||
alias_vals['alias_parent_thread_id'] = obj_data['id']
|
||||
alias_create_ctx = dict(context, alias_model_name=alias_model_name, alias_parent_model_name=child_model_name)
|
||||
alias_id = mail_alias.create(cr, SUPERUSER_ID, alias_vals, context=alias_create_ctx)
|
||||
child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id})
|
||||
child_class_model.write(cr, SUPERUSER_ID, obj_data['id'], {'alias_id': alias_id}, context={'mail_notrack': True})
|
||||
_logger.info('Mail alias created for %s %s (id %s)', child_model_name, obj_data[alias_key], obj_data['id'])
|
||||
|
||||
# Finally attempt to reinstate the missing constraint
|
||||
|
@ -227,11 +233,7 @@ class mail_alias(osv.Model):
|
|||
model_name = context.get('alias_model_name')
|
||||
parent_model_name = context.get('alias_parent_model_name')
|
||||
if vals.get('alias_name'):
|
||||
# when an alias name appears to already be an email, we keep the local part only
|
||||
alias_name = remove_accents(vals['alias_name']).lower().split('@')[0]
|
||||
alias_name = re.sub(r'[^\w+.]+', '-', alias_name)
|
||||
alias_name = self._find_unique(cr, uid, alias_name, context=context)
|
||||
vals['alias_name'] = alias_name
|
||||
vals['alias_name'] = self._clean_and_make_unique(cr, uid, vals.get('alias_name'), context=context)
|
||||
if model_name:
|
||||
model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0]
|
||||
vals['alias_model_id'] = model_id
|
||||
|
@ -240,6 +242,12 @@ class mail_alias(osv.Model):
|
|||
vals['alias_parent_model_id'] = model_id
|
||||
return super(mail_alias, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
""""give uniqe alias name if given alias name is allready assigned"""
|
||||
if vals.get('alias_name'):
|
||||
vals['alias_name'] = self._clean_and_make_unique(cr, uid, vals.get('alias_name'), context=context)
|
||||
return super(mail_alias, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def open_document(self, cr, uid, ids, context=None):
|
||||
alias = self.browse(cr, uid, ids, context=context)[0]
|
||||
if not alias.alias_model_id or not alias.alias_force_thread_id:
|
||||
|
|
|
@ -113,9 +113,9 @@ class mail_thread(osv.AbstractModel):
|
|||
object_id.alias_id.alias_model_id.model == self._name and \
|
||||
object_id.alias_id.alias_force_thread_id == 0:
|
||||
alias = object_id.alias_id
|
||||
elif catchall_domain and model: # no specific res_id given -> generic help message, take an example alias (i.e. alias of some section_id)
|
||||
if not alias and catchall_domain and model: # no res_id or res_id not linked to an alias -> generic help message, take a generic alias of the model
|
||||
alias_obj = self.pool.get('mail.alias')
|
||||
alias_ids = alias_obj.search(cr, uid, [("alias_parent_model_id.model", "=", model), ("alias_name", "!=", False), ('alias_force_thread_id', '=', False)], context=context, order='id ASC')
|
||||
alias_ids = alias_obj.search(cr, uid, [("alias_parent_model_id.model", "=", model), ("alias_name", "!=", False), ('alias_force_thread_id', '=', False), ('alias_parent_thread_id', '=', False)], context=context, order='id ASC')
|
||||
if alias_ids and len(alias_ids) == 1:
|
||||
alias = alias_obj.browse(cr, uid, alias_ids[0], context=context)
|
||||
|
||||
|
@ -384,7 +384,10 @@ class mail_thread(osv.AbstractModel):
|
|||
track_ctx = dict(context)
|
||||
if 'lang' not in track_ctx:
|
||||
track_ctx['lang'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).lang
|
||||
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx)
|
||||
if not context.get('mail_notrack'):
|
||||
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx)
|
||||
else:
|
||||
tracked_fields = []
|
||||
if tracked_fields:
|
||||
records = self.browse(cr, uid, ids, context=track_ctx)
|
||||
initial_values = dict((this.id, dict((key, getattr(this, key)) for key in tracked_fields.keys())) for this in records)
|
||||
|
|
|
@ -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: 2011-12-06 10:25+0000\n"
|
||||
"Last-Translator: qdp (OpenERP) <qdp-launchpad@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2014-02-12 04:36+0000\n"
|
||||
"Last-Translator: Bluce <igamall@yahoo.com.tw>\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: 2014-01-28 05:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16914)\n"
|
||||
"X-Launchpad-Export-Date: 2014-02-13 05:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16916)\n"
|
||||
|
||||
#. module: mrp
|
||||
#: help:mrp.config.settings,module_mrp_repair:0
|
||||
|
@ -47,7 +47,7 @@ msgstr "工作中心使用率"
|
|||
#. module: mrp
|
||||
#: view:mrp.routing.workcenter:0
|
||||
msgid "Routing Work Centers"
|
||||
msgstr "途程工作中心"
|
||||
msgstr "製程工作中心"
|
||||
|
||||
#. module: mrp
|
||||
#: field:mrp.production.workcenter.line,cycle:0
|
||||
|
@ -83,12 +83,12 @@ msgstr "MRP 工作中心"
|
|||
#: 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
|
||||
|
@ -244,6 +244,13 @@ msgid ""
|
|||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"<p class=\"oe_view_nocontent_create\">\n"
|
||||
"點選建立一個製程(Routing)。\n"
|
||||
"</p><p>\n"
|
||||
"製程(Routing)允許您建立並管理在工作中心內應被遵循的製造程序(即工作順序),用以生產產品。\n"
|
||||
"它們被附加於用以定義所需原物料的物料清單(BOM)。\n"
|
||||
"</p>\n"
|
||||
" "
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
|
@ -299,7 +306,7 @@ msgstr "預定之貨品"
|
|||
#. module: mrp
|
||||
#: selection:mrp.bom,type:0
|
||||
msgid "Sets / Phantom"
|
||||
msgstr "套件 / 虛項"
|
||||
msgstr "組 / 虛擬物料"
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
|
@ -315,7 +322,7 @@ msgstr "於外部計劃中之位置的引用。"
|
|||
#. module: mrp
|
||||
#: model:res.groups,name:mrp.group_mrp_routings
|
||||
msgid "Manage Routings"
|
||||
msgstr "管理途程"
|
||||
msgstr "管理製程"
|
||||
|
||||
#. module: mrp
|
||||
#: model:ir.model,name:mrp.model_mrp_product_produce
|
||||
|
@ -393,7 +400,7 @@ msgstr "確認生產"
|
|||
msgid ""
|
||||
"The system creates an order (production or purchased) depending on the sold "
|
||||
"quantity and the products parameters."
|
||||
msgstr ""
|
||||
msgstr "系統依據已售數量與產品參數建立一個供給訂單(製造單或採購單)。"
|
||||
|
||||
#. module: mrp
|
||||
#: model:process.transition,note:mrp.process_transition_servicemts0
|
||||
|
@ -461,6 +468,15 @@ msgid ""
|
|||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"<p class=\"oe_view_nocontent_create\">\n"
|
||||
" 點選建立一個新的屬性。\n"
|
||||
" </p><p>\n"
|
||||
" OpenERP的屬性(properties)是使用於選擇正確的物料表(BoM)於製造產品,\n"
|
||||
" 當您有不同的方法來建立同一產品。您能指定數個屬性給每一個物料表。\n"
|
||||
" 當一位業務人員建立一張銷售訂單時,他們可以將銷售訂單關聯至數個屬性,\n"
|
||||
" 並且OpenERP將根據需求自動選擇物料表(BoM)。\n"
|
||||
" </p>\n"
|
||||
" "
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
|
@ -539,7 +555,7 @@ msgstr ""
|
|||
msgid ""
|
||||
"The Bill of Material is linked to a routing, i.e. the succession of work "
|
||||
"centers."
|
||||
msgstr ""
|
||||
msgstr "物料清單(BOM)已連結至一個製程(工作順序),如各工作中心的接續"
|
||||
|
||||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
|
@ -566,7 +582,7 @@ msgstr "強制預留"
|
|||
#. module: mrp
|
||||
#: field:report.mrp.inout,value:0
|
||||
msgid "Stock value"
|
||||
msgstr ""
|
||||
msgstr "庫存評價"
|
||||
|
||||
#. module: mrp
|
||||
#: model:ir.actions.act_window,name:mrp.action_product_bom_structure
|
||||
|
@ -773,7 +789,7 @@ msgstr "每月"
|
|||
msgid ""
|
||||
"Unit of Measure (Unit of Measure) is the unit of measurement for the "
|
||||
"inventory control"
|
||||
msgstr ""
|
||||
msgstr "度量單位(UoM)是庫存管理的計算單位。"
|
||||
|
||||
#. module: mrp
|
||||
#: report:bom.structure:0
|
||||
|
@ -824,7 +840,7 @@ msgstr "標示為開始"
|
|||
#. module: mrp
|
||||
#: view:mrp.production:0
|
||||
msgid "Partial"
|
||||
msgstr "部份"
|
||||
msgstr "分批"
|
||||
|
||||
#. module: mrp
|
||||
#: report:mrp.production.order:0
|
||||
|
|
|
@ -99,8 +99,6 @@ class mrp_workcenter(osv.osv):
|
|||
value = {'costs_hour': cost.standard_price}
|
||||
return {'value': value}
|
||||
|
||||
|
||||
|
||||
class mrp_routing(osv.osv):
|
||||
"""
|
||||
For specifying the routings of Work Centers.
|
||||
|
@ -288,16 +286,20 @@ class mrp_bom(osv.osv):
|
|||
(_check_product, 'BoM line product should not be same as BoM product.', ['product_id']),
|
||||
]
|
||||
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, name, context=None):
|
||||
def onchange_product_id(self, cr, uid, ids, product_id, name, product_qty=0, context=None):
|
||||
""" Changes UoM and name if product_id changes.
|
||||
@param name: Name of the field
|
||||
@param product_id: Changed product_id
|
||||
@return: Dictionary of changed values
|
||||
"""
|
||||
res = {}
|
||||
if product_id:
|
||||
prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
return {'value': {'name': prod.name, 'product_uom': prod.uom_id.id}}
|
||||
return {}
|
||||
res['value'] = {'name': prod.name, 'product_uom': prod.uom_id.id, 'product_uos_qty': 0, 'product_uos': False}
|
||||
if prod.uos_id.id:
|
||||
res['value']['product_uos_qty'] = product_qty * prod.uos_coeff
|
||||
res['value']['product_uos'] = prod.uos_id.id
|
||||
return res
|
||||
|
||||
def onchange_uom(self, cr, uid, ids, product_id, product_uom, context=None):
|
||||
res = {'value': {}}
|
||||
|
@ -597,16 +599,19 @@ class mrp_production(osv.osv):
|
|||
return {'value': {'location_dest_id': src}}
|
||||
return {}
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product_id, context=None):
|
||||
def product_id_change(self, cr, uid, ids, product_id, product_qty=0, context=None):
|
||||
""" Finds UoM of changed product.
|
||||
@param product_id: Id of changed product.
|
||||
@return: Dictionary of values.
|
||||
"""
|
||||
result = {}
|
||||
if not product_id:
|
||||
return {'value': {
|
||||
'product_uom': False,
|
||||
'bom_id': False,
|
||||
'routing_id': False
|
||||
'routing_id': False,
|
||||
'product_uos_qty': 0,
|
||||
'product_uos': False
|
||||
}}
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
|
@ -615,14 +620,13 @@ class mrp_production(osv.osv):
|
|||
if bom_id:
|
||||
bom_point = bom_obj.browse(cr, uid, bom_id, context=context)
|
||||
routing_id = bom_point.routing_id.id or False
|
||||
|
||||
product_uom_id = product.uom_id and product.uom_id.id or False
|
||||
result = {
|
||||
'product_uom': product_uom_id,
|
||||
'bom_id': bom_id,
|
||||
'routing_id': routing_id,
|
||||
}
|
||||
return {'value': result}
|
||||
product_uos_id = product.uos_id and product.uos_id.id or False
|
||||
result['value'] = {'product_uos_qty': 0, 'product_uos': False, 'product_uom': product_uom_id, 'bom_id': bom_id, 'routing_id': routing_id}
|
||||
if product.uos_id.id:
|
||||
result['value']['product_uos_qty'] = product_qty * product.uos_coeff
|
||||
result['value']['product_uos'] = product.uos_id.id
|
||||
return result
|
||||
|
||||
def bom_id_change(self, cr, uid, ids, bom_id, context=None):
|
||||
""" Finds routing for changed BoM.
|
||||
|
|
|
@ -347,10 +347,10 @@
|
|||
<form string="Bill of Material" version="7.0">
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name, context)" class="oe_inline"/>
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name, product_qty, context)" context="{'default_supply_method':'produce'}" class="oe_inline"/>
|
||||
<label for="product_qty" string="Quantity"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"/>
|
||||
<field name="product_qty" class="oe_inline" on_change="onchange_product_id(product_id, name, product_qty, context)"/>
|
||||
<field name="product_uom" class="oe_inline" on_change="onchange_uom(product_id, product_uom)" groups="product.group_uom"/>
|
||||
</div>
|
||||
<label for="product_uos_qty" groups="product.group_uos"/>
|
||||
|
@ -366,7 +366,7 @@
|
|||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="name" groups="base.group_no_one"/>
|
||||
<field name="name" groups="product.group_mrp_properties"/>
|
||||
<field name="code" string="Reference"/>
|
||||
<field name="type"/>
|
||||
<p colspan="2" class="oe_grey" attrs="{'invisible': [('type','=','normal')]}">
|
||||
|
@ -687,15 +687,14 @@
|
|||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id" on_change="product_id_change(product_id)" domain="[('bom_ids','!=',False),('bom_ids.bom_id','=',False)]" class="oe_inline" context='{"default_type": "product"}'/>
|
||||
<field name="product_id" on_change="product_id_change(product_id, product_qty)" domain="[('bom_ids','!=',False),('bom_ids.bom_id','=',False)]" class="oe_inline" context='{"default_supply_method":"produce", "default_type": "product"}'/>
|
||||
<label for="product_qty"/>
|
||||
<div>
|
||||
<field name="product_qty" class="oe_inline"/>
|
||||
<field name="product_qty" class="oe_inline" on_change="product_id_change(product_id, product_qty)"/>
|
||||
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
|
||||
<button type="action"
|
||||
icon="terp-accessories-archiver+"
|
||||
name="%(mrp.action_change_production_qty)d"
|
||||
string="(Update)" states="confirmed" class="oe_edit_only oe_link"/>
|
||||
string="Update" states="confirmed" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<label for="product_uos_qty" groups="product.group_uos"/>
|
||||
<div groups="product.group_uos">
|
||||
|
|
|
@ -544,11 +544,11 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.order.removeOrderline(this);
|
||||
return;
|
||||
}else{
|
||||
var quant = Math.max(parseFloat(quantity) || 0, 0);
|
||||
var quant = parseFloat(quantity) || 0;
|
||||
var unit = this.get_unit();
|
||||
if(unit){
|
||||
this.quantity = Math.max(unit.rounding, round_pr(quant, unit.rounding));
|
||||
this.quantityStr = this.quantity.toFixed(Math.max(0,Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10))));
|
||||
this.quantity = round_pr(quant, unit.rounding);
|
||||
this.quantityStr = this.quantity.toFixed(Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10)));
|
||||
}else{
|
||||
this.quantity = quant;
|
||||
this.quantityStr = '' + this.quantity;
|
||||
|
@ -1104,10 +1104,11 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}
|
||||
},
|
||||
switchSign: function() {
|
||||
console.log('switchsing');
|
||||
var oldBuffer;
|
||||
oldBuffer = this.get('buffer');
|
||||
this.set({
|
||||
buffer: oldBuffer[0] === '-' ? oldBuffer.substr(1) : "-" + oldBuffer
|
||||
buffer: oldBuffer[0] === '-' ? oldBuffer.substr(1) : "-" + oldBuffer
|
||||
});
|
||||
this.trigger('set_value',this.get('buffer'));
|
||||
},
|
||||
|
|
|
@ -1125,8 +1125,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
is_paid: function(){
|
||||
var currentOrder = this.pos.get('selectedOrder');
|
||||
return (currentOrder.getTotalTaxIncluded() >= 0.000001
|
||||
&& currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded());
|
||||
return (currentOrder.getTotalTaxIncluded() < 0.000001
|
||||
|| currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded());
|
||||
|
||||
},
|
||||
validate_order: function(options) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<!-- Resource: project.project -->
|
||||
<record id="all_projects_account" model="account.analytic.account">
|
||||
<field name="name">Projects</field>
|
||||
<field name="code">3</field>
|
||||
<field name="code">PP001</field>
|
||||
<field name="type">view</field>
|
||||
</record>
|
||||
<function id="parent_project_default_set" model="ir.values" name="set" eval="('default',False,'parent_id', [('project.project', False)], all_projects_account, True, False, False, False, True)"/>
|
||||
|
|
|
@ -48,7 +48,8 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem action="action_header_img" id="menu_header_img" parent="base.menu_custom" sequence="14"/>
|
||||
<menuitem id="menu_webkit" name="Webkit" parent="base.menu_custom"/>
|
||||
<menuitem action="action_header_img" id="menu_header_img" parent="menu_webkit" sequence="14"/>
|
||||
|
||||
<record id="action_header_webkit" model="ir.actions.act_window">
|
||||
<field name="name">Webkit Headers/Footers</field>
|
||||
|
@ -56,7 +57,7 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem action="action_header_webkit" id="menu_header_webkit" parent="base.menu_custom" sequence="14"/>
|
||||
<menuitem action="action_header_webkit" id="menu_header_webkit" parent="menu_webkit" sequence="14"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -301,7 +301,7 @@
|
|||
<field name="monthly_invoiced" widget="gauge" style="width:160px; height: 120px; cursor: pointer;"
|
||||
options="{'max_field': 'invoiced_target'}">Invoiced</field>
|
||||
<field name="invoiced_forecast" widget="gauge" style="width:160px; height: 120px; cursor: pointer;"
|
||||
options="{'max_field': 'invoiced_target', 'action_change': 'action_forecast'}">Forecast</field>
|
||||
options="{'max_field': 'invoiced_target', 'on_change': 'action_forecast'}">Forecast</field>
|
||||
</div>
|
||||
<div class="oe_center oe_salesteams_help" 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.
|
||||
|
|
|
@ -378,20 +378,25 @@ class Website(openerp.addons.web.controllers.main.Home):
|
|||
#------------------------------------------------------
|
||||
# Server actions
|
||||
#------------------------------------------------------
|
||||
@http.route(['/website/action/<id_or_xml_id>'], type='http', auth="public", website=True)
|
||||
def actions_server(self, id_or_xml_id, **post):
|
||||
|
||||
@http.route('/website/action/<path_or_xml_id_or_id>', type='http', auth="public", website=True)
|
||||
def actions_server(self, path_or_xml_id_or_id, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
res, action_id, action = None, None, None
|
||||
ServerActions = request.registry['ir.actions.server']
|
||||
|
||||
# find the action_id, either an int, an int into a basestring, or an xml_id
|
||||
if isinstance(id_or_xml_id, basestring) and '.' in id_or_xml_id:
|
||||
action_id = request.registry['ir.model.data'].xmlid_to_res_id(request.cr, request.uid, id_or_xml_id, raise_if_not_found=False)
|
||||
else:
|
||||
# find the action_id: either an xml_id, the path, or an ID
|
||||
if isinstance(path_or_xml_id_or_id, basestring) and '.' in path_or_xml_id_or_id:
|
||||
action_id = request.registry['ir.model.data'].xmlid_to_res_id(request.cr, request.uid, path_or_xml_id_or_id, raise_if_not_found=False)
|
||||
if not action_id:
|
||||
action_ids = ServerActions.search(cr, uid, [('website_path', '=', path_or_xml_id_or_id), ('website_published', '=', True)], context=context)
|
||||
action_id = action_ids and action_ids[0] or None
|
||||
if not action_id:
|
||||
try:
|
||||
action_id = int(id_or_xml_id)
|
||||
action_id = int(path_or_xml_id_or_id)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# check it effectively exists
|
||||
if action_id:
|
||||
action_ids = ServerActions.exists(cr, uid, [action_id], context=context)
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<field name="name">Website Partner Post and Thanks Demo</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="website_path">partner_thanks</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="code">
|
||||
partner_id, partner = False, None
|
||||
|
@ -118,6 +119,7 @@ response = request.website.render("website.template_partner_post", values)
|
|||
<field name="name">Website Partners Comment Form</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="website_published" eval="True"/>
|
||||
<field name="website_path">partner_comment</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="code">
|
||||
partner_ids = pool['res.partner'].search(cr, uid, [('customer', '=', True)], context=context)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import urlparse
|
||||
|
||||
from openerp.addons.web.http import request
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
@ -9,15 +11,43 @@ class actions_server(osv.Model):
|
|||
_name = 'ir.actions.server'
|
||||
_inherit = ['ir.actions.server']
|
||||
|
||||
def _compute_website_url(self, cr, uid, id, website_path, xml_id, context=None):
|
||||
base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url', context=context)
|
||||
link = website_path or xml_id or (id and '%d' % id) or ''
|
||||
if base_url and link:
|
||||
path = '%s/%s' % ('/website/action', link)
|
||||
return '%s' % urlparse.urljoin(base_url, path)
|
||||
return ''
|
||||
|
||||
def _get_website_url(self, cr, uid, ids, name, args, context=None):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for action in self.browse(cr, uid, ids, context=context):
|
||||
if action.state == 'code' and action.website_published:
|
||||
res[action.id] = self._compute_website_url(cr, uid, action.id, action.website_path, action.xml_id, context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'xml_id': fields.function(
|
||||
osv.osv.get_xml_id, type='char', string="External ID",
|
||||
help="ID of the action if defined in a XML file"),
|
||||
'website_path': fields.char('Website Path'),
|
||||
'website_url': fields.function(
|
||||
_get_website_url, type='char', string='Website URL',
|
||||
help='The full URL to access the server action through the website.'),
|
||||
'website_published': fields.boolean(
|
||||
'Available on the Website',
|
||||
help='A code server action can be executed from the website, using a dedicated'
|
||||
'controller. The address is <base>/website/action/<id_or_xml_id>.'
|
||||
'controller. The address is <base>/website/action/<website_path>.'
|
||||
'Set this field as True to allow users to run this action. If it'
|
||||
'set to is False the action cannot be run through the website.'),
|
||||
}
|
||||
|
||||
def on_change_website_path(self, cr, uid, ids, website_path, xml_id, context=None):
|
||||
values = {
|
||||
'website_url': self._compute_website_url(cr, uid, ids[0], website_path, xml_id, context=context)
|
||||
}
|
||||
return {'value': values}
|
||||
|
||||
def _get_eval_context(self, cr, uid, action, context=None):
|
||||
""" Override to add the request object in eval_context. """
|
||||
eval_context = super(actions_server, self)._get_eval_context(cr, uid, action, context=context)
|
||||
|
|
|
@ -399,7 +399,7 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
|||
}
|
||||
|
||||
.oe_green {
|
||||
background-color: #51d466;
|
||||
background-color: #169c78;
|
||||
color: white;
|
||||
}
|
||||
.oe_green .text-muted {
|
||||
|
@ -407,7 +407,7 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
|||
}
|
||||
|
||||
.oe_blue_light {
|
||||
background-color: #4791d2;
|
||||
background-color: #41b6ab;
|
||||
color: white;
|
||||
}
|
||||
.oe_blue_light .text-muted {
|
||||
|
@ -420,7 +420,7 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
|||
}
|
||||
|
||||
.oe_orange {
|
||||
background-color: #e67e22;
|
||||
background-color: #f05442;
|
||||
color: white;
|
||||
}
|
||||
.oe_orange .text-muted {
|
||||
|
@ -436,7 +436,7 @@ div.carousel[data-snippet-id="slider"] .carousel-indicators .active {
|
|||
}
|
||||
|
||||
.oe_red {
|
||||
background-color: #f75353;
|
||||
background-color: #9c1b31;
|
||||
color: white;
|
||||
}
|
||||
.oe_red .text-muted {
|
||||
|
|
|
@ -328,13 +328,13 @@ div.carousel[data-snippet-id="slider"]
|
|||
color: white
|
||||
|
||||
.oe_green
|
||||
background-color: #51d466
|
||||
background-color: #169C78
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
||||
.oe_blue_light
|
||||
background-color: #4791d2
|
||||
background-color: #41b6ab
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
@ -344,7 +344,7 @@ div.carousel[data-snippet-id="slider"]
|
|||
color: white
|
||||
|
||||
.oe_orange
|
||||
background-color: #e67e22
|
||||
background-color: #f05442
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
@ -356,7 +356,7 @@ div.carousel[data-snippet-id="slider"]
|
|||
color: #ddd
|
||||
|
||||
.oe_red
|
||||
background-color: #f75353
|
||||
background-color: #9C1b31
|
||||
color: white
|
||||
.text-muted
|
||||
color: #ddd
|
||||
|
|
Before Width: | Height: | Size: 370 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 392 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 825 KiB After Width: | Height: | Size: 199 KiB |
Before Width: | Height: | Size: 584 KiB After Width: | Height: | Size: 223 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 348 KiB |
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 290 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 732 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 27 KiB |
|
@ -8,7 +8,7 @@ class TestUi(openerp.tests.HttpCase):
|
|||
def test_public(self):
|
||||
inject = [
|
||||
"./../../../website/static/src/js/website.tour.test.js",
|
||||
"./../../../website/static/src/js/website.tour.test.admin.js"i
|
||||
"./../../../website/static/src/js/website.tour.test.admin.js",
|
||||
]
|
||||
self.phantom_js("/", "openerp.website.Tour.run_test('login_edit')", "openerp.website.Tour", inject=inject);
|
||||
|
||||
|
|
|
@ -6,10 +6,43 @@
|
|||
<field name="name">ir.actions.server.form.website</field>
|
||||
<field name="model">ir.actions.server</field>
|
||||
<field name="inherit_id" ref="base.view_server_action_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//field[@name='state']" position="after">
|
||||
<field name="website_published"
|
||||
attrs="{'invisible': [('state', '!=', 'code')]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='sequence']" position="after">
|
||||
<field name="xml_id" invisible="1"/>
|
||||
<field name="website_path"
|
||||
on_change="on_change_website_path(website_path, xml_id, context)"
|
||||
attrs="{'invisible': ['|', ('website_published', '!=', True), ('state', '!=', 'code')]}"/>
|
||||
<field name="website_url" readonly="1"
|
||||
attrs="{'invisible': ['|', ('website_published', '!=', True), ('state', '!=', 'code')]}"/>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_server_action_tree_website">
|
||||
<field name="name">ir.actions.server.tree.website</field>
|
||||
<field name="model">ir.actions.server</field>
|
||||
<field name="inherit_id" ref="base.view_server_action_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='sequence']" position="after">
|
||||
<field name="website_url"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_server_action_search_website">
|
||||
<field name="name">ir.actions.server.search.website</field>
|
||||
<field name="model">ir.actions.server</field>
|
||||
<field name="inherit_id" ref="base.view_server_action_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='state']" position="after">
|
||||
<field name="website_published"
|
||||
attrs="{'invisible': [('state', '!=', 'code')]}"/>
|
||||
<filter string="Website" name="website"
|
||||
domain="[('website_published', '=', True), ('state', '=', 'code')]"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -907,7 +907,7 @@
|
|||
<li data-class='oe_dark'><a>Darken</a></li>
|
||||
<li data-class='oe_green'><a>Green</a></li>
|
||||
<li data-class='oe_red'><a>Red</a></li>
|
||||
<li data-class='oe_blue_light'><a>Light Blue</a></li>
|
||||
<li data-class='oe_blue_light'><a>Turquoise</a></li>
|
||||
<li data-class='oe_blue'><a>Dark Blue</a></li>
|
||||
<li data-class='oe_orange'><a>Orange</a></li>
|
||||
<li data-class='oe_purple'><a>Purple</a></li>
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
"widget": "monetary",
|
||||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'/>
|
||||
<meta itemprop="price" t-att-content="ticket.price"/>
|
||||
<meta itemprop="priceCurrency" t-att-content="website.pricelist_id.currency_id.name"/>
|
||||
<span itemprop="price" style="display:none;" t-esc="ticket.price"/>
|
||||
<span itemprop="priceCurrency" style="display:none;" t-esc="website.pricelist_id.currency_id.name"/>
|
||||
</t>
|
||||
<t t-if="not ticket.price and not editable">
|
||||
<span>Free</span>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
'version': '0.1',
|
||||
'description': """Glue module holding mail improvements for website.""",
|
||||
'author': 'OpenERP SA',
|
||||
'depends': ['website', 'mail'],
|
||||
'depends': ['website', 'mail', 'email_template'],
|
||||
'data': [
|
||||
'views/snippets.xml',
|
||||
'views/website_mail.xml',
|
||||
|
|
|
@ -30,7 +30,7 @@ class EmailTemplate(osv.Model):
|
|||
_inherit = 'email.template'
|
||||
|
||||
def _get_website_link(self, cr, uid, ids, name, args, context=None):
|
||||
return dict((id, _('<a href="website_mail/email_designer/%s">Edit in Website</a>') % id) for id in ids)
|
||||
return dict((id, _('<a href="website_mail/email_designer/%s">Open with visual editor</a>') % id) for id in ids)
|
||||
|
||||
_columns = {
|
||||
'website_link': fields.function(
|
||||
|
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -6,8 +6,10 @@
|
|||
<field name="model">email.template</field>
|
||||
<field name="inherit_id" ref="email_template.email_template_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@string='Mailing Template']/group" position="before">
|
||||
<field name="website_link" widget='html' radonly='1'/>
|
||||
<xpath expr="//field[@name='model']" position="before">
|
||||
<br />
|
||||
<field name="website_link" widget='html' radonly='1'
|
||||
style='margin: 0px; padding: 0px;'/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -5,14 +5,62 @@
|
|||
|
||||
<div class="scroll" t-ignore="1">
|
||||
<ul class="nav navbar-nav nav-tabs">
|
||||
<li class="active"><a href="#snippet_structure" data-toggle="tab">Structure</a></li>
|
||||
<li><a href="#snippet_content" data-toggle="tab">Content</a></li>
|
||||
<li><a href="#snippet_feature" data-toggle="tab">Features</a></li>
|
||||
<li><a href="#snippet_effect" data-toggle="tab">Effects</a></li>
|
||||
<li class="active"><a href="#snippet_email_structure" data-toggle="tab">Email Design</a></li>
|
||||
<li><a href="#snippet_email_feature" data-toggle="tab">Advanced Email Features</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
|
||||
<div id="snippet_structure" class="tab-pane fade in active">
|
||||
<div id="snippet_email_structure" class="tab-pane fade in active">
|
||||
|
||||
|
||||
<div data-snippet-id="text-image" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_text_block.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Text Block</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px 5px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<h2 style="text-align: center">
|
||||
A Great Headline
|
||||
</h2>
|
||||
<h3 style="text-align: center">
|
||||
A good subtitle
|
||||
</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<p style="overflow:hidden">
|
||||
A great way to catch your reader's attention is to tell a story.
|
||||
Everything you consider writing can be told as a story.
|
||||
</p>
|
||||
<p style="overflow:hidden">
|
||||
<strong>Great stories have personality</strong>. Consider telling
|
||||
a great story that provides personality. Writing a story
|
||||
with personality for potential clients will asist with
|
||||
making a relationship connection. This shows up in small
|
||||
quirks like word choices or phrases. Write from your point
|
||||
of view, not from someone else's experience.
|
||||
</p>
|
||||
<p style="overflow:hidden">
|
||||
<strong>Great stories are for everyone even when only written for
|
||||
just one person</strong>. If you try to write with a wide general
|
||||
audience in mind, your story will ring false and be bland.
|
||||
No one will be interested. Write for one person. If it’s genuine
|
||||
for the one, it’s genuine for the rest.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="text-image" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
|
@ -97,125 +145,34 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="text-image" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div data-snippet-id="three-columns" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_jumbotron.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Big Message</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px 5px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<h1 style="text-align: center">Sell Online. Easily.</h1>
|
||||
<p style="overflow:hidden">
|
||||
Write one sentence to convince visitor about your message.
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="text-image" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_text_block.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Text Block</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px 5px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<h2 style="text-align: center">
|
||||
A Great Headline
|
||||
</h2>
|
||||
<h3 style="text-align: center">
|
||||
A good subtitle
|
||||
</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<p style="overflow:hidden">
|
||||
A great way to catch your reader's attention is to tell a story.
|
||||
Everything you consider writing can be told as a story.
|
||||
</p>
|
||||
<p style="overflow:hidden">
|
||||
<strong>Great stories have personality</strong>. Consider telling
|
||||
a great story that provides personality. Writing a story
|
||||
with personality for potential clients will asist with
|
||||
making a relationship connection. This shows up in small
|
||||
quirks like word choices or phrases. Write from your point
|
||||
of view, not from someone else's experience.
|
||||
</p>
|
||||
<p style="overflow:hidden">
|
||||
<strong>Great stories are for everyone even when only written for
|
||||
just one person</strong>. If you try to write with a wide general
|
||||
audience in mind, your story will ring false and be bland.
|
||||
No one will be interested. Write for one person. If it’s genuine
|
||||
for the one, it’s genuine for the rest.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="hr" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_separator.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Separator</span>
|
||||
<img class="oe_snippet_thumbnail_img" src="/website_mail/static/src/img/blocks/block_two_columns.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Two Columns</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0"/>
|
||||
</div>
|
||||
<td valign="top" style="width:300px">
|
||||
<img width="275" style="display:block;border:none;min-height:50px" src="/website/static/src/img/desert_thumb.jpg"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="big-picture" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_big_picture.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Big Picture</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<h2 style="text-align: center; padding:0px 5px">A Punchy Headline</h2>
|
||||
<td valign="top" style="width:300px">
|
||||
<img width="275" style="display:block;border:none;min-height:50px" src="/website/static/src/img/deers_thumb.jpg"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<img width="500" style="display:block;border:none;min-height:250px;margin:0 auto;" src="/website/static/src/img/big_picture.png"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<p style="text-align: center; overflow:hidden">
|
||||
<h3 style="text-align: center; padding:0px 5px">A Small Subtitle</h3>
|
||||
<td valign="top" style="width:300px">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature One</h3>
|
||||
<p style="overflow:hidden">
|
||||
Choose a vibrant image and write an inspiring paragraph
|
||||
about it. It does not have to be long, but it should
|
||||
reinforce your image.
|
||||
</p>
|
||||
<p style="text-align: center; overflow:hidden">
|
||||
</td>
|
||||
<td valign="top" style="width:300px">
|
||||
<h3 style="text-align: center; padding:0px 5px">Feature Two</h3>
|
||||
<p style="overflow:hidden">
|
||||
Choose a vibrant image and write an inspiring paragraph
|
||||
about it. It does not have to be long, but it should
|
||||
reinforce your image.
|
||||
|
@ -230,7 +187,7 @@
|
|||
|
||||
<div data-snippet-id="three-columns" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_three_columns.png"/>
|
||||
<img class="oe_snippet_thumbnail_img" src="/website_mail/static/src/img/blocks/block_three_columns.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Three Columns</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
|
@ -278,10 +235,67 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="hr" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_separator.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Separator</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="snippet_feature" class="tab-pane fade">
|
||||
<div id="snippet_email_feature" class="tab-pane fade">
|
||||
|
||||
|
||||
<div data-snippet-id="big-picture" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_big_picture.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Big Picture</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<h2 style="text-align: center; padding:0px 5px">A Punchy Headline</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<img width="500" style="display:block;border:none;min-height:250px;margin:0 auto;" src="/website/static/src/img/big_picture.png"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<p style="text-align: center; overflow:hidden">
|
||||
<h3 style="text-align: center; padding:0px 5px">A Small Subtitle</h3>
|
||||
</p>
|
||||
<p style="text-align: center; overflow:hidden">
|
||||
Choose a vibrant image and write an inspiring paragraph
|
||||
about it. It does not have to be long, but it should
|
||||
reinforce your image.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="pricing" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
|
@ -375,6 +389,30 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="text-image" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_jumbotron.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Big Message</span>
|
||||
</div>
|
||||
<div class="oe_snippet_body" style="padding:0px; margin:0px">
|
||||
<table cellspacing="0" cellpadding="0" style="margin:10px 0px 0px;vertical-align:top;padding:0px 5px;font-family:arial;font-size:12px;color:rgb(51,51,51)">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="width:600px">
|
||||
<div style="padding:0px 5px">
|
||||
<h1 style="text-align: center">Sell Online. Easily.</h1>
|
||||
<p style="overflow:hidden">
|
||||
Write one sentence to convince visitor about your message.
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="cta" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_button.png"/>
|
||||
|
@ -443,8 +481,6 @@
|
|||
|
||||
</div>
|
||||
|
||||
<div id="snippet_effect" class="tab-pane fade">
|
||||
</div>
|
||||
|
||||
<div id="snippet_styles" class="hidden">
|
||||
</div>
|
||||
|
|
|
@ -10,35 +10,43 @@
|
|||
</t>
|
||||
<div id="wrap">
|
||||
<div class="container">
|
||||
<h1 t-field="template.name"/>
|
||||
<div class="row" style="width: 600px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Email From</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.email_from"/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<a class="pull-right mt32"
|
||||
t-att-href="'/web#return_label=Website&action=email_template.action_email_template_tree_all&view_type=form&id=%d' % template.id">
|
||||
<button class="btn btn-primary">Back to Template Form</button>
|
||||
</a>
|
||||
<h1 t-field="template.name"/>
|
||||
<div class="row" style="width: 600px;">
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Email From</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.email_from"/></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>To (Email)</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.email_to"/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>To (Email)</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.email_to"/></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>To (Partners)</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.partner_to"/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>To (Partners)</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.partner_to"/></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Reply To</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.reply_to"/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Reply To</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.reply_to"/></div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Subject</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.subject"/></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-3"><b>Subject</b></div>
|
||||
<div class="col-lg-9"><span t-field="template.subject"/></div>
|
||||
</div>
|
||||
|
||||
<div class="row well">
|
||||
<div t-field="template.body_html" style="position: relative;"/>
|
||||
<div class="row well">
|
||||
<div t-field="template.body_html" style="position: relative;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -81,8 +81,8 @@
|
|||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'>
|
||||
</span>
|
||||
<meta itemprop="price" t-att-content="product.product_variant_ids[0].price"/>
|
||||
<meta itemprop="priceCurrency" t-att-content="website.pricelist_id.currency_id.name"/>
|
||||
<span itemprop="price" style="display:none;" t-esc="product.product_variant_ids[0].price"/>
|
||||
<span itemprop="priceCurrency" style="display:none;" t-esc="website.pricelist_id.currency_id.name"/>
|
||||
</b>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -303,7 +303,7 @@
|
|||
<span itemprop="image" t-field="product.image" t-field-options='{"widget": "image", "class": "product_detail_img"}'/>
|
||||
</div><div class="col-sm-5 col-md-5 col-lg-4 col-lg-offset-1">
|
||||
<h1 itemprop="name" t-field="product.name">Product Name</h1>
|
||||
<meta itemprop="url" t-attf-content="/shop/product/{{ slug(product) }}"/>
|
||||
<span itemprop="url" style="display:none;" t-esc="'/shop/product/%s' % slug(product)"/>
|
||||
<form action="/shop/add_cart/" class="js_add_cart_json" method="POST">
|
||||
<input type="hidden" t-if="len(product.product_variant_ids) == 1" name="product_id" t-att-value="product.product_variant_ids[0].id"/>
|
||||
<t t-if="len(product.product_variant_ids) > 1">
|
||||
|
@ -335,8 +335,8 @@
|
|||
"widget": "monetary",
|
||||
"display_currency": "website.pricelist_id.currency_id"
|
||||
}'/>
|
||||
<meta itemprop="price" t-att-content="product.product_variant_ids[0].price"/>
|
||||
<meta itemprop="priceCurrency" t-att-content="website.pricelist_id.currency_id.name"/>
|
||||
<span itemprop="price" style="display:none;" t-esc="product.product_variant_ids[0].price"/>
|
||||
<span itemprop="priceCurrency" style="display:none;" t-esc="website.pricelist_id.currency_id.name"/>
|
||||
</h4>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg mt8">Add to Cart</button>
|
||||
|
|