[MERGE] Merge with trunk
bzr revid: jke@openerp.com-20140502123149-4g7d7xh07i5z9dct
This commit is contained in:
commit
ed6bc9f198
|
@ -139,20 +139,12 @@ for a particular financial year and for preparation of vouchers there is a modul
|
|||
'project/views/report_analyticcostledgerquantity.xml',
|
||||
'project/views/report_analyticcostledger.xml',
|
||||
'project/views/report_invertedanalyticbalance.xml',
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/account_move_reconciliation.js',
|
||||
'static/src/js/account_move_line_quickadd.js',
|
||||
'views/account.xml',
|
||||
],
|
||||
'qweb' : [
|
||||
"static/src/xml/account_move_reconciliation.xml",
|
||||
"static/src/xml/account_move_line_quickadd.xml",
|
||||
],
|
||||
'css':[
|
||||
'static/src/css/account_move_reconciliation.css',
|
||||
'static/src/css/account_move_line_quickadd.css',
|
||||
'static/src/css/account_bank_and_cash.css',
|
||||
],
|
||||
'demo': [
|
||||
'demo/account_demo.xml',
|
||||
'project/project_demo.xml',
|
||||
|
|
|
@ -1944,15 +1944,17 @@ class account_tax(osv.osv):
|
|||
return super(account_tax, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
if context is None:
|
||||
context = {}
|
||||
journal_pool = self.pool.get('account.journal')
|
||||
|
||||
if context and context.has_key('type'):
|
||||
if context.get('type'):
|
||||
if context.get('type') in ('out_invoice','out_refund'):
|
||||
args += [('type_tax_use','in',['sale','all'])]
|
||||
elif context.get('type') in ('in_invoice','in_refund'):
|
||||
args += [('type_tax_use','in',['purchase','all'])]
|
||||
|
||||
if context and context.has_key('journal_id'):
|
||||
if context.get('journal_id'):
|
||||
journal = journal_pool.browse(cr, uid, context.get('journal_id'))
|
||||
if journal.type in ('sale', 'purchase'):
|
||||
args += [('type_tax_use','in',[journal.type,'all'])]
|
||||
|
|
|
@ -409,9 +409,7 @@ class account_invoice(osv.osv):
|
|||
'''
|
||||
assert len(ids) == 1, 'This option should only be used for a single id at a time.'
|
||||
self.write(cr, uid, ids, {'sent': True}, context=context)
|
||||
context2 = context.copy()
|
||||
context2['active_ids'] = ids
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_invoice', context=context2)
|
||||
return self.pool['report'].get_action(cr, uid, [], 'account.report_invoice', context=context)
|
||||
|
||||
def action_invoice_sent(self, cr, uid, ids, context=None):
|
||||
'''
|
||||
|
|
|
@ -457,7 +457,7 @@
|
|||
<filter name="invoices" string="Invoices" domain="[('state','not in',['draft','cancel'])]" help="Proforma/Open/Paid Invoices"/>
|
||||
<filter name="unpaid" string="Unpaid" domain="[('state','=','open')]" help="Unpaid Invoices"/>
|
||||
<separator/>
|
||||
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="user_id" string="Salesperson"/>
|
||||
<field name="period_id" string="Period"/>
|
||||
<separator/>
|
||||
|
|
|
@ -1034,10 +1034,14 @@ class account_move_line(osv.osv):
|
|||
part_rec_ids = [rec['reconcile_partial_id'][0] for rec in part_recs]
|
||||
unlink_ids += rec_ids
|
||||
unlink_ids += part_rec_ids
|
||||
all_moves = obj_move_line.search(cr, uid, ['|',('reconcile_id', 'in', unlink_ids),('reconcile_partial_id', 'in', unlink_ids)])
|
||||
all_moves = list(set(all_moves) - set(move_ids))
|
||||
if unlink_ids:
|
||||
if opening_reconciliation:
|
||||
obj_move_rec.write(cr, uid, unlink_ids, {'opening_reconciliation': False})
|
||||
obj_move_rec.unlink(cr, uid, unlink_ids)
|
||||
if all_moves:
|
||||
obj_move_line.reconcile_partial(cr, uid, all_moves, 'auto',context=context)
|
||||
return True
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None, check=True):
|
||||
|
|
|
@ -65,7 +65,8 @@
|
|||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button type="action" string="Invoices"
|
||||
name="%(account.action_invoice_tree)d"
|
||||
name="%(account.action_invoice_tree1)d"
|
||||
attrs="{'invisible': [('customer', '=', False)]}"
|
||||
context="{'search_default_partner_id': active_id,'default_partner_id': active_id}" groups="account.group_account_invoice"/>
|
||||
<button type="action" string="Journal Items" name="%(account.action_account_moves_all_tree)d" groups="account.group_account_user"/>
|
||||
<button type="action" string="Contracts" name="%(account.action_open_partner_analytic_accounts)d"
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<search string="Analytic Account">
|
||||
<field name="name" filter_domain="['|', ('name','ilike',self), ('code','ilike',self)]" string="Analytic Account"/>
|
||||
<field name="date"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="manager_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="user_id"/>
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="account assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/account/static/src/css/account_move_reconciliation.css"/>
|
||||
<link rel="stylesheet" href="/account/static/src/css/account_move_line_quickadd.css"/>
|
||||
<link rel="stylesheet" href="/account/static/src/css/account_bank_and_cash.css"/>
|
||||
<script type="text/javascript" src="/account/static/src/js/account_move_reconciliation.js"></script>
|
||||
<script type="text/javascript" src="/account/static/src/js/account_move_line_quickadd.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -40,9 +40,7 @@ Adds menu to show relevant information to each manager.You can also view the rep
|
|||
'account_analytic_analysis_view.xml',
|
||||
'account_analytic_analysis_cron.xml',
|
||||
'res_config_view.xml',
|
||||
],
|
||||
'css': [
|
||||
'static/src/css/analytic.css'
|
||||
'views/account_analytic_analysis.xml',
|
||||
],
|
||||
'demo': ['analytic_account_demo.xml'],
|
||||
'test': ['test/account_analytic_analysis.yml'],
|
||||
|
|
|
@ -22,6 +22,7 @@ from dateutil.relativedelta import relativedelta
|
|||
import datetime
|
||||
import logging
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.osv.orm import intersect, except_orm
|
||||
|
@ -72,9 +73,7 @@ class account_analytic_invoice_line(osv.osv):
|
|||
|
||||
result = {}
|
||||
res = self.pool.get('product.product').browse(cr, uid, product, context=context)
|
||||
result.update({'name':res.partner_ref or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': res.list_price or 0.0})
|
||||
if res.description:
|
||||
result['name'] += '\n'+res.description
|
||||
result.update({'name': name or res.description or False,'uom_id': uom_id or res.uom_id.id or False, 'price_unit': price_unit or res.list_price or 0.0})
|
||||
|
||||
res_final = {'value':result}
|
||||
if result['uom_id'] != res.uom_id.id:
|
||||
|
@ -721,23 +720,40 @@ class account_analytic_account(osv.osv):
|
|||
inv_obj.button_compute(cr, uid, [invoice_id], context=context)
|
||||
return invoice_id
|
||||
|
||||
def recurring_create_invoice(self, cr, uid, automatic=False, context=None):
|
||||
def recurring_create_invoice(self, cr, uid, ids, context=None):
|
||||
return self._recurring_create_invoice(cr, uid, ids, context=context)
|
||||
|
||||
def _cron_recurring_create_invoice(self, cr, uid, context=None):
|
||||
return self._recurring_create_invoice(cr, uid, [], automatic=True, context=context)
|
||||
|
||||
def _recurring_create_invoice(self, cr, uid, ids, automatic=False, context=None):
|
||||
context = context or {}
|
||||
current_date = time.strftime('%Y-%m-%d')
|
||||
|
||||
contract_ids = self.search(cr, uid, [('recurring_next_date','<=', current_date), ('state','=', 'open'), ('recurring_invoices','=', True)])
|
||||
if ids:
|
||||
contract_ids = ids
|
||||
else:
|
||||
contract_ids = self.search(cr, uid, [('recurring_next_date','<=', current_date), ('state','=', 'open'), ('recurring_invoices','=', True), ('type', '=', 'contract')])
|
||||
for contract in self.browse(cr, uid, contract_ids, context=context):
|
||||
invoice_id = self._prepare_invoice(cr, uid, contract, context=context)
|
||||
try:
|
||||
invoice_id = self._prepare_invoice(cr, uid, contract, context=context)
|
||||
|
||||
next_date = datetime.datetime.strptime(contract.recurring_next_date or current_date, "%Y-%m-%d")
|
||||
interval = contract.recurring_interval
|
||||
if contract.recurring_rule_type == 'daily':
|
||||
new_date = next_date+relativedelta(days=+interval)
|
||||
elif contract.recurring_rule_type == 'weekly':
|
||||
new_date = next_date+relativedelta(weeks=+interval)
|
||||
else:
|
||||
new_date = next_date+relativedelta(months=+interval)
|
||||
self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context)
|
||||
next_date = datetime.datetime.strptime(contract.recurring_next_date or current_date, "%Y-%m-%d")
|
||||
interval = contract.recurring_interval
|
||||
if contract.recurring_rule_type == 'daily':
|
||||
new_date = next_date+relativedelta(days=+interval)
|
||||
elif contract.recurring_rule_type == 'weekly':
|
||||
new_date = next_date+relativedelta(weeks=+interval)
|
||||
else:
|
||||
new_date = next_date+relativedelta(months=+interval)
|
||||
self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context)
|
||||
if automatic:
|
||||
cr.commit()
|
||||
except Exception:
|
||||
if automatic:
|
||||
cr.rollback()
|
||||
_logger.error(traceback.format_exc())
|
||||
else:
|
||||
raise
|
||||
return True
|
||||
|
||||
class account_analytic_account_summary_user(osv.osv):
|
||||
|
|
|
@ -93,7 +93,7 @@ OpenERP Automatic Email
|
|||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="model" eval="'account.analytic.account'"/>
|
||||
<field name="function" eval="'recurring_create_invoice'"/>
|
||||
<field name="function" eval="'_cron_recurring_create_invoice'"/>
|
||||
<field name="args" eval="'()'"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -151,8 +151,10 @@
|
|||
</group>
|
||||
<separator string="Recurring Invoices" attrs="{'invisible': [('recurring_invoices','!=',True)]}"/>
|
||||
<div>
|
||||
<field name="recurring_invoices" on_change="onchange_recurring_invoices(recurring_invoices, date_start)" class="oe_inline"/>
|
||||
<label for="recurring_invoices" />
|
||||
<div attrs="{'invisible': [('type','!=', 'contract'), ('recurring_invoices', '=', False)]}">
|
||||
<field name="recurring_invoices" on_change="onchange_recurring_invoices(recurring_invoices, date_start)" class="oe_inline" />
|
||||
<label for="recurring_invoices" />
|
||||
</div>
|
||||
<button class="oe_link" name="recurring_create_invoice" attrs="{'invisible': [('recurring_invoices','!=',True)]}" string="⇒ create invoices" type="object" groups="base.group_no_one"/>
|
||||
</div>
|
||||
<group attrs="{'invisible': [('recurring_invoices','!=',True)]}">
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
!record {model: account.analytic.account, id: contract_main}:
|
||||
partner_id: base.main_partner
|
||||
template_id: account_analytic_analysis.contract_template
|
||||
type: contract
|
||||
-
|
||||
I check that the contract inherited from data of the template
|
||||
-
|
||||
|
@ -32,7 +33,7 @@
|
|||
I generate all invoices from contracts having recurring invoicing
|
||||
-
|
||||
!python {model: account.analytic.account}: |
|
||||
self.recurring_create_invoice(cr, uid)
|
||||
self.recurring_create_invoice(cr, uid, [])
|
||||
-
|
||||
I test the generated invoice
|
||||
-
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="account_analytic_analysis assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/account_analytic_analysis/static/src/css/analytic.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -454,15 +454,10 @@ class account_bank_statement(osv.osv):
|
|||
_inherit = "account.bank.statement"
|
||||
_name = "account.bank.statement"
|
||||
|
||||
def create_move_from_st_line(self, cr, uid, st_line_id, company_currency_id, st_line_number, context=None):
|
||||
account_move_line_pool = self.pool.get('account.move.line')
|
||||
account_bank_statement_line_pool = self.pool.get('account.bank.statement.line')
|
||||
st_line = account_bank_statement_line_pool.browse(cr, uid, st_line_id, context=context)
|
||||
result = super(account_bank_statement,self).create_move_from_st_line(cr, uid, st_line_id, company_currency_id, st_line_number, context=context)
|
||||
move = st_line.move_ids and st_line.move_ids[0] or False
|
||||
if move:
|
||||
for line in move.line_id:
|
||||
account_move_line_pool.write(cr, uid, [line.id], {'analytics_id':st_line.analytics_id.id}, context=context)
|
||||
def _prepare_bank_move_line(self, cr, uid, st_line, move_id, amount, company_currency_id, context=None):
|
||||
result = super(account_bank_statement,self)._prepare_bank_move_line(cr, uid, st_line,
|
||||
move_id, amount, company_currency_id, context=context)
|
||||
result['analytics_id'] = st_line.analytics_id.id
|
||||
return result
|
||||
|
||||
def button_confirm_bank(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -123,6 +123,8 @@ class account_invoice_line(osv.osv):
|
|||
if a == line['account_id'] and i_line.product_id.id == line['product_id']:
|
||||
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
|
||||
valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id)
|
||||
if inv.currency_id.id != company_currency:
|
||||
standard_price = self.pool.get('res.currency').compute(cr, uid, company_currency, inv.currency_id.id, standard_price, context={'date': inv.date_invoice})
|
||||
if i_line.product_id.cost_method != 'standard' and i_line.purchase_line_id:
|
||||
#for average/fifo/lifo costing method, fetch real cost price from incomming moves
|
||||
stock_move_obj = self.pool.get('stock.move')
|
||||
|
|
|
@ -783,6 +783,7 @@ class account_voucher(osv.osv):
|
|||
total_credit += line.credit and line.amount_currency or 0.0
|
||||
total_debit += line.debit and line.amount_currency or 0.0
|
||||
|
||||
remaining_amount = price
|
||||
#voucher line creation
|
||||
for line in account_move_lines:
|
||||
|
||||
|
@ -803,13 +804,13 @@ class account_voucher(osv.osv):
|
|||
'move_line_id':line.id,
|
||||
'account_id':line.account_id.id,
|
||||
'amount_original': amount_original,
|
||||
'amount': (line.id in move_lines_found) and min(abs(price), amount_unreconciled) or 0.0,
|
||||
'amount': (line.id in move_lines_found) and min(abs(remaining_amount), amount_unreconciled) or 0.0,
|
||||
'date_original':line.date,
|
||||
'date_due':line.date_maturity,
|
||||
'amount_unreconciled': amount_unreconciled,
|
||||
'currency_id': line_currency_id,
|
||||
}
|
||||
price -= rs['amount']
|
||||
remaining_amount -= rs['amount']
|
||||
#in case a corresponding move_line hasn't been found, we now try to assign the voucher amount
|
||||
#on existing invoices: we split voucher amount by most old first, but only for lines in the same currency
|
||||
if not move_lines_found:
|
||||
|
@ -937,19 +938,17 @@ class account_voucher(osv.osv):
|
|||
def cancel_voucher(self, cr, uid, ids, context=None):
|
||||
reconcile_pool = self.pool.get('account.move.reconcile')
|
||||
move_pool = self.pool.get('account.move')
|
||||
|
||||
move_line_pool = self.pool.get('account.move.line')
|
||||
for voucher in self.browse(cr, uid, ids, context=context):
|
||||
# refresh to make sure you don't unlink an already removed move
|
||||
voucher.refresh()
|
||||
recs = []
|
||||
for line in voucher.move_ids:
|
||||
if line.reconcile_id:
|
||||
recs += [line.reconcile_id.id]
|
||||
if line.reconcile_partial_id:
|
||||
recs += [line.reconcile_partial_id.id]
|
||||
|
||||
reconcile_pool.unlink(cr, uid, recs)
|
||||
|
||||
move_lines = [move_line.id for move_line in line.reconcile_id.line_id]
|
||||
move_lines.remove(line.id)
|
||||
reconcile_pool.unlink(cr, uid, [line.reconcile_id.id])
|
||||
if len(move_lines) >= 2:
|
||||
move_line_pool.reconcile_partial(cr, uid, move_lines, 'auto',context=context)
|
||||
if voucher.move_id:
|
||||
move_pool.button_cancel(cr, uid, [voucher.move_id.id])
|
||||
move_pool.unlink(cr, uid, [voucher.move_id.id])
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
!python {model: account.voucher}: |
|
||||
vals = {}
|
||||
journal_id = self.default_get(cr, uid, ['journal_id']).get('journal_id',None)
|
||||
voucher = self.recompute_voucher_lines(cr, uid, [], ref("base.res_partner_19"), journal_id, 450.0, ref('base.EUR'), 'receipt', False)
|
||||
assert (voucher['value'].get('writeoff_amount') == 0.0), "Writeoff amount calculated by recompute_voucher_lines() is not 0.0"
|
||||
res = self.onchange_partner_id(cr, uid, [], ref("base.res_partner_19"), journal_id, 0.0, 1, ttype='receipt', date=False)
|
||||
vals = {
|
||||
'account_id': ref('account.cash'),
|
||||
|
@ -64,6 +66,7 @@
|
|||
vals['line_cr_ids'] = [(0,0,i) for i in res['value']['line_cr_ids']]
|
||||
id = self.create(cr, uid, vals)
|
||||
voucher_id = self.browse(cr, uid, id)
|
||||
assert (voucher_id.writeoff_amount == 0.0), "Writeoff amount is not 0.0"
|
||||
assert (voucher_id.state=='draft'), "Voucher is not in draft state"
|
||||
self.signal_proforma_voucher(cr, uid, [voucher_id.id])
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ This module is for modifying account analytic view to show some data related to
|
|||
'depends': ['hr_expense','account_analytic_analysis'],
|
||||
'data': ['analytic_contract_hr_expense_view.xml'],
|
||||
'demo': [],
|
||||
'css' : [],
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
}
|
||||
|
|
|
@ -32,9 +32,10 @@ Allow users to login through OpenID.
|
|||
'maintainer': 'OpenERP s.a.',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['base', 'web'],
|
||||
'data': ['res_users.xml'],
|
||||
'js': ['static/src/js/auth_openid.js'],
|
||||
'css': ['static/src/css/openid.css'],
|
||||
'data': [
|
||||
'res_users.xml',
|
||||
'views/auth_openid.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/auth_openid.xml'],
|
||||
'external_dependencies': {
|
||||
'python' : ['openid'],
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="auth_openid assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/auth_openid/static/src/css/openid.css"/>
|
||||
<script type="text/javascript" src="/auth_openid/static/src/js/auth_openid.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -42,6 +42,5 @@ Allow users to sign up and reset their password
|
|||
'res_users_view.xml',
|
||||
'views/auth_signup_login.xml',
|
||||
],
|
||||
'js': [],
|
||||
'bootstrap': True,
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<data>
|
||||
<template id="auth_signup.login" inherit_id="web.login" name="Sign up - Reset Password">
|
||||
<xpath expr="//button[@type='submit']" position="before">
|
||||
<a t-if="signup_enabled" t-attf-href="/web/signup?redirect=/web%3f{{ quote_plus(keep_query()) }}" class="btn btn-link pull-right">Sign up</a>
|
||||
<a t-if="reset_password_enabled" t-attf-href="/web/reset_password?redirect=/web/login%3f{{ quote_plus(keep_query()) }}" class="btn btn-link pull-right">Reset Password</a>
|
||||
<a t-if="signup_enabled" t-attf-href="/web/signup?{{ keep_query() }}" class="btn btn-link pull-right">Sign up</a>
|
||||
<a t-if="reset_password_enabled" t-attf-href="/web/reset_password?{{ keep_query() }}" class="btn btn-link pull-right">Reset Password</a>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
@ -22,12 +22,13 @@
|
|||
<div class="form-group field-name">
|
||||
<label for="name" class="control-label">Your Name</label>
|
||||
<input type="text" name="name" t-att-value="name" id="name" class="form-control" placeholder="e.g. John Doe"
|
||||
required="required" t-att-readonly="'readonly' if only_passwords else None"/>
|
||||
required="required" t-att-readonly="'readonly' if only_passwords else None"
|
||||
t-att-autofocus="'autofocus' if login and not only_passwords else None" />
|
||||
</div>
|
||||
|
||||
<div class="form-group field-password">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<input type="password" name="password" autofocus="autofocus" id="password" class="form-control"
|
||||
<input type="password" name="password" id="password" class="form-control"
|
||||
required="required" t-att-autofocus="'autofocus' if only_passwords else None"/>
|
||||
</div>
|
||||
|
||||
|
@ -39,7 +40,7 @@
|
|||
|
||||
<template id="auth_signup.signup" name="Sign up login">
|
||||
<t t-call="web.login_layout">
|
||||
<form class="oe_signup_form" role="form" t-attf-action="/web/signup{{ '?debug' if debug else '' }}" method="post" t-if="not message">
|
||||
<form class="oe_signup_form" role="form" method="post" t-if="not message">
|
||||
|
||||
<t t-call="auth_signup.fields"/>
|
||||
|
||||
|
@ -49,7 +50,7 @@
|
|||
<input type="hidden" name="redirect" t-att-value="redirect"/>
|
||||
<input type="hidden" name="token" t-att-value="token"/>
|
||||
<div class="clearfix oe_login_buttons">
|
||||
<a href="/web/login" class="btn btn-link pull-right">Back to Login</a>
|
||||
<a t-attf-href="/web/login?{{ keep_query() }}" class="btn btn-link pull-right">Back to Login</a>
|
||||
<button type="submit" class="btn btn-primary pull-left">Sign up</button>
|
||||
</div>
|
||||
|
||||
|
@ -66,7 +67,7 @@
|
|||
<a href="/web/login" class="btn btn-link pull-right">Back to Login</a>
|
||||
</div>
|
||||
|
||||
<form class="oe_reset_password_form" role="form" t-attf-action="/web/reset_password{{ '?debug' if debug else '' }}" method="post" t-if="not message">
|
||||
<form class="oe_reset_password_form" role="form" method="post" t-if="not message">
|
||||
|
||||
<t t-if="token">
|
||||
<t t-call="auth_signup.fields">
|
||||
|
@ -88,7 +89,7 @@
|
|||
<input type="hidden" name="redirect" t-att-value="redirect"/>
|
||||
<input type="hidden" name="token" t-att-value="token"/>
|
||||
<div class="clearfix oe_login_buttons">
|
||||
<a href="/web/login" class="btn btn-link pull-right">Back to Login</a>
|
||||
<a t-attf-href="/web/login?{{ keep_query() }}" class="btn btn-link pull-right">Back to Login</a>
|
||||
<button type="submit" class="btn btn-primary pull-left">Reset password</button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//notebook[last()]" position="inside">
|
||||
<page string="Geo Localization" name="geo_localization" groups="base.group_no_one">
|
||||
<page string="Geo Localization" name="geo_localization">
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Geo Localization" colspan="2"/>
|
||||
<button
|
||||
|
|
|
@ -29,13 +29,7 @@ Re-implement openerp's file import system:
|
|||
'auto_install': True,
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'css': [
|
||||
'static/src/css/import.css',
|
||||
],
|
||||
'js': [
|
||||
'static/lib/javascript-state-machine/state-machine.js',
|
||||
'static/src/js/import.js',
|
||||
'views/base_import.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/import.xml'],
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="base_import assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/base_import/static/src/css/import.css"/>
|
||||
<script type="text/javascript" src="/base_import/static/lib/javascript-state-machine/state-machine.js"></script>
|
||||
<script type="text/javascript" src="/base_import/static/src/js/import.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -14,8 +14,6 @@ for customization purpose.
|
|||
'installable': True,
|
||||
'auto_install': False,
|
||||
'data': [],
|
||||
'css': [],
|
||||
'js': [],
|
||||
'qweb': [],
|
||||
'test': [],
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ Shows you a list of applications features to install from.
|
|||
'base_setup_views.xml',
|
||||
'res_config_view.xml',
|
||||
'res_partner_view.xml',
|
||||
'views/base_setup.xml',
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/base_setup1.jpeg','images/base_setup2.jpeg','images/base_setup3.jpeg','images/base_setup4.jpeg',],
|
||||
'css': ['static/src/css/base_setup.css'],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="base_setup assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/base_setup/static/src/css/base_setup.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -35,10 +35,9 @@ Allows users to create custom dashboard.
|
|||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'board_view.xml',
|
||||
'board_mydashboard_view.xml'
|
||||
'board_mydashboard_view.xml',
|
||||
'views/board.xml',
|
||||
],
|
||||
'js': ['static/src/js/dashboard.js'],
|
||||
'css': ['static/src/css/dashboard.css'],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -91,10 +91,10 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
|
|||
var $dialog = new instance.web.Dialog(this, {
|
||||
title: _t("Edit Layout"),
|
||||
}, QWeb.render('DashBoard.layouts', qdict)).open();
|
||||
$dialog.find('li').click(function() {
|
||||
$dialog.$el.find('li').click(function() {
|
||||
var layout = $(this).attr('data-layout');
|
||||
$dialog.modal('hide');
|
||||
self.do_change_layout(layout);
|
||||
$dialog.$dialog_box.modal('hide');
|
||||
});
|
||||
},
|
||||
do_change_layout: function(new_layout) {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="board assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/board/static/src/css/dashboard.css"/>
|
||||
<script type="text/javascript" src="/board/static/src/js/dashboard.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -44,14 +44,9 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'calendar_view.xml',
|
||||
'contacts_view.xml',
|
||||
'calendar_data.xml',
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/*.js'
|
||||
'views/calendar.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'css': [
|
||||
'static/src/css/calendar.css'
|
||||
],
|
||||
'test': [
|
||||
'test/calendar_test.yml',
|
||||
'test/test_calendar_recurrent_event_case2.yml'
|
||||
|
@ -59,5 +54,5 @@ If you need to manage your meetings, you should install the CRM module.
|
|||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/calendar1.jpeg','images/calendar2.jpeg','images/calendar3.jpeg','images/calendar4.jpeg'],
|
||||
'images': ['images/calendar1.jpeg', 'images/calendar2.jpeg', 'images/calendar3.jpeg', 'images/calendar4.jpeg'],
|
||||
}
|
||||
|
|
|
@ -1067,7 +1067,6 @@ class calendar_event(osv.Model):
|
|||
sort_fields[ord] = '%s-%s' % (browse_event[ord], r_date.strftime("%Y%m%d%H%M%S"))
|
||||
else:
|
||||
sort_fields[ord] = browse_event[ord]
|
||||
'If we sort on FK, we obtain a browse_record, so we need to sort on name_get'
|
||||
if type(browse_event[ord]) is openerp.osv.orm.browse_record:
|
||||
name_get = browse_event[ord].name_get()
|
||||
if len(name_get) and len(name_get[0]) >= 2:
|
||||
|
|
|
@ -39,8 +39,9 @@ class meeting_invitation(http.Controller):
|
|||
|
||||
if attendee:
|
||||
attendee_data['current_attendee'] = attendee[0]
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in webmain.manifest_list('js', db=db))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in webmain.manifest_list('css', db=db))
|
||||
|
||||
css = '<link rel="stylesheet" href="/web/css/web.assets_backend"/>'
|
||||
js = '<script type="text/javascript" src="/web/js/web.assets_backend"></script>'
|
||||
|
||||
return webmain.html_template % {
|
||||
'js': js,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="calendar assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/calendar/static/src/css/calendar.css"/>
|
||||
<script type="text/javascript" src="/calendar/static/src/js/base_calendar.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -92,6 +92,7 @@ Dashboard for CRM will include:
|
|||
'base_partner_merge_view.xml',
|
||||
|
||||
'crm_case_section_view.xml',
|
||||
'views/crm.xml',
|
||||
],
|
||||
'demo': [
|
||||
'crm_demo.xml',
|
||||
|
@ -113,12 +114,6 @@ Dashboard for CRM will include:
|
|||
'test/crm_lead_unlink.yml',
|
||||
'test/crm_lead_find_stage.yml',
|
||||
],
|
||||
'css': [
|
||||
'static/src/css/crm.css'
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/crm_case_section.js',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -978,7 +978,7 @@ class crm_lead(format_address, osv.osv):
|
|||
if obj.type == 'opportunity':
|
||||
model, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
else:
|
||||
view_id = super(crm_lead, self).get_formview_id(cr, uid, id, model=model, context=context)
|
||||
view_id = super(crm_lead, self).get_formview_id(cr, uid, id, model='crm.lead', context=context)
|
||||
return view_id
|
||||
|
||||
def message_get_suggested_recipients(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -327,7 +327,7 @@
|
|||
<field name="categ_ids" string="Tag" filter_domain="[('categ_ids', 'ilike', self)]"/>
|
||||
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
|
||||
<field name="user_id"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="create_date"/>
|
||||
<field name="country_id" context="{'invisible_country': False}"/>
|
||||
<separator/>
|
||||
|
@ -547,7 +547,7 @@
|
|||
<field name="categ_ids" string="Tag" filter_domain="[('categ_ids', 'ilike', self)]"/>
|
||||
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
|
||||
<field name="user_id"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="stage_id" domain="[]"/>
|
||||
<field name="probability"/>
|
||||
<separator/>
|
||||
|
|
|
@ -176,7 +176,7 @@
|
|||
<separator/>
|
||||
<filter string="Phone Calls Assigned to Me or My Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('user_id', '=', uid)]"
|
||||
help="Phone Calls Assigned to the current user or with a team having the current user as team leader"/>
|
||||
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="user_id"/>
|
||||
<field name="opportunity_id"/>
|
||||
<field name="section_id" string="Sales Team"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<graph string="Leads Analysis" type="pivot" stacked="True">
|
||||
<field name="user_id" type="row"/>
|
||||
<field name="create_date" interval="week" type="col"/>
|
||||
<field name="create_date" interval="year" type="col"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<graph string="Leads Analysis" type="pivot" stacked="True">
|
||||
<field name="date_deadline" type="row"/>
|
||||
<field name="user_id" type="col"/>
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="planned_revenue" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
|
@ -45,6 +45,9 @@
|
|||
<field name="model">crm.lead.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Leads Analysis">
|
||||
<filter name="lead" string="Lead" domain="[('type','=', 'lead')]" help="Show only lead"/>
|
||||
<filter name="opportunity" string="Opportunity" domain="[('type','=','opportunity')]" help="Show only opportunity"/>
|
||||
<separator/>
|
||||
<filter string="New" name="new"
|
||||
domain="[('probability', '=', 0), ('stage_id.sequence', '=', 1)]"/>
|
||||
<filter string="Won" name="won"
|
||||
|
@ -77,43 +80,37 @@
|
|||
<field name="date_closed"/>
|
||||
</group>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Salesperson" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}" />
|
||||
<filter string="Sales Team" icon="terp-personal+" domain="[]" context="{'group_by':'section_id'}" />
|
||||
<filter string="Partner" icon="terp-partner" context="{'group_by':'partner_id'}" />
|
||||
<filter string="Country" icon="terp-go-home" context="{'group_by':'country_id'}" />
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Stage" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Priority" icon="terp-rating-rated" domain="[]" context="{'group_by':'priority'}" />
|
||||
<filter string="Campaign" icon="terp-gtk-jump-to-rtl"
|
||||
domain="[]" context="{'group_by':'type_id'}" />
|
||||
<filter string="Channel" icon="terp-call-start"
|
||||
domain="[]" context="{'group_by':'channel_id'}" />
|
||||
<filter string="Salesperson" domain="[]" context="{'group_by':'user_id'}" />
|
||||
<filter string="Sales Team" domain="[]" context="{'group_by':'section_id'}" />
|
||||
<filter string="Partner" context="{'group_by':'partner_id'}" />
|
||||
<filter string="Country" context="{'group_by':'country_id'}" />
|
||||
<filter string="Company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Type" domain="[]" context="{'group_by':'type'}"/>
|
||||
<filter string="Stage" domain="[]" context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Priority" domain="[]" context="{'group_by':'priority'}" />
|
||||
<filter string="Campaign" domain="[]" context="{'group_by':'type_id'}" />
|
||||
<filter string="Channel" domain="[]" context="{'group_by':'channel_id'}" />
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Creation date (day)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:day'}"/>
|
||||
<filter string="Creation date (week)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:week'}"/>
|
||||
<filter string="Creation date (month)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:month'}" name="month"/>
|
||||
<filter string="Creation date (year)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:year'}"/>
|
||||
<filter string="Creation date (day)" domain="[]" context="{'group_by':'create_date:day'}"/>
|
||||
<filter string="Creation date (week)" domain="[]" context="{'group_by':'create_date:week'}"/>
|
||||
<filter string="Creation date (month)" domain="[]" context="{'group_by':'create_date:month'}" name="month"/>
|
||||
<filter string="Creation date (year)" domain="[]" context="{'group_by':'create_date:year'}"/>
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Exp. Closing" icon="terp-go-month"
|
||||
domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
<filter string="Exp. Closing" domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
<filter string="Last Stage Update" context="{'group_by':'date_last_stage_update'}" />
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Leads by user and section Action -->
|
||||
|
||||
<!-- Leads by user and section Action -->
|
||||
<record id="action_report_crm_lead" model="ir.actions.act_window">
|
||||
<field name="name">Leads Analysis</field>
|
||||
<field name="res_model">crm.lead.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="domain">[('type','=', 'lead')]</field>
|
||||
<field name="context">{'search_default_lead': 1}</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="help">Leads Analysis allows you to check different CRM related information like the treatment delays or number of leads per state. You can sort out your leads analysis by different groups to get accurate grained analysis.</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_report_crm_lead_graph">
|
||||
|
@ -122,27 +119,25 @@
|
|||
<field name="view_id" ref="view_report_crm_lead_graph"/>
|
||||
<field name="act_window_id" ref="action_report_crm_lead"/>
|
||||
</record>
|
||||
<menuitem name="Leads Analysis" id="menu_report_crm_leads_tree"
|
||||
groups="base.group_sale_manager"
|
||||
parent="base.next_id_64" action="action_report_crm_lead" sequence="1"/>
|
||||
|
||||
<record id="action_report_crm_opportunity" model="ir.actions.act_window">
|
||||
<field name="name">Opportunities Analysis</field>
|
||||
<field name="res_model">crm.lead.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="domain">[('type','=', 'opportunity')]</field>
|
||||
<field name="context">{'search_default_opportunity': 1}</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="help">Opportunities Analysis gives you an instant access to your opportunities with information such as the expected revenue, planned cost, missed deadlines or the number of interactions per opportunity. This report is mainly used by the sales manager in order to do the periodic review with the teams of the sales pipeline.</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_report_crm_opportunity_graph">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="view_report_crm_opportunity_graph"/>
|
||||
<field name="act_window_id" ref="action_report_crm_opportunity"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Leads Analysis" id="menu_report_crm_leads_tree"
|
||||
groups="base.group_sale_manager"
|
||||
parent="base.next_id_64" action="action_report_crm_lead" sequence="1"/>
|
||||
|
||||
<menuitem name="Opportunities Analysis" id="menu_report_crm_opportunities_tree"
|
||||
parent="base.next_id_64" action="action_report_crm_opportunity" sequence="5"/>
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="crm assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/crm/static/src/css/crm.css"/>
|
||||
<script type="text/javascript" src="/crm/static/src/js/crm_case_section.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -52,7 +52,7 @@
|
|||
</group>
|
||||
<group string="Categorization">
|
||||
<field name="priority"/>
|
||||
<field name="categ_id" domain="[('object_id.model', '=', 'crm.helpdesk')]"/>
|
||||
<field name="categ_id" domain="[('object_id.model', '=', 'crm.helpdesk')]" context="{'object_name': 'crm.helpdesk'}"/>
|
||||
<field name="channel_id"/>
|
||||
</group>
|
||||
</group>
|
||||
|
|
|
@ -51,9 +51,6 @@ to an appropriate local partner, based on the distance and the weight that was a
|
|||
'res_partner_demo.xml',
|
||||
'crm_lead_demo.xml'
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/next.js',
|
||||
],
|
||||
'test': ['test/partner_assign.yml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -194,9 +194,9 @@ class delivery_grid(osv.osv):
|
|||
for line in order.order_line:
|
||||
if not line.product_id or line.is_delivery:
|
||||
continue
|
||||
total += line.price_subtotal or 0.0
|
||||
weight += (line.product_id.weight or 0.0) * line.product_uom_qty
|
||||
volume += (line.product_id.volume or 0.0) * line.product_uom_qty
|
||||
total = order.amount_total or 0.0
|
||||
|
||||
|
||||
return self.get_price_from_picking(cr, uid, id, total,weight, volume, context=context)
|
||||
|
|
|
@ -45,10 +45,10 @@ This is a complete document management system.
|
|||
'wizard/document_configuration_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'report/document_report_view.xml',
|
||||
'views/document.xml',
|
||||
],
|
||||
'demo': [ 'document_demo.xml' ],
|
||||
'test': ['test/document_test2.yml'],
|
||||
'js': ['static/src/js/document.js'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/1_directories.jpeg','images/2_storage_media.jpeg','images/3_directories_structure.jpeg'],
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="document assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/document/static/src/js/document.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -35,10 +35,11 @@ documentation at http://doc.openerp.com.
|
|||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['base', 'email_template'],
|
||||
'data' : [
|
||||
'views/edi.xml',
|
||||
],
|
||||
'icon': '/edi/static/src/img/knowledge.png',
|
||||
'test': ['test/edi_partner_test.yml'],
|
||||
'js': ['static/src/js/edi.js'],
|
||||
'css': ['static/src/css/edi.css'],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'auto_install': False,
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ class EDI(openerp.http.Controller):
|
|||
modules = webmain.module_boot(req) + ['edi']
|
||||
modules_str = ','.join(modules)
|
||||
modules_json = simplejson.dumps(modules)
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in webmain.manifest_list(req, modules_str, 'js'))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in webmain.manifest_list(req, modules_str, 'css'))
|
||||
css = '<link rel="stylesheet" href="/web/css/web.assets_backend"/>'
|
||||
js = '<script type="text/javascript" src="/web/js/web.assets_backend"></script>'
|
||||
|
||||
# `url` may contain a full URL with a valid query string, we basically want to watch out for XML brackets and double-quotes
|
||||
safe_url = werkzeug.url_quote_plus(url,':/?&;=')
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="edi assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/edi/static/src/js/edi.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -431,7 +431,7 @@ class email_template(osv.osv):
|
|||
is taken from template definition)
|
||||
:returns: a dict containing all relevant fields for creating a new
|
||||
mail.mail entry, with one extra key ``attachments``, in the
|
||||
format expected by :py:meth:`mail_thread.message_post`.
|
||||
format [(report_name, data)] where data is base64 encoded.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -492,7 +492,8 @@ class email_template(osv.osv):
|
|||
result, format = self.pool['report'].get_pdf(cr, uid, [res_id], report_service, context=ctx), 'pdf'
|
||||
else:
|
||||
result, format = openerp.report.render_report(cr, uid, [res_id], report_service, {'model': template.model}, ctx)
|
||||
|
||||
|
||||
# TODO in trunk, change return format to binary to match message_post expected format
|
||||
result = base64.b64encode(result)
|
||||
if not report_name:
|
||||
report_name = 'report.' + report_service
|
||||
|
|
|
@ -62,7 +62,7 @@ class test_message_compose(TestMail):
|
|||
'name': 'Pigs Template',
|
||||
'subject': '${object.name}',
|
||||
'body_html': '${object.description}',
|
||||
'user_signature': True,
|
||||
'user_signature': False,
|
||||
'attachment_ids': [(0, 0, _attachments[0]), (0, 0, _attachments[1])],
|
||||
'email_to': 'b@b.b, c@c.c',
|
||||
'email_cc': 'd@d.d'
|
||||
|
@ -157,7 +157,7 @@ class test_message_compose(TestMail):
|
|||
message_pids = [partner.id for partner in compose.partner_ids]
|
||||
partner_ids = [p_a_id]
|
||||
self.assertEqual(compose.subject, '${object.name}', 'mail.compose.message subject incorrect')
|
||||
self.assertEqual(compose.body, '<p>${object.description}</p>', 'mail.compose.message body incorrect')
|
||||
self.assertEqual(compose.body, '<p>${object.description}</p>', 'mail.compose.message body incorrect') # todo: check signature
|
||||
self.assertEqual(set(message_pids), set(partner_ids), 'mail.compose.message partner_ids incorrect')
|
||||
|
||||
# 2. Post the comment, get created message
|
||||
|
|
|
@ -87,9 +87,16 @@ class mail_compose_message(osv.TransientModel):
|
|||
""" - mass_mailing: we cannot render, so return the template values
|
||||
- normal mode: return rendered values """
|
||||
if template_id and composition_mode == 'mass_mail':
|
||||
fields = ['subject', 'body_html', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id']
|
||||
template_values = self.pool.get('email.template').read(cr, uid, template_id, fields, context)
|
||||
values = dict((field, template_values[field]) for field in fields if template_values.get(field))
|
||||
fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id']
|
||||
template = self.pool['email.template'].browse(cr, uid, template_id, context=context)
|
||||
values = dict((field, getattr(template, field)) for field in fields if getattr(template, field))
|
||||
if template.attachment_ids:
|
||||
values['attachment_ids'] = [att.id for att in template.attachment_ids]
|
||||
if template.mail_server_id:
|
||||
values['mail_server_id'] = template.mail_server_id.id
|
||||
if template.user_signature and 'body_html' in values:
|
||||
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
|
||||
values['body_html'] = tools.append_content_to_html(values['body_html'], signature)
|
||||
elif template_id:
|
||||
values = self.generate_email_for_composer_batch(cr, uid, template_id, [res_id], context=context)[res_id]
|
||||
# transform attachments into attachment_ids; not attached to the document because this will
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
|
@ -49,6 +48,7 @@ Key Features
|
|||
'report/report_event_registration_view.xml',
|
||||
'res_partner_view.xml',
|
||||
'email_template.xml',
|
||||
'views/event.xml',
|
||||
],
|
||||
'demo': [
|
||||
'event_demo.xml',
|
||||
|
@ -57,7 +57,6 @@ Key Features
|
|||
'test/ui/event_users.yml',
|
||||
'test/process/event_draft2done.yml'
|
||||
],
|
||||
'css': ['static/src/css/event.css'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/1_event_type_list.jpeg','images/2_events.jpeg','images/3_registrations.jpeg','images/events_kanban.jpeg'],
|
||||
|
|
|
@ -131,7 +131,7 @@ class event_event(osv.osv):
|
|||
@return: Dictionary of function field values.
|
||||
"""
|
||||
event_ids=set()
|
||||
for registration in self.browse(cr, uid, ids, context=context):
|
||||
for registration in self.pool['event.registration'].browse(cr, uid, ids, context=context):
|
||||
event_ids.add(registration.event_id.id)
|
||||
return list(event_ids)
|
||||
|
||||
|
@ -317,6 +317,7 @@ class event_registration(osv.osv):
|
|||
def confirm_registration(self, cr, uid, ids, context=None):
|
||||
for reg in self.browse(cr, uid, ids, context=context or {}):
|
||||
self.pool.get('event.event').message_post(cr, uid, [reg.event_id.id], body=_('New registration confirmed: %s.') % (reg.name or '', ),subtype="event.mt_event_registration", context=context)
|
||||
self.message_post(cr, uid, reg.id, body=_('Event Registration confirmed.'), context=context)
|
||||
return self.write(cr, uid, ids, {'state': 'open'}, context=context)
|
||||
|
||||
def registration_open(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -105,9 +105,9 @@
|
|||
<field name="phone"/>
|
||||
<field name="nb_register" />
|
||||
<field name="state"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object" icon="gtk-jump-to"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
<form string="Registration">
|
||||
<field name="partner_id" attrs="{'readonly':[('state','!=', 'draft')]}" on_change="onchange_partner_id(partner_id, context)" />
|
||||
|
@ -125,9 +125,9 @@
|
|||
<separator string="" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="state" colspan="2"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object" icon="gtk-jump-to"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -333,9 +333,9 @@
|
|||
<field name="origin"/>
|
||||
<field name="state"/>
|
||||
<field name="message_unread" invisible="1"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object"/>
|
||||
<button name="registration_open" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
<button name="button_reg_close" string="Attended the Event" states="open" type="object" icon="gtk-jump-to"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -367,7 +367,7 @@
|
|||
<field name="email" class="oe_inline"/>
|
||||
<button class="oe_inline oe_right" string="Send Email"
|
||||
name="%(mail.action_email_compose_message_wizard)d"
|
||||
context= '{"default_email_to":email}' type="action"/>
|
||||
icon="terp-mail-message-new" context= '{"default_email_to":email}' type="action"/>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
|
@ -434,6 +434,8 @@
|
|||
<filter string="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Event" name="group_event" domain="[]" context="{'group_by':'event_id'}"/>
|
||||
<filter string="Status" domain="[]" context="{'group_by':'state'}"/>
|
||||
<filter string="Registration Day" domain="[]" context="{'group_by': 'create_date:day'}"/>
|
||||
<filter string="Registration Month" domain="[]" context="{'group_by': 'create_date:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="event assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/event/static/src/css/event.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -19,6 +19,7 @@
|
|||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.addons.event.event import event_event as Event
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
@ -137,6 +138,17 @@ class event_event(osv.osv):
|
|||
pass
|
||||
return []
|
||||
|
||||
def _get_ticket_events(self, cr, uid, ids, context=None):
|
||||
# `self` is the event.event.ticket model when called by ORM!
|
||||
return list(set(ticket.event_id.id
|
||||
for ticket in self.browse(cr, uid, ids, context)))
|
||||
|
||||
# proxy method, can't import parent method directly as unbound_method: it would receive
|
||||
# an invalid `self` <event_registration> when called by ORM
|
||||
def _events_from_registrations(self, cr, uid, ids, context=None):
|
||||
# `self` is the event.registration model when called by ORM
|
||||
return self.pool['event.event']._get_events_from_registrations(cr, uid, ids, context=context)
|
||||
|
||||
_columns = {
|
||||
'event_ticket_ids': fields.one2many('event.event.ticket', "event_id", "Event Ticket"),
|
||||
'seats_max': fields.function(_get_seats_max,
|
||||
|
@ -144,7 +156,15 @@ class event_event(osv.osv):
|
|||
help="The maximum registration level is equal to the sum of the maximum registration of event ticket." +
|
||||
"If you have too much registrations you are not able to confirm your event. (0 to ignore this rule )",
|
||||
type='integer',
|
||||
readonly=True)
|
||||
readonly=True),
|
||||
'seats_available': fields.function(Event._get_seats, oldname='register_avail', string='Available Seats',
|
||||
type='integer', multi='seats_reserved',
|
||||
store={
|
||||
'event.registration': (_events_from_registrations, ['state'], 10),
|
||||
'event.event': (lambda self, cr, uid, ids, c = {}: ids,
|
||||
['seats_max', 'registration_ids'], 20),
|
||||
'event.event.ticket': (_get_ticket_events, ['seats_max'], 10),
|
||||
}),
|
||||
}
|
||||
_defaults = {
|
||||
'event_ticket_ids': _get_tickets
|
||||
|
@ -167,12 +187,23 @@ class event_ticket(osv.osv):
|
|||
if ticket.seats_max > 0 else None
|
||||
return res
|
||||
|
||||
def _is_expired(self, cr, uid, ids, field_name, args, context=None):
|
||||
# FIXME: A ticket is considered expired when the deadline is passed. The deadline should
|
||||
# be considered in the timezone of the event, not the timezone of the user!
|
||||
# Until we add a TZ on the event we'll use the context's current date, more accurate
|
||||
# than using UTC all the time.
|
||||
current_date = fields.date.context_today(self, cr, uid, context=context)
|
||||
return {ticket.id: ticket.deadline and ticket.deadline < current_date
|
||||
for ticket in self.browse(cr, uid, ids, context=context)}
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=64, required=True, translate=True),
|
||||
'event_id': fields.many2one('event.event', "Event", required=True, ondelete='cascade'),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, domain=[("event_type_id", "!=", False)]),
|
||||
'registration_ids': fields.one2many('event.registration', 'event_ticket_id', 'Registrations'),
|
||||
'deadline': fields.date("Sales End"),
|
||||
'is_expired': fields.function(_is_expired, type='boolean', string='Is Expired'),
|
||||
'price': fields.float('Price'),
|
||||
'seats_max': fields.integer('Maximum Avalaible Seats', oldname='register_max', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )"),
|
||||
'seats_reserved': fields.function(_get_seats, string='Reserved Seats', type='integer', multi='seats_reserved'),
|
||||
|
|
|
@ -39,6 +39,17 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_registration_ticket_form">
|
||||
<field name="name">event.registration.ticket.form</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="inherit_id" ref="event.view_event_registration_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="user_id" position="after">
|
||||
<field name="event_ticket_id" domain="[('event_id', '=', event_id)]"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="event_sale_product_template_form">
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
|
|
|
@ -48,12 +48,11 @@ Both goals and badges are flexibles and can be adapted to a large range of modul
|
|||
'security/ir.model.access.csv',
|
||||
'data/goal_base.xml',
|
||||
'data/badge.xml',
|
||||
'views/gamification.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
|
||||
'css': ['static/src/css/gamification.css'],
|
||||
'js': ['static/src/js/gamification.js',],
|
||||
'qweb': ['static/src/xml/gamification.xml'],
|
||||
}
|
||||
|
|
|
@ -41,10 +41,6 @@
|
|||
<field name="description">Badge Granted</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="email_template_badge_received" model="email.template">
|
||||
<field name="name">Received Badge</field>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data noupdate="1">
|
||||
<record forcecreate="True" id="ir_cron_check_challenge"
|
||||
model="ir.cron">
|
||||
<field name="name">Run Goal Challenge Checker</field>
|
||||
|
|
|
@ -90,10 +90,6 @@
|
|||
]]></field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
<data>
|
||||
|
||||
<!-- goal definitions -->
|
||||
<record model="gamification.goal.definition" id="definition_base_timezone">
|
||||
<field name="name">Set your Timezone</field>
|
||||
|
|
|
@ -200,7 +200,6 @@ class gamification_challenge(osv.Model):
|
|||
'visibility_mode': 'personal',
|
||||
'report_message_frequency': 'never',
|
||||
'last_report_date': fields.date.today,
|
||||
'start_date': fields.date.today,
|
||||
'manager_id': lambda s, cr, uid, c: uid,
|
||||
'category': 'hr',
|
||||
'reward_failure': False,
|
||||
|
@ -269,13 +268,15 @@ class gamification_challenge(osv.Model):
|
|||
planned_challenge_ids = self.search(cr, uid, [
|
||||
('state', '=', 'draft'),
|
||||
('start_date', '<=', fields.date.today())])
|
||||
self.write(cr, uid, planned_challenge_ids, {'state': 'inprogress'}, context=context)
|
||||
if planned_challenge_ids:
|
||||
self.write(cr, uid, planned_challenge_ids, {'state': 'inprogress'}, context=context)
|
||||
|
||||
# close scheduled challenges
|
||||
planned_challenge_ids = self.search(cr, uid, [
|
||||
('state', '=', 'inprogress'),
|
||||
('end_date', '>=', fields.date.today())])
|
||||
self.write(cr, uid, planned_challenge_ids, {'state': 'done'}, context=context)
|
||||
if planned_challenge_ids:
|
||||
self.write(cr, uid, planned_challenge_ids, {'state': 'done'}, context=context)
|
||||
|
||||
if not ids:
|
||||
ids = self.search(cr, uid, [('state', '=', 'inprogress')], context=context)
|
||||
|
|
|
@ -39,5 +39,12 @@
|
|||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
|
||||
<record id="goal_global_multicompany" model="ir.rule">
|
||||
<field name="name">User can only see his/her goals or goal from the same challenge in board visibility</field>
|
||||
<field name="model_id" ref="model_gamification_goal"/>
|
||||
<field name="domain_force">[('user_id.company_id', 'child_of', [user.company_id.id])]</field>
|
||||
<field name="global" eval="True"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -118,7 +118,7 @@ openerp.gamification = function(instance) {
|
|||
}
|
||||
});
|
||||
|
||||
instance.mail.Widget.include({
|
||||
instance.mail.Wall.include({
|
||||
start: function() {
|
||||
this._super();
|
||||
var sidebar = new instance.gamification.Sidebar(this);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="gamification assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/gamification/static/src/css/gamification.css"/>
|
||||
<script type="text/javascript" src="/gamification/static/src/js/gamification.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- goal definitions -->
|
||||
<record model="gamification.goal.definition" id="definition_crm_tot_invoices">
|
||||
|
|
|
@ -4,18 +4,6 @@
|
|||
|
||||
<!-- challenges -->
|
||||
<record model="gamification.challenge" id="challenge_crm_sale">
|
||||
<field name="user_ids" eval="[(4,ref('base.user_demo'))]" />
|
||||
<field name="state">inprogress</field>
|
||||
</record>
|
||||
|
||||
<!-- goals -->
|
||||
<record model="gamification.goal" id="goal_crm_sale1">
|
||||
<field name="definition_id" eval="ref('definition_crm_tot_invoices')" />
|
||||
<field name="user_id" eval="ref('base.user_demo')" />
|
||||
<field name="line_id" eval="ref('line_crm_sale1')" />
|
||||
<field name="start_date" eval="time.strftime('%Y-%m-01')" />
|
||||
<field name="end_date" eval="(DateTime.today().replace(day=1)+relativedelta(months=1, days=-1)).strftime('%Y-%m-%d')" />
|
||||
<field name="target_goal">2000</field>
|
||||
<field name="state">inprogress</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -31,13 +31,12 @@ The module adds the possibility to synchronize Google Calendar with OpenERP
|
|||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['google_account','calendar'],
|
||||
'css': ['static/src/css/*.css'],
|
||||
'js': ['static/src/js/*.js'],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'data': [
|
||||
'res_config_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'res_config_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/google_calendar.xml',
|
||||
],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="google_calendar assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/google_calendar/static/src/css/google_calendar.css"/>
|
||||
<script type="text/javascript" src="/google_calendar/static/src/js/calendar_sync.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -27,13 +27,11 @@
|
|||
'category': 'Tools',
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'js': [
|
||||
'static/src/js/gdrive.js',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'res_config_user_view.xml',
|
||||
'google_drive_data.xml'
|
||||
'google_drive_data.xml',
|
||||
'views/google_drive.xml',
|
||||
],
|
||||
'demo': [
|
||||
'google_drive_demo.xml'
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="google_drive assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/google_drive/static/src/js/gdrive.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -31,11 +31,12 @@ The module adds the possibility to display data from OpenERP in Google Spreadshe
|
|||
'author': 'OpenERP SA',
|
||||
'website': 'http://www.openerp.com',
|
||||
'depends': ['board', 'google_drive'],
|
||||
'js': [
|
||||
'static/src/js/search.js',
|
||||
'data' : [
|
||||
'google_spreadsheet_view.xml',
|
||||
'google_spreadsheet_data.xml',
|
||||
'views/google_spreadsheet.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'data': ['google_spreadsheet_view.xml', 'google_spreadsheet_data.xml'],
|
||||
'demo': [],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="google_spreadsheet assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/google_spreadsheet/static/src/js/search.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -58,6 +58,7 @@ You can manage:
|
|||
'res_config_view.xml',
|
||||
'mail_hr_view.xml',
|
||||
'res_users_view.xml',
|
||||
'views/hr.xml',
|
||||
],
|
||||
'demo': ['hr_demo.xml'],
|
||||
'test': [
|
||||
|
@ -68,8 +69,6 @@ You can manage:
|
|||
'installable': True,
|
||||
'application': True,
|
||||
'auto_install': False,
|
||||
'css': [ 'static/src/css/hr.css' ],
|
||||
'js': [ 'static/src/js/suggestions.js' ],
|
||||
'qweb': [ 'static/src/xml/suggestions.xml' ],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -28,7 +28,7 @@ Get all your HR operations managed easily: knowledge sharing, recruitments, appr
|
|||
<h2 class="oe_slogan">Manage Your Employees</h2>
|
||||
<div class="oe_span6">
|
||||
<p class='oe_mt32'>
|
||||
Oversee all important information in your company address book. Some information are restricted to HR managers, others are public to easily find colleagues.
|
||||
Oversee all important information in your company address book. Some information are restricted to HR managers, others are public to easily look colleagues.
|
||||
</p><p>
|
||||
Record employee contracts and get alerts when they have to be renewed.
|
||||
</p>
|
||||
|
@ -154,7 +154,7 @@ Inspire achievement with challenges, goals and rewards. Define clear objectives
|
|||
</p>
|
||||
</div>
|
||||
<div class="oe_span4 oe_centered">
|
||||
<h3>Personnal Objectives</h3>
|
||||
<h3>Personal Objectives</h3>
|
||||
<div class="oe_row_img">
|
||||
<img class="oe_picture" src="crm_game_02.png">
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr/static/src/css/hr.css"/>
|
||||
<script type="text/javascript" src="/hr/static/src/js/suggestions.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -42,6 +42,7 @@ actions(Sign in/Sign out) performed by them.
|
|||
'wizard/hr_attendance_error_view.xml',
|
||||
'res_config_view.xml',
|
||||
'views/report_attendanceerrors.xml',
|
||||
'views/hr_attendance.xml',
|
||||
],
|
||||
'demo': ['hr_attendance_demo.xml'],
|
||||
'test': [
|
||||
|
@ -51,9 +52,7 @@ actions(Sign in/Sign out) performed by them.
|
|||
'installable': True,
|
||||
'auto_install': False,
|
||||
#web
|
||||
"js": ["static/src/js/attendance.js"],
|
||||
'qweb': ["static/src/xml/attendance.xml"],
|
||||
'css': ["static/src/css/slider.css"],
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr_attendance assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr_attendance/static/src/css/slider.css"/>
|
||||
<script type="text/javascript" src="/hr_attendance/static/src/js/attendance.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -10,19 +10,7 @@
|
|||
<record id="survey.menu_surveys" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
<record id="survey.menu_define_survey" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
<record id="survey.menu_survey_form" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
<record id="survey.menu_survey_page_form1" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
<record id="survey.menu_survey_type_form1" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
<record id="survey.menu_answer_surveys" model="ir.ui.menu">
|
||||
<record id="survey.menu_surveys_configuration" model="ir.ui.menu">
|
||||
<field eval="[(4,ref('base.group_hr_manager'))]" name="groups_id"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<td>
|
||||
<span t-field="line.name"/>
|
||||
<span t-field="line.description"/><br/>
|
||||
<span t-field="line.analytic_account.complete_name"/>
|
||||
<span t-field="line.analytic_account.complete_name" t-if="line.analytic_account"/>
|
||||
</td>
|
||||
<td style="text-center">
|
||||
<span t-field="line.ref"/>
|
||||
|
|
|
@ -35,7 +35,7 @@ Badge received are displayed on the user profile.
|
|||
'security/gamification_security.xml',
|
||||
'wizard/grant_badge.xml',
|
||||
'views/gamification.xml',
|
||||
'views/hr_gamification.xml',
|
||||
],
|
||||
'js': ['static/src/js/gamification.js'],
|
||||
'auto_install': True,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr_gamification assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/hr_gamification/static/src/js/gamification.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -59,7 +59,6 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p
|
|||
'wizard/hr_holidays_summary_employees_view.xml',
|
||||
],
|
||||
'demo': ['hr_holidays_demo.xml',],
|
||||
'js': ['static/src/js/*.js'],
|
||||
'qweb': [
|
||||
'static/src/xml/*.xml',
|
||||
],
|
||||
|
|
|
@ -58,13 +58,10 @@ You can define the different phases of interviews and easily rate the applicant
|
|||
'res_config_view.xml',
|
||||
'survey_data_recruitment.xml',
|
||||
'hr_recruitment_data.xml',
|
||||
'views/hr_recruitment.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,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr_recruitment assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr_recruitment/static/src/css/job_position.css"/>
|
||||
<script type="text/javascript" src="/hr_recruitment/static/src/js/job_position.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -57,14 +57,13 @@ The validation can be configured in the company:
|
|||
'wizard/hr_timesheet_current_view.xml',
|
||||
'hr_timesheet_sheet_data.xml',
|
||||
'res_config_view.xml',
|
||||
'views/hr_timesheet_sheet.xml',
|
||||
],
|
||||
'demo': ['hr_timesheet_sheet_demo.xml'],
|
||||
'test':['test/test_hr_timesheet_sheet.yml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': True,
|
||||
'js': ['static/src/js/timesheet.js',],
|
||||
'css': ['static/src/css/timesheet.css',],
|
||||
'qweb': ['static/src/xml/timesheet.xml',],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
##############################################################################
|
||||
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.translate import _
|
||||
|
||||
class hr_timesheet_sheet(osv.osv):
|
||||
|
@ -62,28 +63,56 @@ class hr_timesheet_sheet(osv.osv):
|
|||
def copy(self, cr, uid, ids, *args, **argv):
|
||||
raise osv.except_osv(_('Error!'), _('You cannot duplicate a timesheet.'))
|
||||
|
||||
def create(self, cr, uid, vals, *args, **argv):
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if 'employee_id' in vals:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).user_id:
|
||||
raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link him/her to a user.'))
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).product_id:
|
||||
raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product, like \'Consultant\'.'))
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id:
|
||||
raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.'))
|
||||
return super(hr_timesheet_sheet, self).create(cr, uid, vals, *args, **argv)
|
||||
if vals.get('attendances_ids'):
|
||||
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
|
||||
vals['attendances_ids'] = self.sort_attendances(cr, uid, vals['attendances_ids'], context=context)
|
||||
return super(hr_timesheet_sheet, self).create(cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, *args, **argv):
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if 'employee_id' in vals:
|
||||
new_user_id = self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id.id or False
|
||||
new_user_id = self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).user_id.id or False
|
||||
if not new_user_id:
|
||||
raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link him/her to a user.'))
|
||||
if not self._sheet_date(cr, uid, ids, forced_user_id=new_user_id):
|
||||
if not self._sheet_date(cr, uid, ids, forced_user_id=new_user_id, context=context):
|
||||
raise osv.except_osv(_('Error!'), _('You cannot have 2 timesheets that overlap!\nYou should use the menu \'My Timesheet\' to avoid this problem.'))
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).product_id:
|
||||
raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product.'))
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id:
|
||||
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id:
|
||||
raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.'))
|
||||
return super(hr_timesheet_sheet, self).write(cr, uid, ids, vals, *args, **argv)
|
||||
if vals.get('attendances_ids'):
|
||||
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
|
||||
# In addition to the date order, deleting attendances are done before inserting attendances
|
||||
vals['attendances_ids'] = self.sort_attendances(cr, uid, vals['attendances_ids'], context=context)
|
||||
res = super(hr_timesheet_sheet, self).write(cr, uid, ids, vals, context=context)
|
||||
if vals.get('attendances_ids'):
|
||||
for timesheet in self.browse(cr, uid, ids):
|
||||
if not self.pool['hr.attendance']._altern_si_so(cr, uid, [att.id for att in timesheet.attendances_ids]):
|
||||
raise osv.except_osv(_('Warning !'), _('Error ! Sign in (resp. Sign out) must follow Sign out (resp. Sign in)'))
|
||||
return res
|
||||
|
||||
def sort_attendances(self, cr, uid, attendance_tuples, context=None):
|
||||
date_attendances = []
|
||||
for att_tuple in attendance_tuples:
|
||||
if att_tuple[0] in [0,1,4]:
|
||||
if att_tuple[0] in [0,1]:
|
||||
name = att_tuple[2]['name']
|
||||
else:
|
||||
name = self.pool['hr.attendance'].browse(cr, uid, att_tuple[1]).name
|
||||
date_attendances.append((1, name, att_tuple))
|
||||
elif att_tuple[0] in [2,3]:
|
||||
date_attendances.append((0, self.pool['hr.attendance'].browse(cr, uid, att_tuple[1]).name, att_tuple))
|
||||
else:
|
||||
date_attendances.append((0, False, att_tuple))
|
||||
date_attendances.sort()
|
||||
return [att[2] for att in date_attendances]
|
||||
|
||||
def button_confirm(self, cr, uid, ids, context=None):
|
||||
for sheet in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -368,18 +397,22 @@ class hr_attendance(osv.osv):
|
|||
attendance_ids.extend([row[0] for row in cr.fetchall()])
|
||||
return attendance_ids
|
||||
|
||||
def _get_current_sheet(self, cr, uid, employee_id, date=False, context=None):
|
||||
if not date:
|
||||
date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
# ending date with no time to avoid timesheet with early date_to
|
||||
date_to = date[0:10]+' 00:00:00'
|
||||
# limit=1 because only one sheet possible for an employee between 2 dates
|
||||
sheet_ids = self.pool.get('hr_timesheet_sheet.sheet').search(cr, uid, [
|
||||
('date_to', '>=', date_to), ('date_from', '<=', date),
|
||||
('employee_id', '=', employee_id)
|
||||
], limit=1, context=context)
|
||||
return sheet_ids and sheet_ids[0] or False
|
||||
|
||||
def _sheet(self, cursor, user, ids, name, args, context=None):
|
||||
sheet_obj = self.pool.get('hr_timesheet_sheet.sheet')
|
||||
res = {}.fromkeys(ids, False)
|
||||
for attendance in self.browse(cursor, user, ids, context=context):
|
||||
date_to = datetime.strftime(datetime.strptime(attendance.name[0:10], '%Y-%m-%d'), '%Y-%m-%d %H:%M:%S')
|
||||
sheet_ids = sheet_obj.search(cursor, user,
|
||||
[('date_to', '>=', date_to), ('date_from', '<=', attendance.name),
|
||||
('employee_id', '=', attendance.employee_id.id)],
|
||||
context=context)
|
||||
if sheet_ids:
|
||||
# [0] because only one sheet possible for an employee between 2 dates
|
||||
res[attendance.id] = sheet_obj.name_get(cursor, user, sheet_ids, context=context)[0]
|
||||
res[attendance.id] = self._get_current_sheet(cursor, user, attendance.employee_id.id, attendance.name, context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
|
@ -398,16 +431,15 @@ class hr_attendance(osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if 'sheet_id' in context:
|
||||
ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, context['sheet_id'], context=context)
|
||||
|
||||
sheet_id = context.get('sheet_id') or self._get_current_sheet(cr, uid, vals.get('employee_id'), vals.get('name'), context=context)
|
||||
if sheet_id:
|
||||
ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, sheet_id, context=context)
|
||||
if ts.state not in ('draft', 'new'):
|
||||
raise osv.except_osv(_('Error!'), _('You cannot modify an entry in a confirmed timesheet.'))
|
||||
res = super(hr_attendance,self).create(cr, uid, vals, context=context)
|
||||
if 'sheet_id' in context:
|
||||
if context['sheet_id'] != self.browse(cr, uid, res, context=context).sheet_id.id:
|
||||
raise osv.except_osv(_('User Error!'), _('You cannot enter an attendance ' \
|
||||
'date outside the current timesheet dates.'))
|
||||
return res
|
||||
raise osv.except_osv(_('Error!'), _('You can not enter an attendance in a submitted timesheet. Ask your manager to reset it before adding attendance.'))
|
||||
elif ts.date_from > vals.get('name') or ts.date_to < vals.get('name'):
|
||||
raise osv.except_osv(_('User Error!'), _('You can not enter an attendance date outside the current timesheet dates.'))
|
||||
return super(hr_attendance,self).create(cr, uid, vals, context=context)
|
||||
|
||||
def unlink(self, cr, uid, ids, *args, **kwargs):
|
||||
if isinstance(ids, (int, long)):
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr_timesheet_sheet assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr_timesheet_sheet/static/src/css/timesheet.css"/>
|
||||
<script type="text/javascript" src="/hr_timesheet_sheet/static/src/js/timesheet.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -35,7 +35,6 @@ from PIL import Image
|
|||
|
||||
from openerp import http
|
||||
from openerp.http import request
|
||||
from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
|
||||
from openerp.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -16,7 +16,6 @@ _logger = logging.getLogger(__name__)
|
|||
|
||||
from openerp import http
|
||||
from openerp.http import request
|
||||
from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
|
||||
|
||||
|
||||
# drivers modules must add to drivers an object with a get_status() method
|
||||
|
|
|
@ -16,13 +16,9 @@ chat in real time. It support several chats in parallel.
|
|||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/im_security.xml',
|
||||
'views/im.xml',
|
||||
],
|
||||
'depends' : ['base', 'web'],
|
||||
'js': [
|
||||
'static/src/js/im_common.js',
|
||||
'static/src/js/im.js',
|
||||
],
|
||||
'css': ['static/src/css/*.css'],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="im assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/im/static/src/css/im.css"/>
|
||||
<link rel="stylesheet" href="/im/static/src/css/im_common.css"/>
|
||||
<script type="text/javascript" src="/im/static/src/js/im_common.js"></script>
|
||||
<script type="text/javascript" src="/im/static/src/js/im.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -40,10 +40,18 @@ In addition to a full meal and supplier management, this module offers the possi
|
|||
|
||||
If you want to save your employees' time and avoid them to always have coins in their pockets, this module is essential.
|
||||
""",
|
||||
'data': ['security/lunch_security.xml','lunch_view.xml','wizard/lunch_order_view.xml','wizard/lunch_validation_view.xml','wizard/lunch_cancel_view.xml','lunch_report.xml',
|
||||
'data': [
|
||||
'security/lunch_security.xml',
|
||||
'lunch_view.xml',
|
||||
'wizard/lunch_order_view.xml',
|
||||
'wizard/lunch_validation_view.xml',
|
||||
'wizard/lunch_cancel_view.xml',
|
||||
'lunch_report.xml',
|
||||
'report/report_lunch_order_view.xml',
|
||||
'security/ir.model.access.csv','views/report_lunchorder.xml'],
|
||||
'css':['static/src/css/lunch.css'],
|
||||
'security/ir.model.access.csv',
|
||||
'views/report_lunchorder.xml',
|
||||
'views/lunch.xml',
|
||||
],
|
||||
'images': ['images/new_order.jpeg','images/lunch_account.jpeg','images/order_by_supplier_analysis.jpeg','images/alert.jpeg'],
|
||||
'demo': ['lunch_demo.xml',],
|
||||
'installable': True,
|
||||
|
|
|
@ -17,38 +17,14 @@
|
|||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="lunch_mind_your_own_food" model="ir.rule">
|
||||
<field name="name">lunch.order: do not see and create other people's order</field>
|
||||
<field name="model_id" ref="model_lunch_order"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_user'))]"/>
|
||||
<field name="domain_force">[('user_id', '=', user.id)]</field>
|
||||
</record>
|
||||
<record id="lunch_mind_other_food" model="ir.rule">
|
||||
<field name="name">lunch.order: do not see and create other people's order</field>
|
||||
<field name="model_id" ref="model_lunch_order"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_manager'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
<record id="lunch_mind_your_own_food_line" model="ir.rule">
|
||||
<field name="name">lunch.order.line: do not see and create other people's order line</field>
|
||||
<field name="model_id" ref="model_lunch_order_line"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_user'))]"/>
|
||||
<field name="domain_force">[('user_id', '=', user.id)]</field>
|
||||
</record>
|
||||
<record id="lunch_mind_other_food_line" model="ir.rule">
|
||||
<field name="name">lunch.order.line: do not see and create other people's order line</field>
|
||||
<field name="model_id" ref="model_lunch_order_line"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_manager'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
<record id="lunch_mind_your_own_food_money" model="ir.rule">
|
||||
<field name="name">lunch.cashmove: do not see and create other people's cashmove</field>
|
||||
<field name="name">lunch.cashmove: do not see other people's cashmove</field>
|
||||
<field name="model_id" ref="model_lunch_cashmove"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_user'))]"/>
|
||||
<field name="domain_force">[('user_id', '=', user.id)]</field>
|
||||
</record>
|
||||
<record id="lunch_mind_other_food_money" model="ir.rule">
|
||||
<field name="name">lunch.cashmove: do not see and create other people's cashmove</field>
|
||||
<field name="name">lunch.cashmove: do see other people's cashmove</field>
|
||||
<field name="model_id" ref="model_lunch_cashmove"/>
|
||||
<field name="groups" eval="[(4, ref('group_lunch_manager'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- vim:fdn=3:
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="lunch assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/lunch/static/src/css/lunch.css"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
|
@ -63,6 +63,7 @@ Main Features
|
|||
'security/ir.model.access.csv',
|
||||
'mail_alias_view.xml',
|
||||
'res_users_view.xml',
|
||||
'views/mail.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/mail_demo.xml',
|
||||
|
@ -78,18 +79,6 @@ Main Features
|
|||
'images/join_a_group.jpeg',
|
||||
'images/share_a_message.jpeg',
|
||||
],
|
||||
'css': [
|
||||
'static/src/css/mail.css',
|
||||
'static/src/css/mail_group.css',
|
||||
'static/src/css/announcement.css',
|
||||
],
|
||||
'js': [
|
||||
'static/src/js/mail.js',
|
||||
'static/src/js/mail_followers.js',
|
||||
'static/src/js/many2many_tags_email.js',
|
||||
'static/src/js/announcement.js',
|
||||
'static/src/js/suggestions.js',
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/mail.xml',
|
||||
'static/src/xml/mail_followers.xml',
|
||||
|
|
|
@ -135,7 +135,7 @@ class mail_mail(osv.Model):
|
|||
:param browse_record mail: the mail that was just sent
|
||||
:return: True
|
||||
"""
|
||||
if mail.auto_delete:
|
||||
if mail_sent and mail.auto_delete:
|
||||
# done with SUPERUSER_ID to avoid giving large unlink access rights
|
||||
self.unlink(cr, SUPERUSER_ID, [mail.id], context=context)
|
||||
return True
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<field name="model">mail.mail</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Email Search">
|
||||
<field name="email_from" filter_domain="['|' '|',('email_from','ilike',self), ('email_to','ilike',self), ('subject','ilike',self)]" string="Email"/>
|
||||
<field name="email_from" filter_domain="['|', '|',('email_from','ilike',self), ('email_to','ilike',self), ('subject','ilike',self)]" string="Email"/>
|
||||
<field name="date"/>
|
||||
<filter icon="terp-camera_test" name="received" string="Received" domain="[('state','=','received')]"/>
|
||||
<filter icon="terp-call-start" name="outgoing" string="Outgoing" domain="[('state','=','outgoing')]"/>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue