[MRG] merge with lp:openobject-addons
bzr revid: tpa@tinyerp.com-20130617100451-vwtgtfp4r523xsp3
This commit is contained in:
commit
e2c343fc63
|
@ -648,10 +648,10 @@ class account_account(osv.osv):
|
|||
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
|
||||
#Check for 'Closed' type
|
||||
if old_type == 'closed' and new_type !='closed':
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!"))
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!"))
|
||||
# Forbid to change an account type for restricted_groups as it contains journal items (or if one of its children does)
|
||||
if (new_type in restricted_groups):
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,))
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,))
|
||||
|
||||
return True
|
||||
|
||||
|
@ -1015,14 +1015,14 @@ class account_period(osv.osv):
|
|||
if not result:
|
||||
result = self.search(cr, uid, args, context=context)
|
||||
if not result:
|
||||
raise osv.except_osv(_('Error !'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
|
||||
raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt)
|
||||
return result
|
||||
|
||||
def action_draft(self, cr, uid, ids, *args):
|
||||
mode = 'draft'
|
||||
for period in self.browse(cr, uid, ids):
|
||||
if period.fiscalyear_id.state == 'done':
|
||||
raise osv.except_osv(_('Warning !'), _('You can not re-open a period which belongs to closed fiscal year'))
|
||||
raise osv.except_osv(_('Warning!'), _('You can not re-open a period which belongs to closed fiscal year'))
|
||||
cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),))
|
||||
cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),))
|
||||
return True
|
||||
|
@ -2317,7 +2317,7 @@ class account_model(osv.osv):
|
|||
try:
|
||||
entry['name'] = model.name%{'year': move_date.strftime('%Y'), 'month': move_date.strftime('%m'), 'date': move_date.strftime('%Y-%m')}
|
||||
except:
|
||||
raise osv.except_osv(_('Wrong model !'), _('You have a wrong expression "%(...)s" in your model !'))
|
||||
raise osv.except_osv(_('Wrong Model!'), _('You have a wrong expression "%(...)s" in your model!'))
|
||||
move_id = account_move_obj.create(cr, uid, {
|
||||
'ref': entry['name'],
|
||||
'period_id': period_id,
|
||||
|
@ -2329,7 +2329,7 @@ class account_model(osv.osv):
|
|||
analytic_account_id = False
|
||||
if line.analytic_account_id:
|
||||
if not model.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (model.journal_id.name,))
|
||||
analytic_account_id = line.analytic_account_id.id
|
||||
val = {
|
||||
'move_id': move_id,
|
||||
|
|
|
@ -65,12 +65,11 @@ class bank(osv.osv):
|
|||
# Find the code and parent of the bank account to create
|
||||
dig = 6
|
||||
current_num = 1
|
||||
ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id)], context=context)
|
||||
ids = obj_acc.search(cr, uid, [('type','=','liquidity'), ('company_id', '=', bank.company_id.id), ('parent_id', '!=', False)], context=context)
|
||||
# No liquidity account exists, no template available
|
||||
if not ids: continue
|
||||
|
||||
ref_acc_bank_temp = obj_acc.browse(cr, uid, ids[0], context=context)
|
||||
ref_acc_bank = ref_acc_bank_temp.parent_id
|
||||
ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id
|
||||
while True:
|
||||
new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
|
||||
ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)])
|
||||
|
@ -82,7 +81,7 @@ class bank(osv.osv):
|
|||
'name': name,
|
||||
'code': new_code,
|
||||
'type': 'liquidity',
|
||||
'user_type': ref_acc_bank_temp.user_type.id,
|
||||
'user_type': ref_acc_bank.user_type.id,
|
||||
'reconcile': False,
|
||||
'parent_id': ref_acc_bank.id,
|
||||
'company_id': bank.company_id.id,
|
||||
|
|
|
@ -420,7 +420,7 @@ class account_bank_statement(osv.osv):
|
|||
for st_line in st.line_ids:
|
||||
if st_line.analytic_account_id:
|
||||
if not st.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,))
|
||||
if not st_line.amount:
|
||||
continue
|
||||
st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context)
|
||||
|
|
|
@ -252,7 +252,7 @@ class account_cash_statement(osv.osv):
|
|||
for statement in statement_pool.browse(cr, uid, ids, context=context):
|
||||
vals = {}
|
||||
if not self._user_allow(cr, uid, statement.id, context=context):
|
||||
raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal !') % (statement.journal_id.name, )))
|
||||
raise osv.except_osv(_('Error!'), (_('You do not have rights to open this %s journal!') % (statement.journal_id.name, )))
|
||||
|
||||
if statement.name and statement.name == '/':
|
||||
c = {'fiscalyear_id': statement.period_id.fiscalyear_id.id}
|
||||
|
|
|
@ -51,9 +51,12 @@ class account_invoice(osv.osv):
|
|||
company_id = context.get('company_id', user.company_id.id)
|
||||
type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale_refund', 'in_refund': 'purchase_refund'}
|
||||
journal_obj = self.pool.get('account.journal')
|
||||
res = journal_obj.search(cr, uid, [('type', '=', type2journal.get(type_inv, 'sale')),
|
||||
('company_id', '=', company_id)],
|
||||
limit=1)
|
||||
domain = [('company_id', '=', company_id)]
|
||||
if isinstance(type_inv, list):
|
||||
domain.append(('type', 'in', [type2journal.get(type) for type in type_inv if type2journal.get(type)]))
|
||||
else:
|
||||
domain.append(('type', '=', type2journal.get(type_inv, 'sale')))
|
||||
res = journal_obj.search(cr, uid, domain, limit=1)
|
||||
return res and res[0] or False
|
||||
|
||||
def _get_currency(self, cr, uid, context=None):
|
||||
|
@ -69,7 +72,7 @@ class account_invoice(osv.osv):
|
|||
tt = type2journal.get(type_inv, 'sale')
|
||||
result = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=',tt)], context=context)
|
||||
if not result:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You must define an analytic journal of type '%s'!") % (tt,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You must define an analytic journal of type '%s'!") % (tt,))
|
||||
return result[0]
|
||||
|
||||
def _get_type(self, cr, uid, context=None):
|
||||
|
@ -578,6 +581,10 @@ class account_invoice(osv.osv):
|
|||
return {'value': {}}
|
||||
|
||||
def onchange_company_id(self, cr, uid, ids, company_id, part_id, type, invoice_line, currency_id, context=None):
|
||||
#TODO: add the missing context parameter when forward-porting in trunk so we can remove
|
||||
# this hack!
|
||||
context = self.pool['res.users'].context_get(cr, uid)
|
||||
|
||||
val = {}
|
||||
dom = {}
|
||||
obj_journal = self.pool.get('account.journal')
|
||||
|
@ -630,18 +637,17 @@ class account_invoice(osv.osv):
|
|||
obj_l = account_obj.browse(cr, uid, inv_line[2]['account_id'])
|
||||
if obj_l.company_id.id != company_id:
|
||||
raise osv.except_osv(_('Configuration Error!'),
|
||||
_('Invoice line account\'s company and invoice\'s compnay does not match.'))
|
||||
_('Invoice line account\'s company and invoice\'s company does not match.'))
|
||||
else:
|
||||
continue
|
||||
if company_id and type:
|
||||
if type in ('out_invoice'):
|
||||
journal_type = 'sale'
|
||||
elif type in ('out_refund'):
|
||||
journal_type = 'sale_refund'
|
||||
elif type in ('in_refund'):
|
||||
journal_type = 'purchase_refund'
|
||||
else:
|
||||
journal_type = 'purchase'
|
||||
journal_mapping = {
|
||||
'out_invoice': 'sale',
|
||||
'out_refund': 'sale_refund',
|
||||
'in_refund': 'purchase_refund',
|
||||
'in_invoice': 'purchase',
|
||||
}
|
||||
journal_type = journal_mapping[type]
|
||||
journal_ids = obj_journal.search(cr, uid, [('company_id','=',company_id), ('type', '=', journal_type)])
|
||||
if journal_ids:
|
||||
val['journal_id'] = journal_ids[0]
|
||||
|
@ -651,7 +657,12 @@ class account_invoice(osv.osv):
|
|||
if r[1] == 'journal_id' and r[2] in journal_ids:
|
||||
val['journal_id'] = r[2]
|
||||
if not val.get('journal_id', False):
|
||||
raise osv.except_osv(_('Configuration Error!'), (_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % (journal_type)))
|
||||
journal_type_map = dict(obj_journal._columns['type'].selection)
|
||||
journal_type_label = self.pool['ir.translation']._get_source(cr, uid, None, ('code','selection'),
|
||||
context.get('lang'),
|
||||
journal_type_map.get(journal_type))
|
||||
raise osv.except_osv(_('Configuration Error!'),
|
||||
_('Cannot find any account journal of %s type for this company.\n\nYou can create one in the menu: \nConfiguration\Journals\Journals.') % ('"%s"' % journal_type_label))
|
||||
dom = {'journal_id': [('id', 'in', journal_ids)]}
|
||||
else:
|
||||
journal_ids = obj_journal.search(cr, uid, [])
|
||||
|
@ -786,7 +797,7 @@ class account_invoice(osv.osv):
|
|||
else:
|
||||
ref = self._convert_ref(cr, uid, inv.number)
|
||||
if not inv.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
|
||||
il['analytic_lines'] = [(0,0, {
|
||||
'name': il['name'],
|
||||
'date': inv['date_invoice'],
|
||||
|
@ -912,7 +923,7 @@ class account_invoice(osv.osv):
|
|||
if not inv.journal_id.sequence_id:
|
||||
raise osv.except_osv(_('Error!'), _('Please define sequence on the journal related to this invoice.'))
|
||||
if not inv.invoice_line:
|
||||
raise osv.except_osv(_('No Invoice Lines !'), _('Please create some invoice lines.'))
|
||||
raise osv.except_osv(_('No Invoice Lines!'), _('Please create some invoice lines.'))
|
||||
if inv.move_id:
|
||||
continue
|
||||
|
||||
|
@ -933,7 +944,7 @@ class account_invoice(osv.osv):
|
|||
group_check_total = self.pool.get('res.groups').browse(cr, uid, group_check_total_id, context=context)
|
||||
if group_check_total and uid in [x.id for x in group_check_total.users]:
|
||||
if (inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0)):
|
||||
raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe encoded total does not match the computed total.'))
|
||||
raise osv.except_osv(_('Bad Total!'), _('Please verify the price of the invoice!\nThe encoded total does not match the computed total.'))
|
||||
|
||||
if inv.payment_term:
|
||||
total_fixed = total_percent = 0
|
||||
|
@ -968,7 +979,7 @@ class account_invoice(osv.osv):
|
|||
total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml, context=ctx)
|
||||
acc_id = inv.account_id.id
|
||||
|
||||
name = inv['name'] or '/'
|
||||
name = inv['name'] or inv['supplier_invoice_number'] or '/'
|
||||
totlines = False
|
||||
if inv.payment_term:
|
||||
totlines = payment_term_obj.compute(cr,
|
||||
|
@ -1167,12 +1178,12 @@ class account_invoice(osv.osv):
|
|||
if not ids:
|
||||
return []
|
||||
types = {
|
||||
'out_invoice': 'Invoice ',
|
||||
'in_invoice': 'Sup. Invoice ',
|
||||
'out_refund': 'Refund ',
|
||||
'in_refund': 'Supplier Refund ',
|
||||
'out_invoice': _('Invoice'),
|
||||
'in_invoice': _('Supplier Invoice'),
|
||||
'out_refund': _('Refund'),
|
||||
'in_refund': _('Supplier Refund'),
|
||||
}
|
||||
return [(r['id'], (r['number']) or types[r['type']] + (r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
|
||||
return [(r['id'], '%s %s' % (r['number'] or types[r['type']], r['name'] or '')) for r in self.read(cr, uid, ids, ['type', 'number', 'name'], context, load='_classic_write')]
|
||||
|
||||
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
|
||||
if not args:
|
||||
|
@ -1475,7 +1486,7 @@ class account_invoice_line(osv.osv):
|
|||
context = dict(context)
|
||||
context.update({'company_id': company_id, 'force_company': company_id})
|
||||
if not partner_id:
|
||||
raise osv.except_osv(_('No Partner Defined !'),_("You must first select a partner !") )
|
||||
raise osv.except_osv(_('No Partner Defined!'),_("You must first select a partner!") )
|
||||
if not product:
|
||||
if type in ('in_invoice', 'in_refund'):
|
||||
return {'value': {}, 'domain':{'product_uom':[]}}
|
||||
|
|
|
@ -192,7 +192,7 @@ class account_move_line(osv.osv):
|
|||
for obj_line in self.browse(cr, uid, ids, context=context):
|
||||
if obj_line.analytic_account_id:
|
||||
if not obj_line.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
|
||||
vals_line = self._prepare_analytic_line(cr, uid, obj_line, context=context)
|
||||
acc_ana_line_obj.create(cr, uid, vals_line)
|
||||
return True
|
||||
|
@ -1066,12 +1066,12 @@ class account_move_line(osv.osv):
|
|||
|
||||
for line in self.browse(cr, uid, ids, context=context):
|
||||
ctx = context.copy()
|
||||
if ('journal_id' not in ctx):
|
||||
if not ctx.get('journal_id'):
|
||||
if line.move_id:
|
||||
ctx['journal_id'] = line.move_id.journal_id.id
|
||||
else:
|
||||
ctx['journal_id'] = line.journal_id.id
|
||||
if ('period_id' not in ctx):
|
||||
if not ctx.get('period_id'):
|
||||
if line.move_id:
|
||||
ctx['period_id'] = line.move_id.period_id.id
|
||||
else:
|
||||
|
@ -1101,7 +1101,7 @@ class account_move_line(osv.osv):
|
|||
period = period_obj.browse(cr, uid, period_id, context=context)
|
||||
for (state,) in result:
|
||||
if state == 'done':
|
||||
raise osv.except_osv(_('Error !'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
|
||||
raise osv.except_osv(_('Error!'), _('You can not add/modify entries in a closed period %s of journal %s.' % (period.name,journal.name)))
|
||||
if not result:
|
||||
jour_period_obj.create(cr, uid, {
|
||||
'name': (journal.code or journal.name)+':'+(period.name or ''),
|
||||
|
@ -1181,7 +1181,7 @@ class account_move_line(osv.osv):
|
|||
move_id = move_obj.create(cr, uid, v, context)
|
||||
vals['move_id'] = move_id
|
||||
else:
|
||||
raise osv.except_osv(_('No piece number !'), _('Cannot create an automatic sequence for this piece.\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
|
||||
raise osv.except_osv(_('No Piece Number!'), _('Cannot create an automatic sequence for this piece.\nPut a sequence in the journal definition for automatic numbering or create a sequence manually for this piece.'))
|
||||
ok = not (journal.type_control_ids or journal.account_control_ids)
|
||||
if ('account_id' in vals):
|
||||
account = account_obj.browse(cr, uid, vals['account_id'], context=context)
|
||||
|
|
|
@ -585,7 +585,10 @@
|
|||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="ref"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="['|',('parent_id','=',False),('is_company','=',True)]"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[
|
||||
'&',
|
||||
'|',('parent_id','=',False),('is_company','=',True),
|
||||
'|',('customer','=',True),('supplier','=',True)]"/>
|
||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -111,7 +111,7 @@ class account_installer(osv.osv_memory):
|
|||
def check_unconfigured_cmp(self, cr, uid, context=None):
|
||||
""" check if there are still unconfigured companies """
|
||||
if not self.get_unconfigured_cmp(cr, uid, context=context):
|
||||
raise osv.except_osv(_('No unconfigured company !'), _("There is currently no company without chart of account. The wizard will therefore not be executed."))
|
||||
raise osv.except_osv(_('No Unconfigured Company!'), _("There is currently no company without chart of account. The wizard will therefore not be executed."))
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
if context is None: context = {}
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<field name="name">partner.view.buttons</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form" />
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button type="action" string="Invoices"
|
||||
|
@ -96,7 +96,7 @@
|
|||
<field name="priority">2</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<page string="History" position="before" version="7.0">
|
||||
<page name="sales_purchases" position="after" version="7.0">
|
||||
<page string="Accounting" col="4" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
|
||||
<group>
|
||||
<group>
|
||||
|
|
|
@ -363,7 +363,7 @@
|
|||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="analytic_journal_id"/>
|
||||
<field name="analytic_journal_id" groups="analytic.group_analytic_accounting"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -239,7 +239,7 @@
|
|||
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,15) ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ strip_name(line.name,25) ]]</para></td>
|
||||
<td><para style="P8">[[ line.tax_code_id and (line.tax_code_id.code + ':') ]]</para></td>
|
||||
<td><para style="P8">[[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
||||
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
||||
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
||||
|
@ -292,7 +292,7 @@
|
|||
<td><para style="terp_default_8">[[ line.account_id.code ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ line.partner_id and strip_name(line.partner_id.name,12) ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ strip_name(line.name,16) ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ line.tax_code_id and (line.tax_code_id.code + ':') ]]</para></td>
|
||||
<td><para style="terp_default_8">[[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]]</para></td>
|
||||
<td><para style="P8">[[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]]</para></td>
|
||||
<td><para style="P8">[[ formatLang(line.debit, currency_obj=company.currency_id) ]]</para></td>
|
||||
<td><para style="P8">[[ formatLang(line.credit, currency_obj=company.currency_id) ]]</para></td>
|
||||
|
|
|
@ -38,7 +38,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
|||
'report_name': fields.char('Name of new entries',size=64, required=True, help="Give name of the new entries"),
|
||||
}
|
||||
_defaults = {
|
||||
'report_name': _('End of Fiscal Year Entry'),
|
||||
'report_name': lambda self, cr, uid, context: _('End of Fiscal Year Entry'),
|
||||
}
|
||||
|
||||
def data_save(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -57,7 +57,7 @@ class validate_account_move_lines(osv.osv_memory):
|
|||
move_ids.append(line.move_id.id)
|
||||
move_ids = list(set(move_ids))
|
||||
if not move_ids:
|
||||
raise osv.except_osv(_('Warning!'), _('Selected Entry Lines does not have any account move enties in draft state.'))
|
||||
raise osv.except_osv(_('Warning!'), _('Selected Entry Lines does not have any account move entries in draft state.'))
|
||||
obj_move.button_validate(cr, uid, move_ids, context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
|
|
@ -653,7 +653,7 @@ class account_analytic_account(osv.osv):
|
|||
fpos_obj = self.pool.get('account.fiscal.position')
|
||||
|
||||
if not contract.partner_id:
|
||||
raise osv.except_osv(_('No Customer Defined !'),_("You must first select a Customer for Contract %s!") % contract.name )
|
||||
raise osv.except_osv(_('No Customer Defined!'),_("You must first select a Customer for Contract %s!") % contract.name )
|
||||
|
||||
fpos = contract.partner_id.property_account_position.id or False
|
||||
journal_ids = journal_obj.search(cr, uid, [('type', '=','sale'),('company_id', '=', contract.company_id.id or False)], limit=1)
|
||||
|
|
|
@ -72,8 +72,8 @@ class account_invoice_line(osv.osv):
|
|||
_inherit = "account.invoice.line"
|
||||
_description = "Invoice Line"
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||
res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, context=context, company_id=company_id)
|
||||
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||
res_prod = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id=currency_id, context=context, company_id=company_id)
|
||||
rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), context=context)
|
||||
if rec:
|
||||
res_prod['value'].update({'account_analytic_id': rec.analytic_id.id})
|
||||
|
|
|
@ -332,7 +332,7 @@ class account_move_line(osv.osv):
|
|||
for line in self.browse(cr, uid, ids, context=context):
|
||||
if line.analytics_id:
|
||||
if not line.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal.") % (line.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal.") % (line.journal_id.name,))
|
||||
|
||||
toremove = analytic_line_obj.search(cr, uid, [('move_id','=',line.id)], context=context)
|
||||
if toremove:
|
||||
|
@ -471,7 +471,7 @@ class account_bank_statement(osv.osv):
|
|||
for st_line in st.line_ids:
|
||||
if st_line.analytics_id:
|
||||
if not st.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal.") % (st.journal_id.name,))
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal.") % (st.journal_id.name,))
|
||||
if not st_line.amount:
|
||||
continue
|
||||
return True
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="centralisation" position="before">
|
||||
<field name="plan_id" />
|
||||
<field name="plan_id" groups="analytic.group_analytic_accounting"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -136,9 +136,9 @@ class account_invoice_line(osv.osv):
|
|||
res += diff_res
|
||||
return res
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||
def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None):
|
||||
fiscal_pool = self.pool.get('account.fiscal.position')
|
||||
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context, company_id)
|
||||
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom_id, qty, name, type, partner_id, fposition_id, price_unit, currency_id, context, company_id)
|
||||
if not product:
|
||||
return res
|
||||
if type in ('in_invoice','in_refund'):
|
||||
|
|
|
@ -13,6 +13,17 @@
|
|||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_invoice_asset_category">
|
||||
<field name="name">account.invoice.supplier.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='invoice_line']/tree/field[@name='quantity']" position="before">
|
||||
<field name="asset_category_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -203,7 +203,9 @@
|
|||
<field name="view_id" ref="crossovered_budget_view_tree"/>
|
||||
<field name="search_view_id" ref="view_crossovered_budget_search"/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new budget.
|
||||
</p><p>
|
||||
A budget is a forecast of your company's income and/or expenses
|
||||
expected for a period in the future. A budget is defined on some
|
||||
financial accounts and/or analytic accounts (that may represent
|
||||
|
|
|
@ -3,5 +3,5 @@ access_account_followup_followup_line,account_followup.followup.line,model_accou
|
|||
access_account_followup_followup_line_manager,account_followup.followup.line.manager,model_account_followup_followup_line,account.group_account_manager,1,1,1,1
|
||||
access_account_followup_followup_accountant,account_followup.followup user,model_account_followup_followup,account.group_account_invoice,1,0,0,0
|
||||
access_account_followup_followup_manager,account_followup.followup.manager,model_account_followup_followup,account.group_account_manager,1,1,1,1
|
||||
access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,1,1
|
||||
access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,1,1
|
||||
access_account_followup_stat_invoice,account_followup.stat.invoice,model_account_followup_stat,account.group_account_invoice,1,1,0,0
|
||||
access_account_followup_stat_by_partner_manager,account_followup.stat.by.partner,model_account_followup_stat_by_partner,account.group_account_user,1,1,0,0
|
||||
|
|
|
|
@ -88,6 +88,7 @@ class payment_order_create(osv.osv_memory):
|
|||
'order_id': payment.id,
|
||||
'partner_id': line.partner_id and line.partner_id.id or False,
|
||||
'communication': line.ref or '/',
|
||||
'state': line.invoice and line.invoice.reference_type != 'none' and 'structured' or 'normal',
|
||||
'date': date_to_pay,
|
||||
'currency': (line.invoice and line.invoice.currency_id.id) or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id,
|
||||
}, context=context)
|
||||
|
|
|
@ -1622,7 +1622,7 @@ class account_bank_statement(osv.osv):
|
|||
for bk_st in self.browse(cr, uid, ids, context=context):
|
||||
if vals.get('journal_id') and bk_st.line_ids:
|
||||
if any([x.voucher_id and True or False for x in bk_st.line_ids]):
|
||||
raise osv.except_osv(_('Unable to change journal !'), _('You can not change the journal as you already reconciled some statement lines!'))
|
||||
raise osv.except_osv(_('Unable to Change Journal!'), _('You can not change the journal as you already reconciled some statement lines!'))
|
||||
return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 6.0dev\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
|
||||
"PO-Revision-Date: 2013-05-29 13:17+0000\n"
|
||||
"PO-Revision-Date: 2013-06-13 11:30+0000\n"
|
||||
"Last-Translator: Chertykov Denis <chertykov@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-05-30 05:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16652)\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-14 05:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16667)\n"
|
||||
|
||||
#. module: account_voucher
|
||||
#: field:account.bank.statement.line,voucher_id:0
|
||||
|
@ -27,7 +27,7 @@ msgid "account.config.settings"
|
|||
msgstr "account.config.settings"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:369
|
||||
#: code:addons/account_voucher/account_voucher.py:417
|
||||
#, python-format
|
||||
msgid "Write-Off"
|
||||
msgstr "Списание"
|
||||
|
@ -129,7 +129,7 @@ msgid "Voucher Statistics"
|
|||
msgstr ""
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1547
|
||||
#: code:addons/account_voucher/account_voucher.py:1641
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You can not change the journal as you already reconciled some statement "
|
||||
|
@ -223,8 +223,8 @@ msgid "Journal Item"
|
|||
msgstr "Элемент журнала"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:508
|
||||
#: code:addons/account_voucher/account_voucher.py:981
|
||||
#: code:addons/account_voucher/account_voucher.py:558
|
||||
#: code:addons/account_voucher/account_voucher.py:1073
|
||||
#, python-format
|
||||
msgid "Error!"
|
||||
msgstr "Ошибка!"
|
||||
|
@ -251,7 +251,7 @@ msgid "Cancelled"
|
|||
msgstr "Отменено"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1153
|
||||
#: code:addons/account_voucher/account_voucher.py:1249
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You have to configure account base code and account tax code on the '%s' tax!"
|
||||
|
@ -295,7 +295,7 @@ msgid "Tax"
|
|||
msgstr "Налог"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:879
|
||||
#: code:addons/account_voucher/account_voucher.py:971
|
||||
#, python-format
|
||||
msgid "Invalid Action!"
|
||||
msgstr "Неверное действие!"
|
||||
|
@ -348,7 +348,7 @@ msgid "Import Invoices"
|
|||
msgstr "Импорт счетов"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1112
|
||||
#: code:addons/account_voucher/account_voucher.py:1208
|
||||
#, python-format
|
||||
msgid "Wrong voucher line"
|
||||
msgstr ""
|
||||
|
@ -367,7 +367,7 @@ msgid "Receipt"
|
|||
msgstr "Приход"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1018
|
||||
#: code:addons/account_voucher/account_voucher.py:1110
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You should configure the 'Gain Exchange Rate Account' in the accounting "
|
||||
|
@ -388,7 +388,7 @@ msgstr "Период"
|
|||
|
||||
#. module: account_voucher
|
||||
#: view:account.voucher:0
|
||||
#: code:addons/account_voucher/account_voucher.py:211
|
||||
#: code:addons/account_voucher/account_voucher.py:231
|
||||
#, python-format
|
||||
msgid "Supplier"
|
||||
msgstr "Поставщик"
|
||||
|
@ -409,7 +409,7 @@ msgid "Debit"
|
|||
msgstr "Дебет"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1547
|
||||
#: code:addons/account_voucher/account_voucher.py:1641
|
||||
#, python-format
|
||||
msgid "Unable to change journal !"
|
||||
msgstr "Невозможно изменить журнал!"
|
||||
|
@ -515,7 +515,7 @@ msgid "Pay Invoice"
|
|||
msgstr "Оплата счета"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1153
|
||||
#: code:addons/account_voucher/account_voucher.py:1249
|
||||
#, python-format
|
||||
msgid "No Account Base Code and Account Tax Code!"
|
||||
msgstr ""
|
||||
|
@ -569,15 +569,15 @@ msgid "To Review"
|
|||
msgstr "Для проверки"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1025
|
||||
#: code:addons/account_voucher/account_voucher.py:1039
|
||||
#: code:addons/account_voucher/account_voucher.py:1194
|
||||
#: code:addons/account_voucher/account_voucher.py:1120
|
||||
#: code:addons/account_voucher/account_voucher.py:1134
|
||||
#: code:addons/account_voucher/account_voucher.py:1286
|
||||
#, python-format
|
||||
msgid "change"
|
||||
msgstr "изменить"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1014
|
||||
#: code:addons/account_voucher/account_voucher.py:1106
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You should configure the 'Loss Exchange Rate Account' in the accounting "
|
||||
|
@ -631,6 +631,7 @@ msgstr "Месяц"
|
|||
#. module: account_voucher
|
||||
#: field:account.voucher,currency_id:0
|
||||
#: field:account.voucher.line,currency_id:0
|
||||
#: model:ir.model,name:account_voucher.model_res_currency
|
||||
#: field:sale.receipt.report,currency_id:0
|
||||
msgid "Currency"
|
||||
msgstr "Валюта"
|
||||
|
@ -674,7 +675,7 @@ msgid "Reconcile Payment Balance"
|
|||
msgstr "Сверка платежного баланса"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:975
|
||||
#: code:addons/account_voucher/account_voucher.py:1067
|
||||
#, python-format
|
||||
msgid "Configuration Error !"
|
||||
msgstr "Ошибка конфигурации !"
|
||||
|
@ -739,7 +740,7 @@ msgid "October"
|
|||
msgstr "Октябрь"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:976
|
||||
#: code:addons/account_voucher/account_voucher.py:1068
|
||||
#, python-format
|
||||
msgid "Please activate the sequence of selected journal !"
|
||||
msgstr "Пожалуйста, включите нумерацию выбранного журнала!"
|
||||
|
@ -819,7 +820,7 @@ msgid "Previous Payments ?"
|
|||
msgstr "Предыдущие платежи ?"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1112
|
||||
#: code:addons/account_voucher/account_voucher.py:1208
|
||||
#, python-format
|
||||
msgid "The invoice you are willing to pay is not valid anymore."
|
||||
msgstr "Счет, который вы готовы платить, уже не актуален ."
|
||||
|
@ -851,7 +852,7 @@ msgid "Active"
|
|||
msgstr "Активно"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:982
|
||||
#: code:addons/account_voucher/account_voucher.py:1074
|
||||
#, python-format
|
||||
msgid "Please define a sequence on the journal."
|
||||
msgstr "Пожалуйста, определите нумерацию журнала."
|
||||
|
@ -861,7 +862,7 @@ msgstr "Пожалуйста, определите нумерацию журна
|
|||
#: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt
|
||||
#: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt
|
||||
msgid "Customer Payments"
|
||||
msgstr "Платежи клиентов"
|
||||
msgstr "Платежи заказчиков"
|
||||
|
||||
#. module: account_voucher
|
||||
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all
|
||||
|
@ -979,7 +980,7 @@ msgid "Journal Items"
|
|||
msgstr "Элементы журнала"
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:508
|
||||
#: code:addons/account_voucher/account_voucher.py:558
|
||||
#, python-format
|
||||
msgid "Please define default credit/debit accounts on the journal \"%s\"."
|
||||
msgstr ""
|
||||
|
@ -1188,7 +1189,7 @@ msgid ""
|
|||
msgstr ""
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:879
|
||||
#: code:addons/account_voucher/account_voucher.py:971
|
||||
#, python-format
|
||||
msgid "Cannot delete voucher(s) which are already opened or paid."
|
||||
msgstr ""
|
||||
|
@ -1251,8 +1252,8 @@ msgid "Status <b>changed</b>"
|
|||
msgstr ""
|
||||
|
||||
#. module: account_voucher
|
||||
#: code:addons/account_voucher/account_voucher.py:1014
|
||||
#: code:addons/account_voucher/account_voucher.py:1018
|
||||
#: code:addons/account_voucher/account_voucher.py:1106
|
||||
#: code:addons/account_voucher/account_voucher.py:1110
|
||||
#, python-format
|
||||
msgid "Insufficient Configuration!"
|
||||
msgstr ""
|
||||
|
|
|
@ -157,7 +157,7 @@ class account_analytic_account(osv.osv):
|
|||
for account in self.browse(cr, uid, ids, context=context):
|
||||
if account.company_id:
|
||||
if account.company_id.currency_id.id != value:
|
||||
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really usefull for consolidation purposes of several companies charts with different currencies, for example."))
|
||||
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really useful for consolidation purposes of several companies charts with different currencies, for example."))
|
||||
if value:
|
||||
return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ class hr_analytic_timesheet(osv.osv):
|
|||
a = r.product_id.categ_id.property_account_expense_categ.id
|
||||
if not a:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('There is no expense account define ' \
|
||||
_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d)') % \
|
||||
(r.product_id.name, r.product_id.id,))
|
||||
# Compute based on pricetype
|
||||
|
@ -133,7 +133,7 @@ class hr_analytic_timesheet(osv.osv):
|
|||
a = r.product_id.categ_id.property_account_expense_categ.id
|
||||
if not a:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('There is no expense account define ' \
|
||||
_('There is no expense account defined ' \
|
||||
'for this product: "%s" (id:%d)') % \
|
||||
(r.product_id.name, r.product_id.id,))
|
||||
# Compute based on pricetype
|
||||
|
|
|
@ -86,11 +86,11 @@ class ir_model_fields_anonymization(osv.osv):
|
|||
if context.get('manual'):
|
||||
global_state = self._get_global_state(cr, uid, context=context)
|
||||
if global_state == 'anonymized':
|
||||
raise osv.except_osv('Error !', "The database is currently anonymized, you cannot create, modify or delete fields.")
|
||||
raise osv.except_osv('Error!', "The database is currently anonymized, you cannot create, modify or delete fields.")
|
||||
elif global_state == 'unstable':
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to create, write or delete fields.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -357,7 +357,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
|||
else:
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to do anything else.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
res['arch'] = etree.tostring(eview)
|
||||
|
||||
|
@ -521,11 +521,11 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
|
|||
# check that all the defined fields are in the 'anonymized' state
|
||||
state = ir_model_fields_anonymization_model._get_global_state(cr, uid, context=context)
|
||||
if state == 'clear':
|
||||
raise osv.except_osv_('Error !', "The database is not currently anonymized, you cannot reverse the anonymization.")
|
||||
raise osv.except_osv_('Error!', "The database is not currently anonymized, you cannot reverse the anonymization.")
|
||||
elif state == 'unstable':
|
||||
msg = _("The database anonymization is currently in an unstable state. Some fields are anonymized," + \
|
||||
" while some fields are not anonymized. You should try to solve this problem before trying to do anything.")
|
||||
raise osv.except_osv('Error !', msg)
|
||||
raise osv.except_osv('Error!', msg)
|
||||
|
||||
wizards = self.browse(cr, uid, ids, context=context)
|
||||
for wizard in wizards:
|
||||
|
|
|
@ -102,7 +102,10 @@ class OAuthController(oeweb.Controller):
|
|||
registry = RegistryManager.get(dbname)
|
||||
with registry.cursor() as cr:
|
||||
IMD = registry['ir.model.data']
|
||||
model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
|
||||
try:
|
||||
model, provider_id = IMD.get_object_reference(cr, SUPERUSER_ID, 'auth_oauth', 'provider_openerp')
|
||||
except ValueError:
|
||||
return set_cookie_and_redirect(req, '/?db=%s' % dbname)
|
||||
assert model == 'auth.oauth.provider'
|
||||
|
||||
state = {
|
||||
|
|
|
@ -60,7 +60,7 @@ class crm_meeting(base_state, osv.Model):
|
|||
'categ_ids': fields.many2many('crm.meeting.type', 'meeting_category_rel',
|
||||
'event_id', 'type_id', 'Tags'),
|
||||
'attendee_ids': fields.many2many('calendar.attendee', 'meeting_attendee_rel',\
|
||||
'event_id', 'attendee_id', 'Attendees', states={'done': [('readonly', True)]}),
|
||||
'event_id', 'attendee_id', 'Invited People', states={'done': [('readonly', True)]}),
|
||||
}
|
||||
_defaults = {
|
||||
'state': 'open',
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Name,Is a company,Related company,Address type,Customer,Supplier,Street,ZIP,City,State,Country
|
||||
Aurora Shelves,1,,,1,0,25 Pacific Road,95101,San José,CA,United States
|
||||
Roger Martins,0,Aurora Shelves,Invoice,1,0,27 Pacific Road,95102,San José,CA,United States
|
||||
House Sales Direct,1,,,1,0,104 Saint Mary Avenue,94059,Redwood,CA,United States
|
||||
Yvan Holiday,0,House Sales Direct,Default,1,0,104 Saint Mary Avenue,94060,Redwood,CA,United States
|
||||
Jack Unsworth,0,House Sales Direct,Invoice,1,0,227 Jackson Road,94061,Redwood,CA,United States
|
||||
Michael Mason,0,,,1,0,16 5th Avenue,94104,San Francisco,CA,United States
|
||||
International Wood,1,,,1,0,748 White House Boulevard,20004,Washington,DC,United States
|
||||
Sharon Pecker,0,International Wood,Invoice,1,0,755 White House Boulevard,20005,Washington,DC,United States
|
|
|
@ -1,8 +0,0 @@
|
|||
Name,Address type,Street,City,Country,Tags,Supplier,Customer,Is a company,Companies that refers to partner / Parent company
|
||||
Wood y Wood Pecker,,"Snow Street, 25",Kainuu,Finland,Supplier,1,0,1,
|
||||
Roger Pecker,Default,"Snow Street, 27",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
||||
Sharon Pecker,Delivery,"Snow Street, 28",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
||||
Thomas Pecker,Contact,"Snow Street, 27",Kainuu,Finland,Supplier,1,0,0,Wood y Wood Pecker
|
||||
Vicking Direct,,"Atonium Street, 45a",Brussels,Belgium,Supplier,1,0,1,
|
||||
Yvan Holiday,Invoice,"Atonium Street, 45b",Brussels,Belgium,Supplier,1,0,0,Vicking Direct
|
||||
Jack Unsworth,Contact,"Atonium Street, 45a",Brussels,Belgium,Supplier,1,0,0,Vicking Direct
|
|
|
@ -229,8 +229,8 @@
|
|||
orders with their respective purchase order lines:</p>
|
||||
<a href="/base_import/static/csv/o2m_purchase_order_lines.csv">Purchase orders with their respective purchase order lines</a>
|
||||
<p>The following CSV file shows how to import
|
||||
suppliers and their respective contacts</p>
|
||||
<a href="/base_import/static/csv/o2m_suppliers_contacts.csv">Suppliers and their respective contacts</a>
|
||||
customers and their respective contacts</p>
|
||||
<a href="/base_import/static/csv/o2m_customers_contacts.csv">Customers and their respective contacts</a>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
|
|
@ -14,9 +14,13 @@
|
|||
<label string="This plug-in allows you to create/modify OpenERP Reports into OpenOffice Writer."/>
|
||||
</separator>
|
||||
<xpath expr="//button[@string='Install Modules']" position="replace">
|
||||
<button name="action_next" icon="gtk-go-forward" type="object" string="Configure" invisible="context.get('menu',False)" class="oe_highlight"/>
|
||||
<button name="action_next" type="object" string="Configure" invisible="context.get('menu',False)" class="oe_highlight"/>
|
||||
<label string="or" invisible="context.get('menu',False)" class="oe_inline"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@string='Skip']" position="replace">
|
||||
<button string="Ok" class="oe_highlight" special="cancel" invisible="context.get('active_model',False)"/>
|
||||
<button string="Skip" class="oe_link" special="cancel" invisible="context.get('menu',False)"/>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//separator[@string='title']" position="after">
|
||||
<group colspan="8" height="450" width="750">
|
||||
<field name="name" invisible="1"/>
|
||||
|
|
|
@ -61,8 +61,8 @@ class RPCSession(object):
|
|||
protocol = m.group(1)
|
||||
if not m:
|
||||
return -1
|
||||
if protocol == 'http://' or protocol == 'http://':
|
||||
self.gateway = XMLRPCGateway(host, port, 'http')
|
||||
if protocol == 'http://' or protocol == 'https://':
|
||||
self.gateway = XMLRPCGateway(host, port, protocol[:-3])
|
||||
elif protocol == 'socket://':
|
||||
|
||||
self.gateway = NETRPCGateway(host, port)
|
||||
|
|
Binary file not shown.
|
@ -104,7 +104,7 @@ class base_state(object):
|
|||
if parent_id.change_responsible and parent_id.user_id:
|
||||
data['user_id'] = parent_id.user_id.id
|
||||
else:
|
||||
raise osv.except_osv(_('Error !'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
raise osv.except_osv(_('Error!'), _('You can not escalate, you are already at the top level regarding your sales-team category.'))
|
||||
self.write(cr, uid, [case.id], data, context=context)
|
||||
case.case_escalate_send_note(parent_id, context=context)
|
||||
return True
|
||||
|
|
|
@ -344,7 +344,7 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
|
|||
},
|
||||
load_data:function(){
|
||||
var board = new instance.web.Model('board.board');
|
||||
return board.call('list');
|
||||
return board.call('list', [board.context()]);
|
||||
},
|
||||
_x:function() {
|
||||
if (!instance.webclient) { return $.Deferred().reject(); }
|
||||
|
|
|
@ -2,19 +2,6 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Add section_id (Sales Team) to res.partner -->
|
||||
<record id="view_partners_form_crm1" model="ir.ui.view">
|
||||
<field name="name">view.res.partner.form.crm.inherited1</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field eval="18" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="user_id" position="after">
|
||||
<field name="section_id" completion="1" groups="base.group_multi_salesteams"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- open meetings related to given partner -->
|
||||
<record id="crm_meeting_partner" model="ir.actions.act_window">
|
||||
<field name="name">Meetings</field>
|
||||
|
@ -91,24 +78,31 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="res_partner_view_buttons">
|
||||
<field name="name">res.partner.view.buttons</field>
|
||||
<!-- Add section_id (SalesTeam) and contextual button on partner form view -->
|
||||
<record id="view_partners_form_crm1" model="ir.ui.view">
|
||||
<field name="name">view.res.partner.form.crm.inherited1</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form" />
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field eval="18" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button type="action"
|
||||
string="Meetings"
|
||||
name="%(base_calendar.action_crm_meeting)d"
|
||||
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
|
||||
<button type="action" string="Calls"
|
||||
name="%(crm.crm_case_categ_phone_incoming0)d"
|
||||
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}" />
|
||||
<button type="action" string="Opportunities" attrs="{'invisible': [('customer', '=', False)]}"
|
||||
name="%(crm.crm_case_category_act_oppor11)d" context="{'search_default_partner_id': active_id}"/>
|
||||
</xpath>
|
||||
<data>
|
||||
<field name="user_id" position="after">
|
||||
<field name="section_id" completion="1" groups="base.group_multi_salesteams"/>
|
||||
</field>
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button class="oe_inline" type="action" string="Opportunities"
|
||||
attrs="{'invisible': [('customer', '=', False)]}"
|
||||
name="%(crm.crm_case_category_act_oppor11)d"
|
||||
context="{'search_default_partner_id': active_id}"/>
|
||||
<button class="oe_inline" type="action"
|
||||
string="Meetings"
|
||||
name="%(base_calendar.action_crm_meeting)d"
|
||||
context="{'search_default_partner_ids': active_id, 'default_partner_ids' : [active_id]}"/>
|
||||
<button class="oe_inline" type="action" string="Calls"
|
||||
name="%(crm.crm_case_categ_phone_incoming0)d"
|
||||
context="{'search_default_partner_id': active_id, 'default_duration': 1.0}" />
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
lead_obj = self.pool.get('crm.lead')
|
||||
for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context):
|
||||
if lead.state in ['done', 'cancel']:
|
||||
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled leads cannot be converted into opportunities."))
|
||||
raise osv.except_osv(_("Warning!"), _("Closed/Cancelled leads cannot be converted into opportunities."))
|
||||
return False
|
||||
|
||||
def _convert_opportunity(self, cr, uid, ids, vals, context=None):
|
||||
|
|
|
@ -42,14 +42,20 @@ automatically new claims based on incoming emails.
|
|||
'security/ir.model.access.csv',
|
||||
'report/crm_claim_report_view.xml',
|
||||
'crm_claim_data.xml',
|
||||
'res_partner_view.xml',
|
||||
],
|
||||
'demo': ['crm_claim_demo.xml'],
|
||||
'test': ['test/process/claim.yml',
|
||||
'test/ui/claim_demo.yml'
|
||||
'test': [
|
||||
'test/process/claim.yml',
|
||||
'test/ui/claim_demo.yml'
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'images': ['images/claim_categories.jpeg','images/claim_stages.jpeg','images/claims.jpeg'],
|
||||
'images': [
|
||||
'images/claim_categories.jpeg',
|
||||
'images/claim_stages.jpeg',
|
||||
'images/claims.jpeg'
|
||||
],
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
<field name="view_id" ref="crm_case_claims_tree_view"/>
|
||||
<field name="context">{"search_default_user_id":uid, "stage_type":'claim'}</field>
|
||||
<field name="search_view_id" ref="crm_claim.view_crm_case_claims_filter"/>
|
||||
<field name="help">Record and track your customers' claims. Claims may be linked to a sales order or a lot. You can send emails with attachments and keep the full history for a claim (emails sent, intervention type and so on). Claims may automatically be linked to an email address using the mail gateway module.</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Record and track your customers' claims. Claims may be linked to a sales order or a lot.You can send emails with attachments and keep the full history for a claim (emails sent, intervention type and so on).Claims may automatically be linked to an email address using the mail gateway module.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_claim0">
|
||||
|
|
|
@ -216,35 +216,5 @@
|
|||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_claim_partner_info_form1" model="ir.ui.view">
|
||||
<field name="name">res.partner.claim.info.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='page_history']" position="attributes">
|
||||
<attribute name="invisible">False</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='page_history']" position="inside">
|
||||
<group name="grp_claim" string="Claims">
|
||||
<field name="claims_ids" colspan="4" nolabel="1">
|
||||
<tree string="Partners Claim" editable="bottom">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window
|
||||
context="{'search_default_partner_id': [active_id], 'default_partner_id': active_id}"
|
||||
id="act_claim_partner"
|
||||
name="Claims"
|
||||
view_mode="tree,form"
|
||||
res_model="crm.claim"
|
||||
src_model="res.partner"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Partners inherited form -->
|
||||
<record id="view_claim_res_partner_info_form" model="ir.ui.view">
|
||||
<field name="name">res.partner.claim.info.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="priority" eval="50"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='buttons']" position="inside">
|
||||
<button class="oe_inline" type="action"
|
||||
name="%(crm_case_categ_claim0)d"
|
||||
string="Claims"
|
||||
context="{'search_default_partner_id': active_id, 'default_partner_id': active_id}"
|
||||
groups="base.group_sale_salesman" />
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -14,7 +14,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-07 05:48+0000\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-08 05:52+0000\n"
|
||||
"X-Generator: Launchpad (build 16667)\n"
|
||||
|
||||
#. module: crm_helpdesk
|
||||
|
|
|
@ -51,10 +51,10 @@ class sale_order(osv.osv):
|
|||
for order in self.browse(cr, uid, ids, context=context):
|
||||
grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id)
|
||||
if not grid_id:
|
||||
raise osv.except_osv(_('No grid available !'), _('No grid matching for this carrier !'))
|
||||
raise osv.except_osv(_('No Grid Available!'), _('No grid matching for this carrier!'))
|
||||
|
||||
if not order.state in ('draft'):
|
||||
raise osv.except_osv(_('Order not in draft state !'), _('The order state have to be draft to add delivery lines.'))
|
||||
raise osv.except_osv(_('Order not in Draft State!'), _('The order state have to be draft to add delivery lines.'))
|
||||
|
||||
grid = grid_obj.browse(cr, uid, grid_id, context=context)
|
||||
|
||||
|
|
|
@ -88,7 +88,11 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_wiki_tree"/>
|
||||
<field name="search_view_id" ref="view_wiki_filter"/>
|
||||
<field name="help">Create web pages</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new web page.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<menuitem id="menu_page" parent="menu_wiki" name="Pages" action="action_page" sequence="10"/>
|
||||
<record id="action_category" model="ir.actions.act_window">
|
||||
|
|
|
@ -126,7 +126,7 @@ class edi(osv.AbstractModel):
|
|||
module = edi_document.get('__import_module') or edi_document.get('__module')
|
||||
assert module, 'a `__module` or `__import_module` attribute is required in each EDI document.'
|
||||
if module != 'base' and not ir_module.search(cr, uid, [('name','=',module),('state','=','installed')]):
|
||||
raise osv.except_osv(_('Missing application.'),
|
||||
raise osv.except_osv(_('Missing Application.'),
|
||||
_("The document you are trying to import requires the OpenERP `%s` application. "
|
||||
"You can install it by connecting as the administrator and opening the configuration assistant.")%(module,))
|
||||
model = edi_document.get('__import_model') or edi_document.get('__model')
|
||||
|
|
|
@ -24,8 +24,8 @@ import base64
|
|||
import logging
|
||||
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.osv import fields
|
||||
from openerp import tools
|
||||
from openerp.tools.translate import _
|
||||
from urllib import urlencode, quote as quote
|
||||
|
@ -191,7 +191,6 @@ class email_template(osv.osv):
|
|||
}
|
||||
|
||||
def create_action(self, cr, uid, ids, context=None):
|
||||
vals = {}
|
||||
action_obj = self.pool.get('ir.actions.act_window')
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
for template in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -199,7 +198,7 @@ class email_template(osv.osv):
|
|||
model_data_id = data_obj._get_id(cr, uid, 'mail', 'email_compose_message_wizard_form')
|
||||
res_id = data_obj.browse(cr, uid, model_data_id, context=context).res_id
|
||||
button_name = _('Send Mail (%s)') % template.name
|
||||
vals['ref_ir_act_window'] = action_obj.create(cr, uid, {
|
||||
act_id = action_obj.create(cr, SUPERUSER_ID, {
|
||||
'name': button_name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'mail.compose.message',
|
||||
|
@ -211,27 +210,29 @@ class email_template(osv.osv):
|
|||
'target': 'new',
|
||||
'auto_refresh':1
|
||||
}, context)
|
||||
vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
|
||||
ir_values_id = self.pool.get('ir.values').create(cr, SUPERUSER_ID, {
|
||||
'name': button_name,
|
||||
'model': src_obj,
|
||||
'key2': 'client_action_multi',
|
||||
'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']),
|
||||
'value': "ir.actions.act_window,%s" % act_id,
|
||||
'object': True,
|
||||
}, context)
|
||||
self.write(cr, uid, ids, {
|
||||
'ref_ir_act_window': vals.get('ref_ir_act_window',False),
|
||||
'ref_ir_value': vals.get('ref_ir_value',False),
|
||||
}, context)
|
||||
|
||||
template.write({
|
||||
'ref_ir_act_window': act_id,
|
||||
'ref_ir_value': ir_values_id,
|
||||
})
|
||||
|
||||
return True
|
||||
|
||||
def unlink_action(self, cr, uid, ids, context=None):
|
||||
for template in self.browse(cr, uid, ids, context=context):
|
||||
try:
|
||||
if template.ref_ir_act_window:
|
||||
self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context)
|
||||
self.pool.get('ir.actions.act_window').unlink(cr, SUPERUSER_ID, template.ref_ir_act_window.id, context)
|
||||
if template.ref_ir_value:
|
||||
ir_values_obj = self.pool.get('ir.values')
|
||||
ir_values_obj.unlink(cr, uid, template.ref_ir_value.id, context)
|
||||
ir_values_obj.unlink(cr, SUPERUSER_ID, template.ref_ir_value.id, context)
|
||||
except Exception:
|
||||
raise osv.except_osv(_("Warning"), _("Deletion of the action record failed."))
|
||||
return True
|
||||
|
|
|
@ -54,18 +54,22 @@ class mail_compose_message(osv.TransientModel):
|
|||
Indeed, basic mail.compose.message wizard duplicates attachments in mass
|
||||
mailing mode. But in 'single post' mode, attachments of an email template
|
||||
also have to be duplicated to avoid changing their ownership. """
|
||||
if context is None:
|
||||
context = {}
|
||||
wizard_context = dict(context)
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
if wizard.template_id and not wizard.template_id.user_signature:
|
||||
wizard_context['mail_notify_user_signature'] = False # template user_signature is added when generating body_html
|
||||
if not wizard.attachment_ids or wizard.composition_mode == 'mass_mail' or not wizard.template_id:
|
||||
continue
|
||||
template = self.pool.get('email.template').browse(cr, uid, wizard.template_id.id, context=context)
|
||||
new_attachment_ids = []
|
||||
for attachment in wizard.attachment_ids:
|
||||
if attachment in template.attachment_ids:
|
||||
if attachment in wizard.template_id.attachment_ids:
|
||||
new_attachment_ids.append(self.pool.get('ir.attachment').copy(cr, uid, attachment.id, {'res_model': 'mail.compose.message', 'res_id': wizard.id}, context=context))
|
||||
else:
|
||||
new_attachment_ids.append(attachment.id)
|
||||
self.write(cr, uid, wizard.id, {'attachment_ids': [(6, 0, new_attachment_ids)]}, context=context)
|
||||
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
|
||||
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=wizard_context)
|
||||
|
||||
def onchange_template_id(self, cr, uid, ids, template_id, composition_mode, model, res_id, context=None):
|
||||
""" - mass_mailing: we cannot render, so return the template values
|
||||
|
|
|
@ -21,15 +21,13 @@
|
|||
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
||||
class res_partner(osv.osv):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
_columns = {
|
||||
'speaker': fields.boolean('Speaker', help="Check this box if this contact is a speaker."),
|
||||
'event_ids': fields.one2many('event.event','main_speaker_id', readonly=True),
|
||||
'event_registration_ids': fields.one2many('event.registration','partner_id', readonly=True),
|
||||
}
|
||||
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Partners inherited form -->
|
||||
|
||||
<record id="view_event_partner_info_form" model="ir.ui.view">
|
||||
<!-- Partners inherited form -->
|
||||
<record id="view_event_partner_info_form" model="ir.ui.view">
|
||||
<field name="name">res.partner.event.info.inherit</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
|
@ -12,34 +11,8 @@
|
|||
<field name="supplier" position="after">
|
||||
<field name="speaker"/>
|
||||
</field>
|
||||
<xpath expr="//page[@name='page_history']" position="attributes">
|
||||
<attribute name="invisible">False</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='page_history']" position="inside">
|
||||
<group name="grp_event" string="Events">
|
||||
<field name="event_ids" colspan="4" nolabel="1">
|
||||
<tree string="Events">
|
||||
<field name="name" string="Event"/>
|
||||
<field name="main_speaker_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<group name="grp_registration" string="Registrations">
|
||||
<field name="event_registration_ids" colspan="4" nolabel="1">
|
||||
<tree string="Events Registration">
|
||||
<field name="event_begin_date" string="Date"/>
|
||||
<field name="event_id" />
|
||||
<field name="nb_register"/>
|
||||
<field name="state"/>
|
||||
<button name="button_reg_cancel" string="Cancel Registration" states="draft,open" type="object" icon="gtk-cancel"/>
|
||||
<button name="button_reg_close" string="Close Registration" states="open" type="object" icon="gtk-close"/>
|
||||
<button name="check_confirm" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -591,6 +591,9 @@
|
|||
<field name="view_mode">tree,graph</field>
|
||||
<field name="context">{"search_default_groupby_vehicle" : True}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new odometer log.
|
||||
</p>
|
||||
<p>
|
||||
Here you can add various odometer entries for all vehicles.
|
||||
You can also show odometer value for a particular vehicle using
|
||||
|
|
|
@ -23,5 +23,6 @@ import hr_department
|
|||
import hr
|
||||
|
||||
import res_config
|
||||
import res_users
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -59,6 +59,8 @@ You can manage:
|
|||
'hr_installer.xml',
|
||||
'hr_data.xml',
|
||||
'res_config_view.xml',
|
||||
'mail_hr_view.xml',
|
||||
'res_users_view.xml',
|
||||
],
|
||||
'demo': ['hr_demo.xml'],
|
||||
'test': [
|
||||
|
@ -69,5 +71,7 @@ You can manage:
|
|||
'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:
|
||||
|
|
107
addons/hr/hr.py
107
addons/hr/hr.py
|
@ -25,9 +25,11 @@ 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):
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
|
@ -156,6 +158,7 @@ class hr_job(osv.osv):
|
|||
class hr_employee(osv.osv):
|
||||
_name = "hr.employee"
|
||||
_description = "Employee"
|
||||
_order = 'name_related'
|
||||
_inherits = {'resource.resource': "resource_id"}
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
|
@ -164,10 +167,10 @@ class hr_employee(osv.osv):
|
|||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
result[obj.id] = tools.image_get_resized_images(obj.image)
|
||||
return result
|
||||
|
||||
|
||||
def _set_image(self, cr, uid, id, name, value, args, context=None):
|
||||
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
|
||||
|
||||
|
||||
_columns = {
|
||||
#we need a related field in order to be able to sort the employee by name
|
||||
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
|
||||
|
@ -177,12 +180,12 @@ class hr_employee(osv.osv):
|
|||
'sinid': fields.char('SIN No', size=32, help="Social Insurance Number"),
|
||||
'identification_id': fields.char('Identification No', size=32),
|
||||
'otherid': fields.char('Other Id', size=64),
|
||||
'gender': fields.selection([('male', 'Male'),('female', 'Female')], 'Gender'),
|
||||
'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
|
||||
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
|
||||
'department_id':fields.many2one('hr.department', 'Department'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'address_id': fields.many2one('res.partner', 'Working Address'),
|
||||
'address_home_id': fields.many2one('res.partner', 'Home Address'),
|
||||
'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
|
||||
'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
|
||||
'work_phone': fields.char('Work Phone', size=32, readonly=False),
|
||||
'mobile_phone': fields.char('Work Mobile', size=32, readonly=False),
|
||||
'work_email': fields.char('Work Email', size=240),
|
||||
|
@ -213,25 +216,42 @@ class hr_employee(osv.osv):
|
|||
help="Small-sized photo of the employee. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required."),
|
||||
'passport_id':fields.char('Passport No', size=64),
|
||||
'passport_id': fields.char('Passport No', size=64),
|
||||
'color': fields.integer('Color Index'),
|
||||
'city': fields.related('address_id', 'city', type='char', string='City'),
|
||||
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
|
||||
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
|
||||
}
|
||||
|
||||
_order='name_related'
|
||||
def _get_default_image(self, cr, uid, context=None):
|
||||
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
|
||||
defaults = {
|
||||
'active': 1,
|
||||
'image': _get_default_image,
|
||||
'color': 0,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, data, context=None):
|
||||
employee_id = super(hr_employee, self).create(cr, uid, data, context=context)
|
||||
try:
|
||||
(model, mail_group_id) = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'group_all_employees')
|
||||
employee = self.browse(cr, uid, employee_id, context=context)
|
||||
self.pool.get('mail.group').message_post(cr, uid, [mail_group_id],
|
||||
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
|
||||
subtype='mail.mt_comment', context=context)
|
||||
except:
|
||||
pass # group deleted: do not push a message
|
||||
if context is None:
|
||||
context = {}
|
||||
create_ctx = dict(context, mail_create_nolog=True)
|
||||
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
|
||||
employee = self.browse(cr, uid, employee_id, context=context)
|
||||
if employee.user_id:
|
||||
# send a copy to every user of the company
|
||||
company_id = employee.user_id.partner_id.company_id.id
|
||||
partner_ids = self.pool.get('res.partner').search(cr, uid, [
|
||||
('company_id', '=', company_id),
|
||||
('user_ids', '!=', False)], context=context)
|
||||
else:
|
||||
partner_ids = []
|
||||
self.message_post(cr, uid, [employee_id],
|
||||
body=_('Welcome to %s! Please help him/her take the first steps with OpenERP!') % (employee.name),
|
||||
partner_ids=partner_ids,
|
||||
subtype='mail.mt_comment', context=context
|
||||
)
|
||||
return employee_id
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
|
@ -252,7 +272,7 @@ class hr_employee(osv.osv):
|
|||
company_id = self.pool.get('res.company').browse(cr, uid, company, context=context)
|
||||
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['default'])
|
||||
address_id = address and address['default'] or False
|
||||
return {'value': {'address_id' : address_id}}
|
||||
return {'value': {'address_id': address_id}}
|
||||
|
||||
def onchange_department_id(self, cr, uid, ids, department_id, context=None):
|
||||
value = {'parent_id': False}
|
||||
|
@ -265,17 +285,36 @@ class hr_employee(osv.osv):
|
|||
work_email = False
|
||||
if user_id:
|
||||
work_email = self.pool.get('res.users').browse(cr, uid, user_id, context=context).email
|
||||
return {'value': {'work_email' : work_email}}
|
||||
return {'value': {'work_email': work_email}}
|
||||
|
||||
def _get_default_image(self, cr, uid, context=None):
|
||||
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
def action_follow(self, cr, uid, ids, context=None):
|
||||
""" Wrapper because message_subscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_subscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
_defaults = {
|
||||
'active': 1,
|
||||
'image': _get_default_image,
|
||||
'color': 0,
|
||||
}
|
||||
def action_unfollow(self, cr, uid, ids, context=None):
|
||||
""" Wrapper because message_unsubscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_unsubscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Show the suggestion of employees if display_employees_suggestions if the
|
||||
user perference allows it. """
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
if not user.display_employees_suggestions:
|
||||
return []
|
||||
else:
|
||||
return super(hr_employee, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
|
||||
|
||||
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
|
||||
""" Overwrite of the original method to always follow user_id field,
|
||||
even when not track_visibility so that a user will follow it's employee
|
||||
"""
|
||||
user_field_lst = []
|
||||
for name, column_info in self._all_columns.items():
|
||||
if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
|
||||
user_field_lst.append(name)
|
||||
return user_field_lst
|
||||
|
||||
def _check_recursion(self, cr, uid, ids, context=None):
|
||||
level = 100
|
||||
|
@ -291,6 +330,22 @@ class hr_employee(osv.osv):
|
|||
(_check_recursion, 'Error! You cannot create recursive hierarchy of Employee(s).', ['parent_id']),
|
||||
]
|
||||
|
||||
# ---------------------------------------------------
|
||||
# Mail gateway
|
||||
# ---------------------------------------------------
|
||||
|
||||
def check_mail_message_access(self, cr, uid, mids, operation, model_obj=None, context=None):
|
||||
""" mail.message document permission rule: can post a new message if can read
|
||||
because of portal document. """
|
||||
if not model_obj:
|
||||
model_obj = self
|
||||
employee_ids = model_obj.search(cr, uid, [('user_id', '=', uid)], context=context)
|
||||
if employee_ids and operation == 'create':
|
||||
model_obj.check_access_rights(cr, uid, 'read')
|
||||
model_obj.check_access_rule(cr, uid, mids, 'read', context=context)
|
||||
else:
|
||||
return super(hr_employee, self).check_mail_message_access(cr, uid, mids, operation, model_obj=model_obj, context=context)
|
||||
|
||||
|
||||
class hr_department(osv.osv):
|
||||
_description = "Department"
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
</h1>
|
||||
<label for="category_ids" class="oe_edit_only" groups="base.group_hr_user"/>
|
||||
<field name="category_ids" widget="many2many_tags" placeholder="e.g. Part Time" groups="base.group_hr_user"/>
|
||||
<label for="work_email" class="oe_edit_only"/>
|
||||
<field name="work_email" widget="email"/>
|
||||
<label for="work_phone" class="oe_edit_only"/>
|
||||
<field name="work_phone"/>
|
||||
</div>
|
||||
<div class="oe_right oe_button_box" name="button_box">
|
||||
<!-- Put here related buttons -->
|
||||
|
@ -36,8 +40,6 @@
|
|||
<group>
|
||||
<group string="Contact Information">
|
||||
<field name="address_id" on_change="onchange_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
|
||||
<field name="work_email" widget="email"/>
|
||||
<field name="work_phone"/>
|
||||
<field name="mobile_phone"/>
|
||||
<field name="work_location"/>
|
||||
</group>
|
||||
|
@ -136,6 +138,9 @@
|
|||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="last_login"/>
|
||||
<field name="message_is_follower"/>
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_ids"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_employee_vignette">
|
||||
|
@ -154,10 +159,19 @@
|
|||
</li>
|
||||
<li t-if="record.job_id.raw_value"><field name="job_id"/></li>
|
||||
<li t-if="record.work_location.raw_value"><field name="work_location"/></li>
|
||||
<li t-if="record.work_phone.raw_value">Tel: <field name="work_phone"/></li>
|
||||
<li t-if="record.mobile_phone.raw_value">Mobile: <field name="mobile_phone"/></li>
|
||||
<li t-if="record.work_email.raw_value"><a t-attf-href="mailto:#{record.work_email.value}"><field name="work_email"/></a></li>
|
||||
</ul>
|
||||
<div class="oe_kanban_footer_left">
|
||||
<span title='Messages'><span class='oe_e'>9</span><t t-esc="record.message_ids.raw_value.length"/></span>
|
||||
<span title='Followers'><span class='oe_e'>+</span><t t-esc="record.message_follower_ids.raw_value.length"/></span>
|
||||
</div>
|
||||
<div class="oe_followers" groups="base.group_user">
|
||||
<button t-if="record.message_is_follower.raw_value" name="action_unfollow" type="object" class="oe_follower oe_following">
|
||||
<span class="oe_unfollow">Unfollow</span>
|
||||
<span class="oe_following">Following</span>
|
||||
</button>
|
||||
<button t-if="! record.message_is_follower.raw_value" name="action_follow" type="object" class="oe_follower oe_notfollow">Follow</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="mail.action_mail_inbox_feeds" model="ir.actions.client">
|
||||
<field name="params" eval=""{
|
||||
'domain': [
|
||||
('to_read', '=', True),
|
||||
('starred', '=', False),
|
||||
],
|
||||
'view_mailbox': True,
|
||||
'view_inbox': True,
|
||||
'read_action': 'read',
|
||||
'show_compose_message': True
|
||||
}""/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,65 @@
|
|||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class res_users(osv.Model):
|
||||
""" Update of res.users class
|
||||
- if adding groups to an user, check if base.group_user is in it
|
||||
(member of 'Employee'), create an employee form linked to it.
|
||||
"""
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users']
|
||||
|
||||
_columns = {
|
||||
'display_employees_suggestions': fields.boolean("Display Employees Suggestions"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'display_employees_suggestions': True,
|
||||
}
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
""" Override of __init__ to add access rights on
|
||||
display_employees_suggestions fields. Access rights are disabled by
|
||||
default, but allowed on some specific fields defined in
|
||||
self.SELF_{READ/WRITE}ABLE_FIELDS.
|
||||
"""
|
||||
init_res = super(res_users, self).__init__(pool, cr)
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
|
||||
self.SELF_WRITEABLE_FIELDS.append('display_employees_suggestions')
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
|
||||
self.SELF_READABLE_FIELDS.append('display_employees_suggestions')
|
||||
return init_res
|
||||
|
||||
def stop_showing_employees_suggestions(self, cr, uid, user_id, context=None):
|
||||
"""Update display_employees_suggestions value to False"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.write(cr, uid, user_id, {"display_employees_suggestions": False}, context)
|
||||
|
||||
def _create_welcome_message(self, cr, uid, user, context=None):
|
||||
"""Do not welcome new users anymore, welcome new employees instead"""
|
||||
return True
|
||||
|
||||
def _message_post_get_eid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'hr.employee'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
return self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', thread_id)], context=context)
|
||||
|
||||
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related employee.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
if kwargs.get('type') == 'email':
|
||||
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||
employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
|
||||
if not employee_ids:
|
||||
pass # dpo something
|
||||
for employee_id in employee_ids:
|
||||
res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
|
||||
return res
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Update user form !-->
|
||||
<record id="view_users_form_mail" model="ir.ui.view">
|
||||
<field name="name">res.users.form.hr</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="mail.view_users_form_mail"/>
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<field name="display_groups_suggestions" position="after">
|
||||
<field name="display_employees_suggestions"/>
|
||||
</field>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -68,3 +68,8 @@
|
|||
margin: 2px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.openerp .oe_employee_vignette .oe_followers {
|
||||
width: auto;
|
||||
float: none;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
openerp.hr = function(session) {
|
||||
var _t = session.web._t;
|
||||
var QWeb = session.web.qweb;
|
||||
|
||||
var suggestions = session.suggestions;
|
||||
var removed_suggested_employee = session.suggestions.removed_suggested_employee = [];
|
||||
|
||||
suggestions.Employees = session.web.Widget.extend({
|
||||
events: {
|
||||
'click .oe_suggestion_remove.oe_suggestion_employee': 'stop_employee_suggestion',
|
||||
'click .oe_suggestion_remove_item.oe_suggestion_employee': 'remove_employee_suggestion',
|
||||
'click .oe_suggestion_follow': 'follow_employee',
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._super(this, arguments);
|
||||
this.hr_employee = new session.web.DataSetSearch(this, 'hr.employee');
|
||||
this.res_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
this.employees = [];
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
return this.fetch_suggested_employee();
|
||||
},
|
||||
|
||||
fetch_suggested_employee: function () {
|
||||
var self = this;
|
||||
var employee = self.hr_employee.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_employee}).then(function (res) {
|
||||
_(res).each(function (result) {
|
||||
result['image']=self.session.url('/web/binary/image', {model: 'hr.employee', field: 'image_small', id: result.id});
|
||||
});
|
||||
self.employees = res;
|
||||
});
|
||||
return $.when(employee).done(this.proxy('display_suggested_employees'));
|
||||
},
|
||||
|
||||
display_suggested_employees: function () {
|
||||
var suggested_employees = this.$('.oe_sidebar_suggestion.oe_suggestion_employee');
|
||||
if (suggested_employees) {
|
||||
suggested_employees.remove();
|
||||
}
|
||||
if (this.employees.length === 0) {
|
||||
return this.$el.empty();
|
||||
}
|
||||
return this.$el.empty().html(QWeb.render('hr.suggestions.employees', {'widget': this}));
|
||||
},
|
||||
|
||||
follow_employee: function (event) {
|
||||
var self = this;
|
||||
var employee_id = parseInt($(event.currentTarget).attr('id'), 10);
|
||||
return this.hr_employee.call('message_subscribe_users', [[employee_id], [this.session.uid], undefined]).then(function(res) {
|
||||
self.fetch_suggested_employee();
|
||||
});
|
||||
},
|
||||
|
||||
remove_employee_suggestion: function (event) {
|
||||
removed_suggested_employee.push($(event.currentTarget).attr('id'));
|
||||
return this.fetch_suggested_employee();
|
||||
},
|
||||
|
||||
stop_employee_suggestion: function (event) {
|
||||
var self = this;
|
||||
return this.res_users.call('stop_showing_employees_suggestions', [this.session.uid]).then(function(res) {
|
||||
self.$(".oe_sidebar_suggestion.oe_suggestion_employee").hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
session.mail.WallSidebar.include({
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
var sug_employees = new suggestions.Employees(this);
|
||||
return sug_employees.appendTo(this.$('.oe_suggestions_employees'));
|
||||
},
|
||||
});
|
||||
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!-- Employees placeholder in sidebar -->
|
||||
<t t-extend="mail.wall.sidebar">
|
||||
<t t-jquery=".oe_mail_wall_sidebar" t-operation="append">
|
||||
<div class="oe_suggestions_employees"></div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<!-- Suggested employees -->
|
||||
<div t-name="hr.suggestions.employees" class="oe_sidebar_suggestion oe_suggestion_employee">
|
||||
<div class="oe_suggest_title">
|
||||
<a class="oe_suggestion_remove oe_suggestion_employee oe_e">X</a>
|
||||
<h2>Suggested Employees</h2>
|
||||
</div>
|
||||
<div class="oe_suggest_items">
|
||||
<t t-foreach="widget.employees" t-as="result">
|
||||
<div class="oe_suggested_item">
|
||||
<div class="oe_suggested_item_image">
|
||||
<a t-attf-href="#model=hr.employee&id=#{result.id}">
|
||||
<img t-attf-src="{result.image}" t-attf-alt="{result.name}"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_suggested_item_content">
|
||||
<a class="oe_suggestion_item_name" t-attf-href="#model=hr.employee&id=#{result.id}"><t t-esc="result.name"/></a>
|
||||
<a class="oe_suggestion_remove_item oe_suggestion_employee oe_e" t-attf-id="{result.id}">X</a>
|
||||
<br/>
|
||||
<button class="oe_suggestion_follow" t-att-id="result.id">Follow</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
|
@ -46,7 +46,7 @@ class hr_attendance_error(osv.osv_memory):
|
|||
cr.execute("SELECT id FROM hr_attendance WHERE employee_id IN %s AND to_char(name,'YYYY-mm-dd')<=%s AND to_char(name,'YYYY-mm-dd')>=%s AND action IN %s ORDER BY name" ,(tuple(context['active_ids']), date_to, date_from, tuple(['sign_in','sign_out'])))
|
||||
attendance_ids = [x[0] for x in cr.fetchall()]
|
||||
if not attendance_ids:
|
||||
raise osv.except_osv(_('No Data Available !'), _('No records are found for your selection!'))
|
||||
raise osv.except_osv(_('No Data Available!'), _('No records are found for your selection!'))
|
||||
attendance_records = self.pool.get('hr.attendance').browse(cr, uid, attendance_ids, context=context)
|
||||
|
||||
for rec in attendance_records:
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
# Thai translation for openobject-addons
|
||||
# Copyright (c) 2013 Rosetta Contributors and Canonical Ltd 2013
|
||||
# This file is distributed under the same license as the openobject-addons package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
|
||||
"PO-Revision-Date: 2013-06-15 17:09+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Thai <th@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-06-16 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16667)\n"
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,wage:0
|
||||
msgid "Wage"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Information"
|
||||
msgstr "ข้อมูล"
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,trial_date_start:0
|
||||
msgid "Trial Start Date"
|
||||
msgstr "วันที่เริ่มต้นการทดลอง"
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,vehicle:0
|
||||
msgid "Company Vehicle"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Group By..."
|
||||
msgstr "จัดกลุ่มตาม..."
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,department_id:0
|
||||
msgid "Department"
|
||||
msgstr "แผนก"
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: field:hr.contract,employee_id:0
|
||||
#: model:ir.model,name:hr_contract.model_hr_employee
|
||||
msgid "Employee"
|
||||
msgstr "พนักงาน"
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Search Contract"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: view:hr.employee:0
|
||||
#: field:hr.employee,contract_ids:0
|
||||
#: model:ir.actions.act_window,name:hr_contract.act_hr_employee_2_hr_contract
|
||||
#: model:ir.actions.act_window,name:hr_contract.action_hr_contract
|
||||
#: model:ir.ui.menu,name:hr_contract.hr_menu_contract
|
||||
msgid "Contracts"
|
||||
msgstr "สัญญา"
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,children:0
|
||||
msgid "Number of Children"
|
||||
msgstr "จำนวนบุตร"
|
||||
|
||||
#. module: hr_contract
|
||||
#: help:hr.employee,contract_id:0
|
||||
msgid "Latest contract of the employee"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Job"
|
||||
msgstr "งาน"
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,advantages:0
|
||||
msgid "Advantages"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Work Permit"
|
||||
msgstr "ใบอนุญาตทำงาน"
|
||||
|
||||
#. module: hr_contract
|
||||
#: model:ir.actions.act_window,name:hr_contract.action_hr_contract_type
|
||||
#: model:ir.ui.menu,name:hr_contract.hr_menu_contract_type
|
||||
msgid "Contract Types"
|
||||
msgstr "ประเภทสัญญา"
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.employee:0
|
||||
msgid "Medical Exam"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,date_end:0
|
||||
msgid "End Date"
|
||||
msgstr "วันสิ้นสุด"
|
||||
|
||||
#. module: hr_contract
|
||||
#: help:hr.contract,wage:0
|
||||
msgid "Basic Salary of the employee"
|
||||
msgstr "เงินเดือนของพนักงาน"
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: field:hr.contract,name:0
|
||||
msgid "Contract Reference"
|
||||
msgstr "อ้างอิงตามสัญญา"
|
||||
|
||||
#. module: hr_contract
|
||||
#: help:hr.employee,vehicle_distance:0
|
||||
msgid "In kilometers"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: field:hr.contract,notes:0
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,permit_no:0
|
||||
msgid "Work Permit No"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: view:hr.employee:0
|
||||
#: field:hr.employee,contract_id:0
|
||||
#: model:ir.model,name:hr_contract.model_hr_contract
|
||||
#: model:ir.ui.menu,name:hr_contract.next_id_56
|
||||
msgid "Contract"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: field:hr.contract,type_id:0
|
||||
#: view:hr.contract.type:0
|
||||
#: field:hr.contract.type,name:0
|
||||
#: model:ir.model,name:hr_contract.model_hr_contract_type
|
||||
msgid "Contract Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
#: field:hr.contract,working_hours:0
|
||||
msgid "Working Schedule"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Salary and Advantages"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,job_id:0
|
||||
msgid "Job Title"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: constraint:hr.contract:0
|
||||
msgid "Error! Contract start-date must be less than contract end-date."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,manager:0
|
||||
msgid "Is a Manager"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,date_start:0
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,visa_no:0
|
||||
msgid "Visa No"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,vehicle_distance:0
|
||||
msgid "Home-Work Dist."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,place_of_birth:0
|
||||
msgid "Place of Birth"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Trial Period Duration"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract:0
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,visa_expire:0
|
||||
msgid "Visa Expire Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.employee,medic_exam:0
|
||||
msgid "Medical Examination Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: field:hr.contract,trial_date_end:0
|
||||
msgid "Trial End Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_contract
|
||||
#: view:hr.contract.type:0
|
||||
msgid "Search Contract Type"
|
||||
msgstr ""
|
|
@ -165,9 +165,14 @@
|
|||
</header>
|
||||
<sheet>
|
||||
<label for="employee_id" class="oe_edit_only"/>
|
||||
<h1><field name="employee_id" on_change="onchange_employee_id(employee_id)" class="oe_inline"/>, <field name="date" class="oe_inline"/></h1>
|
||||
<h1><field name="employee_id" class="oe_inline"
|
||||
attrs="{'readonly': [('state', '=', 'done')]}"
|
||||
on_change="onchange_employee_id(employee_id)"/>,
|
||||
<field name="date"
|
||||
attrs="{'readonly': [('state', '=', 'done')]}"/>
|
||||
</h1>
|
||||
<label for="plan_id" class="oe_edit_only"/>
|
||||
<h2><field name="plan_id"/></h2>
|
||||
<h2><field name="plan_id" attrs="{'readonly': [('state', '=', 'done')]}"/></h2>
|
||||
<group>
|
||||
<group colspan="4" attrs="{'invisible':['|', ('state','=','draft'), ('state', '=', 'wait')]}">
|
||||
<field name="rating" attrs="{'readonly':[('state','<>','progress')]}"/>
|
||||
|
@ -175,7 +180,7 @@
|
|||
</group>
|
||||
</group>
|
||||
<group string="Appraisal Forms" attrs="{'invisible':[('state','=','draft')]}">
|
||||
<field nolabel="1" name="survey_request_ids">
|
||||
<field nolabel="1" name="survey_request_ids" attrs="{'readonly': [('state', '=', 'done')]}">
|
||||
<form string="Interview Appraisal" version="7.0">
|
||||
<div class="oe_right oe_button_box">
|
||||
<button name="%(survey.action_view_survey_question_message)d" string="Answer Survey" type="action" states="waiting_answer" icon="gtk-execute" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response,'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}" attrs="{'readonly':[('survey_id','=',False)]}"/>
|
||||
|
|
|
@ -210,6 +210,11 @@
|
|||
<field name="context">{"default_hr_expense_ok":1}</field>
|
||||
<field name="domain">[('hr_expense_ok','=',True)]</field>
|
||||
<field name="search_view_id" ref="product.product_search_form_view"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new expense category.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_hr_product" name="Expense Categories" parent="hr.menu_hr_configuration" action="hr_expense_product"/>
|
||||
|
|
|
@ -146,6 +146,7 @@
|
|||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="manager_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="date_from" invisible="1"/>
|
||||
<!--field name="type"/-->
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
|
|
|
@ -49,7 +49,7 @@ class hr_payslip_employees(osv.osv_memory):
|
|||
to_date = run_data.get('date_end', False)
|
||||
credit_note = run_data.get('credit_note', False)
|
||||
if not data['employee_ids']:
|
||||
raise osv.except_osv(_("Warning !"), _("You must select employee(s) to generate payslip(s)."))
|
||||
raise osv.except_osv(_("Warning!"), _("You must select employee(s) to generate payslip(s)."))
|
||||
for emp in emp_pool.browse(cr, uid, data['employee_ids'], context=context):
|
||||
slip_data = slip_pool.onchange_employee_id(cr, uid, [], from_date, to_date, emp.id, contract_id=False, context=context)
|
||||
res = {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<group colspan="4">
|
||||
<field name="month"/>
|
||||
<field name="year"/>
|
||||
<field name="employee_id" colspan="3"/>
|
||||
<field name="employee_id" />
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Print" name="print_report" type="object" class="oe_highlight"/>
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
<menuitem action="action_hr_timesheet_employee"
|
||||
id="menu_hr_timesheet_employee"
|
||||
parent="hr.menu_hr_reporting"
|
||||
parent="hr.menu_hr_reporting_timesheet"
|
||||
sequence="2" icon="STOCK_PRINT"/>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -181,7 +181,7 @@ class account_analytic_line(osv.osv):
|
|||
for account in analytic_account_obj.browse(cr, uid, list(account_ids), context=context):
|
||||
partner = account.partner_id
|
||||
if (not partner) or not (account.pricelist_id):
|
||||
raise osv.except_osv(_('Analytic Account incomplete !'),
|
||||
raise osv.except_osv(_('Analytic Account Incomplete!'),
|
||||
_('Contract incomplete. Please fill in the Customer and Pricelist fields.'))
|
||||
|
||||
date_due = False
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<field name="name">timesheet.report.tree</field>
|
||||
<field name="model">timesheet.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="blue:state == 'draft';black:state in ('confirm','new');gray:state == 'cancel'" string="Timesheet">
|
||||
<tree colors="blue:state == 'draft';black:state in ('confirm','new');gray:state == 'cancel'" string="Timesheet" create="false">
|
||||
<field name="date" invisible="1"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
|
|
|
@ -3,7 +3,7 @@ access_hr_timesheet_sheet_sheet_user,hr_timesheet_sheet.sheet.user,model_hr_time
|
|||
access_hr_timesheet_sheet_sheet_system_employee,hr_timesheet_sheet.sheet.system.employee,model_hr_timesheet_sheet_sheet,base.group_user,1,1,1,0
|
||||
access_hr_timesheet_sheet_sheet_day,hr_timesheet_sheet.sheet.day,model_hr_timesheet_sheet_sheet_day,base.group_hr_user,1,1,1,1
|
||||
access_hr_timesheet_sheet_sheet_account,hr_timesheet_sheet.sheet.account,model_hr_timesheet_sheet_sheet_account,base.group_hr_user,1,1,1,1
|
||||
access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,1,1
|
||||
access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,0,0
|
||||
access_hr_analytic_timesheet_system_user,hr.analytic.timesheet.system.user,model_hr_analytic_timesheet,base.group_user,1,0,0,0
|
||||
access_hr_timesheet_sheet_sheet_day,hr.timesheet.sheet.sheet.day.user,model_hr_timesheet_sheet_sheet_day,base.group_user,1,1,1,0
|
||||
access_timesheet_report,timesheet.report,model_timesheet_report,base.group_hr_manager,1,1,1,1
|
||||
access_timesheet_report,timesheet.report,model_timesheet_report,base.group_hr_manager,1,1,0,0
|
||||
|
|
|
|
@ -190,8 +190,13 @@ openerp.hr_timesheet_sheet = function(instance) {
|
|||
$(this).val(self.sum_box(account, day_count, true));
|
||||
} else {
|
||||
account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
|
||||
self.display_totals();
|
||||
self.sync();
|
||||
var product = (account.days[day_count].lines[0].product_id instanceof Array) ? account.days[day_count].lines[0].product_id[0] : account.days[day_count].lines[0].product_id
|
||||
var journal = (account.days[day_count].lines[0].journal_id instanceof Array) ? account.days[day_count].lines[0].journal_id[0] : account.days[day_count].lines[0].journal_id
|
||||
new instance.web.Model("hr.analytic.timesheet").call("on_change_unit_amount", [[], product, account.days[day_count].lines[0].unit_amount, false, false, journal]).then(function(res) {
|
||||
account.days[day_count].lines[0]['amount'] = res.value.amount || 0;
|
||||
self.display_totals();
|
||||
self.sync();
|
||||
});
|
||||
if(!isNaN($(this).val())){
|
||||
$(this).val(self.sum_box(account, day_count, true));
|
||||
}
|
||||
|
@ -308,10 +313,10 @@ openerp.hr_timesheet_sheet = function(instance) {
|
|||
generate_o2m_value: function() {
|
||||
var self = this;
|
||||
var ops = [];
|
||||
|
||||
|
||||
_.each(self.accounts, function(account) {
|
||||
var auth_keys = _.extend(_.clone(account.account_defaults), {
|
||||
name: true, unit_amount: true, date: true, account_id:true,
|
||||
name: true, amount:true, unit_amount: true, date: true, account_id:true,
|
||||
});
|
||||
_.each(account.days, function(day) {
|
||||
_.each(day.lines, function(line) {
|
||||
|
|
|
@ -84,7 +84,7 @@ class l10n_be_vat_declaration(osv.osv_memory):
|
|||
obj_company = obj_user.browse(cr, uid, uid, context=context).company_id
|
||||
vat_no = obj_company.partner_id.vat
|
||||
if not vat_no:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No VAT number associated with your company.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No VAT number associated with your company.'))
|
||||
vat_no = vat_no.replace(' ','').upper()
|
||||
vat = vat_no[2:]
|
||||
|
||||
|
|
|
@ -60,12 +60,12 @@ class partner_vat(osv.osv_memory):
|
|||
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
|
||||
period_ids = obj_period.search(cr, uid, [('date_start' ,'>=', date_start), ('date_stop','<=',date_stop), ('company_id','=',company_id)])
|
||||
if not period_ids:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No data for the selected year.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No data for the selected year.'))
|
||||
|
||||
partners = []
|
||||
partner_ids = obj_partner.search(cr, uid, [('vat_subjected', '!=', False), ('vat','ilike','BE%')], context=context)
|
||||
if not partner_ids:
|
||||
raise osv.except_osv(_('Error'),_('No belgian contact with a VAT number in your database.'))
|
||||
raise osv.except_osv(_('Error'),_('No belgium contact with a VAT number in your database.'))
|
||||
cr.execute("""SELECT sub1.partner_id, sub1.name, sub1.vat, sub1.turnover, sub2.vat_amount
|
||||
FROM (SELECT l.partner_id, p.name, p.vat, SUM(CASE WHEN c.code ='49' THEN -l.tax_amount ELSE l.tax_amount END) as turnover
|
||||
FROM account_move_line l
|
||||
|
@ -90,7 +90,7 @@ class partner_vat(osv.osv_memory):
|
|||
partners.append(id_client)
|
||||
|
||||
if not partners:
|
||||
raise osv.except_osv(_('insufficient data!'), _('No data found for the selected year.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'), _('No data found for the selected year.'))
|
||||
context.update({'partner_ids': partners, 'year': data['year'], 'limit_amount': data['limit_amount']})
|
||||
model_data_ids = obj_model_data.search(cr, uid, [('model','=','ir.ui.view'), ('name','=','view_vat_listing')])
|
||||
resource_id = obj_model_data.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
|
||||
|
|
|
@ -108,7 +108,7 @@ class partner_vat_intra(osv.osv_memory):
|
|||
# Get Company vat
|
||||
company_vat = data_company.partner_id.vat
|
||||
if not company_vat:
|
||||
raise osv.except_osv(_('insufficient data!'),_('No VAT number associated with your company.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No VAT number associated with your company.'))
|
||||
company_vat = company_vat.replace(' ','').upper()
|
||||
issued_by = company_vat[:2]
|
||||
|
||||
|
@ -120,7 +120,7 @@ class partner_vat_intra(osv.osv_memory):
|
|||
|
||||
p_id_list = obj_partner.search(cr, uid, [('vat','!=',False)], context=context)
|
||||
if not p_id_list:
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number asociated with him.'))
|
||||
raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number associated with him.'))
|
||||
|
||||
seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum')
|
||||
dnum = company_vat[2:] + seq_declarantnum[-4:]
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
<para style="terp_default_9">[[ l['vat'] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_9">[[ l['code'] (l['intra_code']) ]]</para>
|
||||
<para style="terp_default_9">[[ l['code'] ]]([[ l['intra_code'] ]])</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Right_9">[[ formatLang(l['amount'], currency_obj=company.currency_id) ]]</para>
|
||||
|
|
|
@ -35,24 +35,24 @@
|
|||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_account_bank_statement_line_coda_tree" model="ir.ui.view">
|
||||
<record id="view_account_bank_statement_line_coda_tree" model="ir.ui.view">
|
||||
<field name="name">account.bank.statement.line.coda.tree</field>
|
||||
<field name="model">account.bank.statement.line</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="Statement lines">
|
||||
<field name="statement_id" readonly="1" invisible="1"/>
|
||||
<field name="sequence" readonly="1" invisible="1"/>
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="ref"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',parent.journal_id), ('company_id', '=', parent.company_id)]"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('company_id', '=', parent.company_id), ('type', '<>', 'view')]"/>
|
||||
<field name="amount"/>
|
||||
<field name="note"/>
|
||||
</tree>
|
||||
<tree editable="bottom" string="Statement lines" create="0">
|
||||
<field name="sequence" readonly="1" invisible="1"/>
|
||||
<field name="statement_id" readonly="1" />
|
||||
<field name="date"/>
|
||||
<field name="name"/>
|
||||
<field name="ref"/>
|
||||
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
|
||||
<field name="type" on_change="onchange_type(partner_id, type)"/>
|
||||
<field name="account_id" options='{"no_open":True}' domain="[('type', '<>', 'view')]"/>
|
||||
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type', '<>', 'view')]"/>
|
||||
<field name="amount"/>
|
||||
<field name="note"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ class payroll_advice(osv.osv):
|
|||
slip_ids = payslip_pool.search(cr, uid, [('date_from', '<=', advice.date), ('date_to', '>=', advice.date), ('state', '=', 'done')], context=context)
|
||||
for slip in payslip_pool.browse(cr, uid, slip_ids, context=context):
|
||||
if not slip.employee_id.bank_account_id and not slip.employee_id.bank_account_id.acc_number:
|
||||
raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
line_ids = payslip_line_pool.search(cr, uid, [ ('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context)
|
||||
if line_ids:
|
||||
line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0]
|
||||
|
@ -129,7 +129,7 @@ class payroll_advice(osv.osv):
|
|||
seq_obj = self.pool.get('ir.sequence')
|
||||
for advice in self.browse(cr, uid, ids, context=context):
|
||||
if not advice.line_ids:
|
||||
raise osv.except_osv(_('Error !'), _('You can not confirm Payment advice without advice lines.'))
|
||||
raise osv.except_osv(_('Error!'), _('You can not confirm Payment advice without advice lines.'))
|
||||
advice_date = datetime.strptime(advice.date, DATETIME_FORMAT)
|
||||
advice_year = advice_date.strftime('%m') + '-' + advice_date.strftime('%Y')
|
||||
number = seq_obj.get(cr, uid, 'payment.advice')
|
||||
|
@ -183,7 +183,7 @@ class hr_payslip_run(osv.osv):
|
|||
users = self.pool.get('res.users').browse(cr, uid, [uid], context=context)
|
||||
for run in self.browse(cr, uid, ids, context=context):
|
||||
if run.available_advice:
|
||||
raise osv.except_osv(_('Error !'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name))
|
||||
raise osv.except_osv(_('Error!'), _("Payment advice already exists for %s, 'Set to Draft' to create a new advice.") %(run.name))
|
||||
advice_data = {
|
||||
'batch_id': run.id,
|
||||
'company_id': users[0].company_id.id,
|
||||
|
@ -201,7 +201,7 @@ class hr_payslip_run(osv.osv):
|
|||
|
||||
for slip in payslip_pool.browse(cr, uid, slip_ids, context=context):
|
||||
if not slip.employee_id.bank_account_id or not slip.employee_id.bank_account_id.acc_number:
|
||||
raise osv.except_osv(_('Error !'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
raise osv.except_osv(_('Error!'), _('Please define bank account for the %s employee') % (slip.employee_id.name))
|
||||
line_ids = payslip_line_pool.search(cr, uid, [('slip_id', '=', slip.id), ('code', '=', 'NET')], context=context)
|
||||
if line_ids:
|
||||
line = payslip_line_pool.browse(cr, uid, line_ids, context=context)[0]
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,7 +64,7 @@ class report_custom(report_int):
|
|||
self.obj.render()
|
||||
return (self.obj.pdf, 'pdf')
|
||||
except Exception:
|
||||
raise osv.except_osv(_('pdf not created !'), _('Please check if package pdftk is installed!'))
|
||||
raise osv.except_osv(_('PDF Not Created!'), _('Please check if package pdftk is installed!'))
|
||||
|
||||
report_custom('report.l10n_lu.tax.report.print')
|
||||
|
||||
|
|
|
@ -87,10 +87,12 @@ Main Features
|
|||
'static/src/js/mail.js',
|
||||
'static/src/js/mail_followers.js',
|
||||
'static/src/js/many2many_tags_email.js',
|
||||
'static/src/js/suggestions.js',
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/mail.xml',
|
||||
'static/src/xml/mail_followers.xml',
|
||||
'static/src/xml/suggestions.xml',
|
||||
],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -150,11 +150,17 @@ class mail_notification(osv.Model):
|
|||
|
||||
return footer
|
||||
|
||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None):
|
||||
def _notify(self, cr, uid, msg_id, partners_to_notify=None, context=None,
|
||||
force_send=False, user_signature=True):
|
||||
""" Send by email the notification depending on the user preferences
|
||||
|
||||
:param list partners_to_notify: optional list of partner ids restricting
|
||||
the notifications to process
|
||||
:param bool force_send: if True, the generated mail.mail is
|
||||
immediately sent after being created, as if the scheduler
|
||||
was executed for this message only.
|
||||
:param bool user_signature: if True, the generated mail.mail body is
|
||||
the body of the related mail.message with the author's signature
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -189,8 +195,9 @@ class mail_notification(osv.Model):
|
|||
# add signature
|
||||
body_html = msg.body
|
||||
user_id = msg.author_id and msg.author_id.user_ids and msg.author_id.user_ids[0] and msg.author_id.user_ids[0].id or None
|
||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||
if user_signature:
|
||||
signature_company = self.get_signature_footer(cr, uid, user_id, res_model=msg.model, res_id=msg.res_id, context=context)
|
||||
body_html = tools.append_content_to_html(body_html, signature_company, plaintext=False, container_tag='div')
|
||||
|
||||
references = False
|
||||
if msg.parent_id:
|
||||
|
@ -203,13 +210,9 @@ class mail_notification(osv.Model):
|
|||
'recipient_ids': [(4, id) for id in notify_partner_ids],
|
||||
'references': references,
|
||||
}
|
||||
if msg.email_from:
|
||||
mail_values['email_from'] = msg.email_from
|
||||
if msg.reply_to:
|
||||
mail_values['reply_to'] = msg.reply_to
|
||||
mail_mail = self.pool.get('mail.mail')
|
||||
email_notif_id = mail_mail.create(cr, uid, mail_values, context=context)
|
||||
try:
|
||||
return mail_mail.send(cr, uid, [email_notif_id], context=context)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
if force_send:
|
||||
mail_mail.send(cr, uid, [email_notif_id], context=context)
|
||||
return True
|
||||
|
|
|
@ -66,11 +66,11 @@
|
|||
|
||||
<!-- Add followers related menu entries in Settings/Email -->
|
||||
<menuitem name="Followers" id="menu_email_followers" parent="base.menu_email"
|
||||
action="action_view_followers" sequence="30" groups="base.group_no_one"/> -->
|
||||
action="action_view_followers" sequence="30" groups="base.group_no_one"/>
|
||||
|
||||
<!-- Add notifications related menu entry in Settings/Email -->
|
||||
<menuitem name="Notifications" id="menu_email_notifications" parent="base.menu_email"
|
||||
action="action_view_notifications" sequence="35" groups="base.group_no_one"/>
|
||||
action="action_view_notifications" sequence="13" groups="base.group_no_one"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -208,3 +208,12 @@ class mail_group(osv.Model):
|
|||
""" Wrapper because message_unsubscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_unsubscribe_users(cr, uid, ids, context=context)
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Show the suggestion of groups if display_groups_suggestions if the
|
||||
user perference allows it."""
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
if not user.display_groups_suggestions:
|
||||
return []
|
||||
else:
|
||||
return super(mail_group, self).get_suggested_thread(cr, uid, removed_suggested_threads, context)
|
||||
|
|
|
@ -55,7 +55,6 @@ class mail_mail(osv.Model):
|
|||
'auto_delete': fields.boolean('Auto Delete',
|
||||
help="Permanently delete this email after sending it, to save space"),
|
||||
'references': fields.text('References', help='Message references, such as identifiers of previous messages', readonly=1),
|
||||
'email_from': fields.char('From', help='Message sender, taken from user preferences.'),
|
||||
'email_to': fields.text('To', help='Message recipients (emails)'),
|
||||
'recipient_ids': fields.many2many('res.partner', string='To (Partners)'),
|
||||
'email_cc': fields.char('Cc', help='Carbon copy message recipients'),
|
||||
|
@ -67,16 +66,13 @@ class mail_mail(osv.Model):
|
|||
}
|
||||
|
||||
def _get_default_from(self, cr, uid, context=None):
|
||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if this.alias_domain:
|
||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
||||
elif this.email:
|
||||
return '%s <%s>' % (this.name, this.email)
|
||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||
""" Kept for compatibility
|
||||
TDE TODO: remove me in 8.0
|
||||
"""
|
||||
return self.pool['mail.message']._get_default_from(cr, uid, context=context)
|
||||
|
||||
_defaults = {
|
||||
'state': 'outgoing',
|
||||
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
|
@ -93,19 +89,25 @@ class mail_mail(osv.Model):
|
|||
# if value specified: directly return it
|
||||
if values.get('reply_to'):
|
||||
return values.get('reply_to')
|
||||
format_name = True # whether to use a 'Followers of Pigs <pigs@openerp.com' format
|
||||
email_reply_to = None
|
||||
|
||||
mailgateway = True # tells whether the answer will go through the mailgateway, leading to the formatting of reply_to <Followers of ...>
|
||||
ir_config_parameter = self.pool.get("ir.config_parameter")
|
||||
catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
|
||||
|
||||
# model, res_id, email_from, reply_to: comes from values OR related message
|
||||
message = None
|
||||
# model, res_id, email_from: comes from values OR related message
|
||||
model, res_id, email_from = values.get('model'), values.get('res_id'), values.get('email_from')
|
||||
if values.get('mail_message_id'):
|
||||
message = self.pool.get('mail.message').browse(cr, uid, values.get('mail_message_id'), context=context)
|
||||
model = values.get('model', message and message.model or False)
|
||||
res_id = values.get('res_id', message and message.res_id or False)
|
||||
email_from = values.get('email_from', message and message.email_from or False)
|
||||
email_reply_to = message and message.reply_to or False
|
||||
if message.reply_to:
|
||||
email_reply_to = message.reply_to
|
||||
format_name = False
|
||||
if not model:
|
||||
model = message.model
|
||||
if not res_id:
|
||||
res_id = message.res_id
|
||||
if not email_from:
|
||||
email_from = message.email_from
|
||||
|
||||
# if model and res_id: try to use ``message_get_reply_to`` that returns the document alias
|
||||
if not email_reply_to and model and res_id and hasattr(self.pool[model], 'message_get_reply_to'):
|
||||
|
@ -115,16 +117,16 @@ class mail_mail(osv.Model):
|
|||
catchall_alias = ir_config_parameter.get_param(cr, uid, "mail.catchall.alias", context=context)
|
||||
if catchall_domain and catchall_alias:
|
||||
email_reply_to = '%s@%s' % (catchall_alias, catchall_domain)
|
||||
# no alias reply_to -> reply_to will be the email_from, only the email part
|
||||
|
||||
# still no reply_to -> reply_to will be the email_from
|
||||
if not email_reply_to and email_from:
|
||||
emails = tools.email_split(email_from)
|
||||
if emails:
|
||||
email_reply_to = emails[0]
|
||||
if emails[0].split('@')[1] != catchall_domain:
|
||||
mailgateway = False
|
||||
email_reply_to = email_from
|
||||
|
||||
# format 'Document name <email_address>'
|
||||
if email_reply_to and model and res_id and mailgateway:
|
||||
if email_reply_to and model and res_id and format_name:
|
||||
emails = tools.email_split(email_reply_to)
|
||||
if emails:
|
||||
email_reply_to = emails[0]
|
||||
document_name = self.pool[model].name_get(cr, SUPERUSER_ID, [res_id], context=context)[0]
|
||||
if document_name:
|
||||
# sanitize document name
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
<field name="res_model">mail.mail</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_outgoing': 1, 'search_default_type_email': 1}</field>
|
||||
<field name="context">{'search_default_outgoing': 1}</field>
|
||||
<field name="search_view_id" ref="view_mail_search"/>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -196,6 +196,14 @@ class mail_message(osv.Model):
|
|||
def _needaction_domain_get(self, cr, uid, context=None):
|
||||
return [('to_read', '=', True)]
|
||||
|
||||
def _get_default_from(self, cr, uid, context=None):
|
||||
this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if this.alias_domain:
|
||||
return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain)
|
||||
elif this.email:
|
||||
return '%s <%s>' % (this.name, this.email)
|
||||
raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias."))
|
||||
|
||||
def _get_default_author(self, cr, uid, context=None):
|
||||
return self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
|
||||
|
@ -204,7 +212,7 @@ class mail_message(osv.Model):
|
|||
'date': lambda *a: fields.datetime.now(),
|
||||
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
|
||||
'body': '',
|
||||
'email_from': lambda self, cr, uid, ctx=None: self.pool.get('mail.mail')._get_default_from(cr, uid, ctx),
|
||||
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
|
||||
}
|
||||
|
||||
#------------------------------------------------------
|
||||
|
@ -329,8 +337,10 @@ class mail_message(osv.Model):
|
|||
for key, message in message_tree.iteritems():
|
||||
if message.author_id:
|
||||
partner_ids |= set([message.author_id.id])
|
||||
if message.notified_partner_ids:
|
||||
if message.subtype_id and message.notified_partner_ids: # take notified people of message with a subtype
|
||||
partner_ids |= set([partner.id for partner in message.notified_partner_ids])
|
||||
elif not message.subtype_id and message.partner_ids: # take specified people of message without a subtype (log)
|
||||
partner_ids |= set([partner.id for partner in message.partner_ids])
|
||||
if message.attachment_ids:
|
||||
attachment_ids |= set([attachment.id for attachment in message.attachment_ids])
|
||||
# Read partners as SUPERUSER -> display the names like classic m2o even if no access
|
||||
|
@ -350,9 +360,12 @@ class mail_message(osv.Model):
|
|||
else:
|
||||
author = (0, message.email_from)
|
||||
partner_ids = []
|
||||
for partner in message.notified_partner_ids:
|
||||
if partner.id in partner_tree:
|
||||
partner_ids.append(partner_tree[partner.id])
|
||||
if message.subtype_id:
|
||||
partner_ids = [partner_tree[partner.id] for partner in message.notified_partner_ids
|
||||
if partner.id in partner_tree]
|
||||
else:
|
||||
partner_ids = [partner_tree[partner.id] for partner in message.partner_ids
|
||||
if partner.id in partner_tree]
|
||||
attachment_ids = []
|
||||
for attachment in message.attachment_ids:
|
||||
if attachment.id in attachments_tree:
|
||||
|
@ -766,7 +779,9 @@ class mail_message(osv.Model):
|
|||
elif not values.get('message_id'):
|
||||
values['message_id'] = tools.generate_tracking_message_id('private')
|
||||
newid = super(mail_message, self).create(cr, uid, values, context)
|
||||
self._notify(cr, uid, newid, context=context)
|
||||
self._notify(cr, uid, newid, context=context,
|
||||
force_send=context.get('mail_notify_force_send', True),
|
||||
user_signature=context.get('mail_notify_user_signature', True))
|
||||
# TDE FIXME: handle default_starred. Why not setting an inv on starred ?
|
||||
# Because starred will call set_message_starred, that looks for notifications.
|
||||
# When creating a new mail_message, it will create a notification to a message
|
||||
|
@ -880,20 +895,16 @@ class mail_message(osv.Model):
|
|||
return ''
|
||||
return result
|
||||
|
||||
def _notify(self, cr, uid, newid, context=None):
|
||||
def _notify(self, cr, uid, newid, context=None, force_send=False, user_signature=True):
|
||||
""" Add the related record followers to the destination partner_ids if is not a private message.
|
||||
Call mail_notification.notify to manage the email sending
|
||||
"""
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
message = self.browse(cr, uid, newid, context=context)
|
||||
|
||||
partners_to_notify = set([])
|
||||
# message has no subtype_id: pure log message -> no partners, no one notified
|
||||
if not message.subtype_id:
|
||||
return True
|
||||
|
||||
# all followers of the mail.message document have to be added as partners and notified
|
||||
if message.model and message.res_id:
|
||||
# all followers of the mail.message document have to be added as partners and notified if a subtype is defined (otherwise: log message)
|
||||
if message.subtype_id and message.model and message.res_id:
|
||||
fol_obj = self.pool.get("mail.followers")
|
||||
# browse as SUPERUSER because rules could restrict the search results
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||
|
@ -903,7 +914,7 @@ class mail_message(osv.Model):
|
|||
], context=context)
|
||||
partners_to_notify |= set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context))
|
||||
# remove me from notified partners, unless the message is written on my own wall
|
||||
if message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
||||
if message.subtype_id and message.author_id and message.model == "res.partner" and message.res_id == message.author_id.id:
|
||||
partners_to_notify |= set([message.author_id])
|
||||
elif message.author_id:
|
||||
partners_to_notify -= set([message.author_id])
|
||||
|
@ -914,7 +925,8 @@ class mail_message(osv.Model):
|
|||
|
||||
# notify
|
||||
if partners_to_notify:
|
||||
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context)
|
||||
notification_obj._notify(cr, uid, newid, partners_to_notify=[p.id for p in partners_to_notify], context=context,
|
||||
force_send=force_send, user_signature=user_signature)
|
||||
message.refresh()
|
||||
|
||||
# An error appear when a user receive a notification without notifying
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
<field name="subject"/>
|
||||
<field name="author_id"/>
|
||||
<field name="email_from"/>
|
||||
<field name="reply_to"/>
|
||||
<field name="date"/>
|
||||
<field name="type"/>
|
||||
<field name="subtype_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="model"/>
|
||||
|
@ -40,6 +40,7 @@
|
|||
<field name="parent_id"/>
|
||||
<field name="partner_ids" widget="many2many_tags"/>
|
||||
<field name="notified_partner_ids" widget="many2many_tags"/>
|
||||
<field name="subtype_id"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="body"/>
|
||||
|
|
|
@ -240,21 +240,42 @@ class mail_thread(osv.AbstractModel):
|
|||
fol_obj.create(cr, SUPERUSER_ID, {'res_model': self._name, 'res_id': id, 'partner_id': partner_id})
|
||||
|
||||
def _search_followers(self, cr, uid, obj, name, args, context):
|
||||
"""Search function for message_follower_ids
|
||||
|
||||
Do not use with operator 'not in'. Use instead message_is_followers
|
||||
"""
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
res = []
|
||||
for field, operator, value in args:
|
||||
assert field == name
|
||||
# TOFIX make it work with not in
|
||||
assert operator != "not in", "Do not search message_follower_ids with 'not in'"
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('partner_id', operator, value)])
|
||||
res_ids = [fol.res_id for fol in fol_obj.browse(cr, SUPERUSER_ID, fol_ids)]
|
||||
res.append(('id', 'in', res_ids))
|
||||
return res
|
||||
|
||||
def _search_is_follower(self, cr, uid, obj, name, args, context):
|
||||
"""Search function for message_is_follower"""
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
res = []
|
||||
for field, operator, value in args:
|
||||
assert field == name
|
||||
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
if (operator == '=' and value) or (operator == '!=' and not value): # is a follower
|
||||
res_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
|
||||
else: # is not a follower or unknown domain
|
||||
mail_ids = self.search(cr, uid, [('message_follower_ids', 'in', [partner_id])], context=context)
|
||||
res_ids = self.search(cr, uid, [('id', 'not in', mail_ids)], context=context)
|
||||
res.append(('id', 'in', res_ids))
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'message_is_follower': fields.function(_get_followers,
|
||||
type='boolean', string='Is a Follower', multi='_get_followers,'),
|
||||
'message_is_follower': fields.function(_get_followers, type='boolean',
|
||||
fnct_search=_search_is_follower, string='Is a Follower', multi='_get_followers,'),
|
||||
'message_follower_ids': fields.function(_get_followers, fnct_inv=_set_followers,
|
||||
fnct_search=_search_followers, type='many2many',
|
||||
obj='res.partner', string='Followers', multi='_get_followers'),
|
||||
fnct_search=_search_followers, type='many2many',
|
||||
obj='res.partner', string='Followers', multi='_get_followers'),
|
||||
'message_ids': fields.one2many('mail.message', 'res_id',
|
||||
domain=lambda self: [('model', '=', self._name)],
|
||||
auto_join=True,
|
||||
|
@ -559,7 +580,7 @@ class mail_thread(osv.AbstractModel):
|
|||
ret_dict = {}
|
||||
for model_name in self.pool.obj_list():
|
||||
model = self.pool[model_name]
|
||||
if 'mail.thread' in getattr(model, '_inherit', []):
|
||||
if hasattr(model, "message_process") and hasattr(model, "message_post"):
|
||||
ret_dict[model_name] = model._description
|
||||
return ret_dict
|
||||
|
||||
|
@ -794,6 +815,9 @@ class mail_thread(osv.AbstractModel):
|
|||
else:
|
||||
assert thread_id == 0, "Posting a message without model should be with a null res_id, to create a private message."
|
||||
model_pool = self.pool.get('mail.thread')
|
||||
if not hasattr(model_pool, 'message_post'):
|
||||
context['thread_model'] = model
|
||||
model_pool = self.pool['mail.thread']
|
||||
new_msg_id = model_pool.message_post(cr, uid, [thread_id], context=context, subtype='mail.mt_comment', **msg)
|
||||
|
||||
if partner_ids:
|
||||
|
@ -1128,7 +1152,7 @@ class mail_thread(osv.AbstractModel):
|
|||
model = False
|
||||
if thread_id:
|
||||
model = context.get('thread_model', self._name) if self._name == 'mail.thread' else self._name
|
||||
if model != self._name:
|
||||
if model != self._name and hasattr(self.pool[model], 'message_post'):
|
||||
del context['thread_model']
|
||||
return self.pool[model].message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, content_subtype=content_subtype, **kwargs)
|
||||
|
||||
|
@ -1287,7 +1311,10 @@ class mail_thread(osv.AbstractModel):
|
|||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
""" Add partners to the records followers. """
|
||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
mail_followers_obj = self.pool.get('mail.followers')
|
||||
subtype_obj = self.pool.get('mail.message.subtype')
|
||||
|
||||
user_pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
|
||||
if set(partner_ids) == set([user_pid]):
|
||||
try:
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
|
@ -1296,27 +1323,35 @@ class mail_thread(osv.AbstractModel):
|
|||
else:
|
||||
self.check_access_rights(cr, uid, 'write')
|
||||
|
||||
# subscribe partners
|
||||
self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
|
||||
for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
existing_pids = set([f.id for f in record.message_follower_ids
|
||||
if f.id in partner_ids])
|
||||
new_pids = set(partner_ids) - existing_pids
|
||||
|
||||
# subtype specified: update the subscriptions
|
||||
fol_obj = self.pool.get('mail.followers')
|
||||
if subtype_ids is not None:
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids), ('partner_id', 'in', partner_ids)], context=context)
|
||||
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||
# no subtypes: default ones for new subscription, do not update existing subscriptions
|
||||
else:
|
||||
# search new subscriptions: subtype_ids is False
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', ids),
|
||||
('partner_id', 'in', partner_ids),
|
||||
('subtype_ids', '=', False)
|
||||
], context=context)
|
||||
if fol_ids:
|
||||
subtype_obj = self.pool.get('mail.message.subtype')
|
||||
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
|
||||
fol_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||
# subtype_ids specified: update already subscribed partners
|
||||
if subtype_ids and existing_pids:
|
||||
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', self._name),
|
||||
('res_id', '=', record.id),
|
||||
('partner_id', 'in', list(existing_pids)),
|
||||
], context=context)
|
||||
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
|
||||
else:
|
||||
subtype_ids = subtype_obj.search(cr, uid, [
|
||||
('default', '=', True),
|
||||
'|',
|
||||
('res_model', '=', self._name),
|
||||
('res_model', '=', False)
|
||||
], context=context)
|
||||
# subscribe new followers
|
||||
for new_pid in new_pids:
|
||||
mail_followers_obj.create(cr, SUPERUSER_ID, {
|
||||
'res_model': self._name,
|
||||
'res_id': record.id,
|
||||
'partner_id': new_pid,
|
||||
'subtype_ids': [(6, 0, subtype_ids)],
|
||||
}, context=context)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -1454,4 +1489,33 @@ class mail_thread(osv.AbstractModel):
|
|||
''', (ids, self._name, partner_id))
|
||||
return True
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
#------------------------------------------------------
|
||||
# Thread suggestion
|
||||
#------------------------------------------------------
|
||||
|
||||
def get_suggested_thread(self, cr, uid, removed_suggested_threads=None, context=None):
|
||||
"""Return a list of suggested threads, sorted by the numbers of followers"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
# TDE HACK: originally by MAT from portal/mail_mail.py but not working until the inheritance graph bug is not solved in trunk
|
||||
# TDE FIXME: relocate in portal when it won't be necessary to reload the hr.employee model in an additional bridge module
|
||||
if self.pool['res.groups']._all_columns.get('is_portal'):
|
||||
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
|
||||
if any(group.is_portal for group in user.groups_id):
|
||||
return []
|
||||
|
||||
threads = []
|
||||
if removed_suggested_threads is None:
|
||||
removed_suggested_threads = []
|
||||
|
||||
thread_ids = self.search(cr, uid, [('id', 'not in', removed_suggested_threads), ('message_is_follower', '=', False)], context=context)
|
||||
for thread in self.browse(cr, uid, thread_ids, context=context):
|
||||
data = {
|
||||
'id': thread.id,
|
||||
'popularity': len(thread.message_follower_ids),
|
||||
'name': thread.name,
|
||||
'image_small': thread.image_small
|
||||
}
|
||||
threads.append(data)
|
||||
return sorted(threads, key=lambda x: (x['popularity'], x['id']), reverse=True)[:3]
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
],
|
||||
'view_mailbox': True,
|
||||
'view_inbox': True,
|
||||
'read_action': 'read'
|
||||
'read_action': 'read',
|
||||
'show_compose_message': False
|
||||
}""/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import fields, osv
|
||||
|
||||
|
@ -52,21 +53,4 @@ class res_partner_mail(osv.Model):
|
|||
self._message_add_suggested_recipient(cr, uid, recipients, partner, partner=partner, reason=_('Partner Profile'))
|
||||
return recipients
|
||||
|
||||
def message_post(self, cr, uid, thread_id, **kwargs):
|
||||
""" Override related to res.partner. In case of email message, set it as
|
||||
private:
|
||||
- add the target partner in the message partner_ids
|
||||
- set thread_id as None, because this will trigger the 'private'
|
||||
aspect of the message (model=False, res_id=False)
|
||||
"""
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
if kwargs.get('type') == 'email':
|
||||
partner_ids = kwargs.get('partner_ids', [])
|
||||
if thread_id not in [command[1] for command in partner_ids]:
|
||||
partner_ids.append((4, thread_id))
|
||||
kwargs['partner_ids'] = partner_ids
|
||||
thread_id = False
|
||||
return super(res_partner_mail, self).message_post(cr, uid, thread_id, **kwargs)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -28,6 +28,7 @@ class res_users(osv.Model):
|
|||
- add a preference about sending emails about notifications
|
||||
- make a new user follow itself
|
||||
- add a welcome message
|
||||
- add suggestion preference
|
||||
"""
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users']
|
||||
|
@ -37,10 +38,12 @@ class res_users(osv.Model):
|
|||
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
|
||||
help="Email address internally associated with this user. Incoming "\
|
||||
"emails will appear in the user's notifications."),
|
||||
'display_groups_suggestions': fields.boolean("Display Groups Suggestions"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'alias_domain': False, # always hide alias during creation
|
||||
'display_groups_suggestions': True,
|
||||
}
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
|
@ -51,10 +54,10 @@ class res_users(osv.Model):
|
|||
init_res = super(res_users, self).__init__(pool, cr)
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
|
||||
self.SELF_WRITEABLE_FIELDS.append('notification_email_send')
|
||||
self.SELF_WRITEABLE_FIELDS.extend(['notification_email_send', 'display_groups_suggestions'])
|
||||
# duplicate list to avoid modifying the original reference
|
||||
self.SELF_READABLE_FIELDS = list(self.SELF_READABLE_FIELDS)
|
||||
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name'])
|
||||
self.SELF_READABLE_FIELDS.extend(['notification_email_send', 'alias_domain', 'alias_name', 'display_groups_suggestions'])
|
||||
return init_res
|
||||
|
||||
def _auto_init(self, cr, context=None):
|
||||
|
@ -109,7 +112,7 @@ class res_users(osv.Model):
|
|||
def _message_post_get_pid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'res.partner'
|
||||
context['thread_model'] = 'res.users'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
return self.browse(cr, SUPERUSER_ID, thread_id).partner_id.id
|
||||
|
@ -118,44 +121,32 @@ class res_users(osv.Model):
|
|||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
partner_ids = kwargs.get('partner_ids', [])
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post(cr, uid, partner_id, context=context, **kwargs)
|
||||
if partner_id not in [command[1] for command in partner_ids]:
|
||||
partner_ids.append(partner_id)
|
||||
kwargs['partner_ids'] = partner_ids
|
||||
return self.pool.get('mail.thread').message_post(cr, uid, False, **kwargs)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
|
||||
for id in ids:
|
||||
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
|
||||
self.pool.get('res.partner').message_update(cr, uid, [partner_id], msg_dict, update_vals=update_vals, context=context)
|
||||
return True
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
for id in ids:
|
||||
partner_id = self.browse(cr, SUPERUSER_ID, id).partner_id.id
|
||||
self.pool.get('res.partner').message_subscribe(cr, uid, [partner_id], partner_ids, subtype_ids=subtype_ids, context=context)
|
||||
return True
|
||||
|
||||
def message_get_partner_info_from_emails(self, cr, uid, emails, link_mail=False, context=None):
|
||||
return self.pool.get('res.partner').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
|
||||
return self.pool.get('mail.thread').message_get_partner_info_from_emails(cr, uid, emails, link_mail=link_mail, context=context)
|
||||
|
||||
def message_get_suggested_recipients(self, cr, uid, ids, context=None):
|
||||
partner_ids = []
|
||||
for id in ids:
|
||||
partner_ids.append(self.browse(cr, SUPERUSER_ID, id).partner_id.id)
|
||||
return self.pool.get('res.partner').message_get_suggested_recipients(cr, uid, partner_ids, context=context)
|
||||
return dict.fromkeys(ids, list())
|
||||
|
||||
#------------------------------------------------------
|
||||
# Compatibility methods: do not use
|
||||
# TDE TODO: remove me in 8.0
|
||||
#------------------------------------------------------
|
||||
|
||||
def message_post_user_api(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, context=context, **kwargs)
|
||||
|
||||
def message_create_partners_from_emails(self, cr, uid, emails, context=None):
|
||||
return self.pool.get('res.partner').message_create_partners_from_emails(cr, uid, emails, context=context)
|
||||
def stop_showing_groups_suggestions(self, cr, uid, user_id, context=None):
|
||||
"""Update display_groups_suggestions value to False"""
|
||||
if context is None:
|
||||
context = {}
|
||||
self.write(cr, uid, user_id, {"display_groups_suggestions": False}, context)
|
||||
|
||||
|
||||
class res_users_mail_group(osv.Model):
|
||||
|
|
|
@ -30,6 +30,12 @@
|
|||
<field name="alias_domain" invisible="1"/>
|
||||
<field name="alias_id" readonly="1" required="0" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
|
||||
</field>
|
||||
<group string="Email preferences" position="after">
|
||||
<group name="misc" string="Miscellaneous"
|
||||
groups="base.group_no_one">
|
||||
<field name="display_groups_suggestions"/>
|
||||
</group>
|
||||
</group>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0px;
|
||||
margin: 0px
|
||||
margin: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
|
@ -665,8 +665,72 @@
|
|||
.openerp .oe_mail_wall .oe_mail{
|
||||
margin: 16px;
|
||||
width: 600px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.openerp .oe_mail .oe_view_nocontent > p {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* ------------- WALL SIDEBAR ------------- */
|
||||
|
||||
.openerp .oe_mail_wall .oe_mail_wall_aside {
|
||||
margin: 16px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 260px;
|
||||
}
|
||||
.openerp .oe_mail_wall_aside .oe_sidebar_suggestion {
|
||||
background-color: #EDEDF6;
|
||||
border-radius: 2px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title h2 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
padding: 0px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item {
|
||||
border-radius: 2px;
|
||||
width: 100%;
|
||||
margin-left: 10px;
|
||||
min-height: 67px; /* image_small 66x66px */
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image {
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_image img {
|
||||
border-radius: 2px;
|
||||
border: solid 1px rgba(0,0,0,0.03);
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content button {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_item_name {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 90%;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title a.oe_suggestion_remove {
|
||||
line-height: 15px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
visibility: hidden;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items .oe_suggested_item_content a.oe_suggestion_remove_item {
|
||||
line-height: 15px;
|
||||
margin-top: -2px;
|
||||
float: right;
|
||||
visibility: hidden;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_title:hover a.oe_suggestion_remove,
|
||||
.openerp .oe_sidebar_suggestion .oe_suggest_items:hover a.oe_suggestion_remove_item {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
text-align: center;
|
||||
overflow: hidden;
|
||||
-moz-border-radius: 3px;
|
||||
border-collapse: separate;
|
||||
-webkit-border-radius: 3px;
|
||||
-o-border-radius: 3px;
|
||||
-ms-border-radius: 3px;
|
||||
|
|
|
@ -4,8 +4,8 @@ openerp.mail = function (session) {
|
|||
|
||||
var mail = session.mail = {};
|
||||
|
||||
openerp_mail_followers(session, mail); // import mail_followers.js
|
||||
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
|
||||
openerp_mail_followers(session, mail); // import mail_followers.js
|
||||
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
|
@ -237,8 +237,15 @@ openerp.mail = function (session) {
|
|||
|
||||
this.format_data();
|
||||
|
||||
// update record_name: Partner profile
|
||||
if (this.model == 'res.partner') {
|
||||
this.record_name = 'Partner Profile of ' + this.record_name;
|
||||
}
|
||||
else if (this.model == 'hr.employee') {
|
||||
this.record_name = 'News from ' + this.record_name;
|
||||
}
|
||||
// record options and data
|
||||
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level && this.model != 'res.partner';
|
||||
this.show_record_name = this.options.show_record_name && this.record_name && !this.thread_level;
|
||||
this.options.show_read = false;
|
||||
this.options.show_unread = false;
|
||||
if (this.options.show_read_unread_button) {
|
||||
|
@ -257,8 +264,10 @@ openerp.mail = function (session) {
|
|||
|
||||
/* Convert date, timerelative and avatar in displayable data. */
|
||||
format_data: function () {
|
||||
|
||||
//formating and add some fields for render
|
||||
this.date = this.date ? session.web.str_to_datetime(this.date) : false;
|
||||
this.display_date = this.date.toString('ddd MMM dd yyyy HH:mm');
|
||||
if (this.date && new Date().getTime()-this.date.getTime() < 7*24*60*60*1000) {
|
||||
this.timerelative = $.timeago(this.date);
|
||||
}
|
||||
|
@ -745,7 +754,7 @@ openerp.mail = function (session) {
|
|||
}
|
||||
// create object and attach to the thread object
|
||||
thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
|
||||
var message = thread.create_message_object( data[0] );
|
||||
var message = thread.create_message_object( data.slice(-1)[0] );
|
||||
// insert the message on dom
|
||||
thread.insert_message( message, root ? undefined : self.$el, root );
|
||||
});
|
||||
|
@ -978,8 +987,8 @@ openerp.mail = function (session) {
|
|||
expender: function () {
|
||||
this.$('.oe_msg_body:first').expander({
|
||||
slicePoint: this.options.truncate_limit,
|
||||
expandText: 'read more',
|
||||
userCollapseText: 'read less',
|
||||
expandText: _t('read more'),
|
||||
userCollapseText: _t('read less'),
|
||||
detailClass: 'oe_msg_tail',
|
||||
moreClass: 'oe_mail_expand',
|
||||
lessClass: 'oe_mail_reduce',
|
||||
|
@ -1840,6 +1849,19 @@ openerp.mail = function (session) {
|
|||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Aside Widget
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* This widget handles the display of a sidebar on the Wall. Its main use
|
||||
* is to display group and employees suggestion (if hr is installed).
|
||||
*/
|
||||
mail.WallSidebar = session.web.Widget.extend({
|
||||
template: 'mail.wall.sidebar',
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Wall Widget
|
||||
|
@ -1901,6 +1923,9 @@ openerp.mail = function (session) {
|
|||
if (! this.searchview.has_defaults) {
|
||||
this.message_render();
|
||||
}
|
||||
// render sidebar
|
||||
var wall_sidebar = new mail.WallSidebar(this);
|
||||
wall_sidebar.appendTo(this.$el.find('.oe_mail_wall_aside'));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2018,4 +2043,16 @@ openerp.mail = function (session) {
|
|||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* Sub-widgets loading
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* Load here widgets that could depend on widgets defined in mail.js
|
||||
*/
|
||||
|
||||
openerp.mail.suggestions(session, mail); // import suggestion.js (suggestion widget)
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
openerp.mail.suggestions = function(session, mail) {
|
||||
var _t = session.web._t;
|
||||
var QWeb = session.web.qweb;
|
||||
|
||||
var suggestions = session.suggestions = {};
|
||||
var removed_suggested_group = session.suggestions.removed_suggested_group = [];
|
||||
|
||||
suggestions.Groups = session.web.Widget.extend({
|
||||
events: {
|
||||
'click .oe_suggestion_remove.oe_suggestion_group': 'stop_group_suggestion',
|
||||
'click .oe_suggestion_remove_item.oe_suggestion_group': 'remove_group_suggestion',
|
||||
'click .oe_suggestion_join': 'join_group',
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this._super.apply(this, arguments);
|
||||
this.mail_group = new session.web.DataSetSearch(this, 'mail.group');
|
||||
this.res_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
this.groups = [];
|
||||
},
|
||||
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
return this.fetch_suggested_groups();
|
||||
},
|
||||
|
||||
fetch_suggested_groups: function () {
|
||||
var self = this;
|
||||
var group = self.mail_group.call('get_suggested_thread', {'removed_suggested_threads': removed_suggested_group}).then(function (res) {
|
||||
_(res).each(function (result) {
|
||||
result['image']=self.session.url('/web/binary/image', {model: 'mail.group', field: 'image_small', id: result.id});
|
||||
});
|
||||
self.groups = res;
|
||||
});
|
||||
return $.when(group).then(this.proxy('display_suggested_groups'));
|
||||
},
|
||||
|
||||
display_suggested_groups: function () {
|
||||
var suggested_groups = this.$('.oe_sidebar_suggestion.oe_suggestion_group');
|
||||
if (suggested_groups) {
|
||||
suggested_groups.empty();
|
||||
}
|
||||
if (this.groups.length === 0) {
|
||||
return this.$el.empty();
|
||||
}
|
||||
return this.$el.empty().html(QWeb.render('mail.suggestions.groups', {'widget': this}));
|
||||
},
|
||||
|
||||
join_group: function (event) {
|
||||
var self = this;
|
||||
return this.mail_group.call('message_subscribe_users', [[$(event.currentTarget).attr('id')],[this.session.uid]]).then(function(res) {
|
||||
self.fetch_suggested_groups();
|
||||
});
|
||||
},
|
||||
|
||||
remove_group_suggestion: function (event) {
|
||||
removed_suggested_group.push($(event.currentTarget).attr('id'));
|
||||
return this.fetch_suggested_groups();
|
||||
},
|
||||
|
||||
stop_group_suggestion: function (event) {
|
||||
var self = this;
|
||||
return this.res_users.call('stop_showing_groups_suggestions', [this.session.uid]).then(function(res) {
|
||||
self.$(".oe_sidebar_suggestion.oe_suggestion_group").hide();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
session.mail.WallSidebar.include({
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
var sug_groups = new suggestions.Groups(this);
|
||||
return sug_groups.appendTo(this.$('.oe_suggestions_groups'));
|
||||
},
|
||||
});
|
||||
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue