[MERGE] Sync with trunk

bzr revid: tde@openerp.com-20130429102102-y732cl7t6g1g163v
This commit is contained in:
Thibault Delavallée 2013-04-29 12:21:02 +02:00
commit 9180fbd76a
162 changed files with 19435 additions and 1377 deletions

View File

@ -1001,8 +1001,7 @@ class account_period(osv.osv):
def find(self, cr, uid, dt=None, context=None):
if context is None: context = {}
if not dt:
dt = fields.date.context_today(self,cr,uid,context=context)
#CHECKME: shouldn't we check the state of the period?
dt = fields.date.context_today(self, cr, uid, context=context)
args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)]
if context.get('company_id', False):
args.append(('company_id', '=', context['company_id']))
@ -1010,7 +1009,7 @@ class account_period(osv.osv):
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
args.append(('company_id', '=', company_id))
result = []
if context.get('account_period_prefer_normal'):
if context.get('account_period_prefer_normal', True):
# look for non-special periods first, and fallback to all if no result is found
result = self.search(cr, uid, args + [('special', '=', False)], context=context)
if not result:
@ -1214,7 +1213,7 @@ class account_move(osv.osv):
return res
def _get_period(self, cr, uid, context=None):
ctx = dict(context or {}, account_period_prefer_normal=True)
ctx = dict(context or {})
period_ids = self.pool.get('account.period').find(cr, uid, context=ctx)
return period_ids[0]
@ -1786,7 +1785,7 @@ class account_tax_code(osv.osv):
if context.get('period_id', False):
period_id = context['period_id']
else:
period_id = self.pool.get('account.period').find(cr, uid)
period_id = self.pool.get('account.period').find(cr, uid, context=context)
if not period_id:
return dict.fromkeys(ids, 0.0)
period_id = period_id[0]

View File

@ -61,7 +61,7 @@ class account_bank_statement(osv.osv):
return res
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid,context=context)
periods = self.pool.get('account.period').find(cr, uid, context=context)
if periods:
return periods[0]
return False

View File

@ -286,7 +286,10 @@ class account_invoice(osv.osv):
'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True, track_visibility='onchange', states={'draft':[('readonly',False)]}),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]}),
'commercial_partner_id': fields.related('partner_id', 'commercial_partner_id', string='Commercial Entity', type='many2one',
relation='res.partner', store=True, readonly=True,
help="The commercial entity that will be used on Journal Entries for this invoice")
}
_defaults = {
'type': _get_type,
@ -985,8 +988,7 @@ class account_invoice(osv.osv):
'narration':inv.comment
}
period_id = inv.period_id and inv.period_id.id or False
ctx.update(company_id=inv.company_id.id,
account_period_prefer_normal=True)
ctx.update(company_id=inv.company_id.id)
if not period_id:
period_ids = period_obj.find(cr, uid, inv.date_invoice, context=ctx)
period_id = period_ids and period_ids[0] or False
@ -1262,9 +1264,7 @@ class account_invoice(osv.osv):
ref = invoice.reference
else:
ref = self._convert_ref(cr, uid, invoice.number)
partner = invoice.partner_id
if partner.parent_id and not partner.is_company:
partner = partner.parent_id
partner = self.pool['res.partner']._find_accounting_partner(invoice.partner_id)
# Pay attention to the sign for both debit/credit AND amount_currency
l1 = {
'debit': direction * pay_amount>0 and direction * pay_amount,
@ -1734,15 +1734,11 @@ class res_partner(osv.osv):
'invoice_ids': fields.one2many('account.invoice.line', 'partner_id', 'Invoices', readonly=True),
}
def _find_accounting_partner(self, part):
def _find_accounting_partner(self, partner):
'''
Find the partner for which the accounting entries will be created
'''
#if the chosen partner is not a company and has a parent company, use the parent for the journal entries
#because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait'
if part.parent_id and not part.is_company:
part = part.parent_id
return part
return partner.commercial_partner_id
def copy(self, cr, uid, id, default=None, context=None):
default = default or {}

View File

@ -117,6 +117,7 @@
<field name="arch" type="xml">
<tree colors="blue:state == 'draft';black:state in ('proforma','proforma2','open');gray:state == 'cancel'" string="Invoice">
<field name="partner_id" groups="base.group_user"/>
<field name="commercial_partner_id" invisible="1"/>
<field name="date_invoice"/>
<field name="number"/>
<field name="reference" invisible="1"/>
@ -320,7 +321,8 @@
<field string="Customer" name="partner_id"
on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id)"
groups="base.group_user" context="{'search_default_customer':1, 'show_address': 1}"
options='{"always_reload": True}'/>
options='{"always_reload": True}'
domain="[('customer', '=', True)]"/>
<field name="fiscal_position" widget="selection" />
</group>
<group>
@ -447,19 +449,20 @@
<field name="model">account.invoice</field>
<field name="arch" type="xml">
<search string="Search Invoice">
<field name="number" string="Invoice" filter_domain="['|','|','|', ('number','ilike',self), ('origin','ilike',self), ('supplier_invoice_number', 'ilike', self), ('partner_id', 'ilike', self)]"/>
<field name="number" string="Invoice" filter_domain="['|','|','|', ('number','ilike',self), ('origin','ilike',self), ('supplier_invoice_number', 'ilike', self), ('partner_id', 'child_of', self)]"/>
<filter name="draft" string="Draft" domain="[('state','=','draft')]" help="Draft Invoices"/>
<filter name="proforma" string="Proforma" domain="[('state','=','proforma2')]" help="Proforma Invoices" groups="account.group_proforma_invoices"/>
<filter name="invoices" string="Invoices" domain="[('state','not in',['draft','cancel'])]" help="Proforma/Open/Paid Invoices"/>
<filter name="unpaid" string="Unpaid" domain="[('state','=','open')]" help="Unpaid Invoices"/>
<separator/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="user_id" string="Salesperson"/>
<field name="period_id" string="Period"/>
<separator/>
<filter domain="[('user_id','=',uid)]" help="My Invoices"/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter name="partner_id" string="Partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter name="commercial_partner_id" string="Commercial Partner" domain="[]" context="{'group_by':'commercial_partner_id'}"/>
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Journal" icon="terp-folder-orange" domain="[]" context="{'group_by':'journal_id'}"/>
<filter string="Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
@ -622,8 +625,6 @@
</record>
<menuitem action="action_invoice_tree4" id="menu_action_invoice_tree4" parent="menu_finance_payables"/>
<act_window context="{'search_default_partner_id':[active_id], 'default_partner_id': active_id}" id="act_res_partner_2_account_invoice_opened" name="Invoices" res_model="account.invoice" src_model="res.partner"/>
<act_window
id="act_account_journal_2_account_invoice_opened"
name="Unpaid Invoices"

View File

@ -559,10 +559,11 @@ class account_move_line(osv.osv):
]
def _auto_init(self, cr, context=None):
super(account_move_line, self)._auto_init(cr, context=context)
res = super(account_move_line, self)._auto_init(cr, context=context)
cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = \'account_move_line_journal_id_period_id_index\'')
if not cr.fetchone():
cr.execute('CREATE INDEX account_move_line_journal_id_period_id_index ON account_move_line (journal_id, period_id)')
return res
def _check_no_view(self, cr, uid, ids, context=None):
lines = self.browse(cr, uid, ids, context=context)
@ -654,13 +655,7 @@ class account_move_line(osv.osv):
}
return result
def onchange_account_id(self, cr, uid, ids, account_id, context=None):
res = {'value': {}}
if account_id:
res['value']['account_tax_id'] = [x.id for x in self.pool.get('account.account').browse(cr, uid, account_id, context=context).tax_ids]
return res
def onchange_partner_id(self, cr, uid, ids, move_id, partner_id, account_id=None, debit=0, credit=0, date=False, journal=False):
def onchange_partner_id(self, cr, uid, ids, move_id, partner_id, account_id=None, debit=0, credit=0, date=False, journal=False, context=None):
partner_obj = self.pool.get('res.partner')
payment_term_obj = self.pool.get('account.payment.term')
journal_obj = self.pool.get('account.journal')
@ -674,8 +669,8 @@ class account_move_line(osv.osv):
date = datetime.now().strftime('%Y-%m-%d')
jt = False
if journal:
jt = journal_obj.browse(cr, uid, journal).type
part = partner_obj.browse(cr, uid, partner_id)
jt = journal_obj.browse(cr, uid, journal, context=context).type
part = partner_obj.browse(cr, uid, partner_id, context=context)
payment_term_id = False
if jt and jt in ('purchase', 'purchase_refund') and part.property_supplier_payment_term:
@ -700,20 +695,20 @@ class account_move_line(osv.osv):
elif part.supplier:
val['account_id'] = fiscal_pos_obj.map_account(cr, uid, part and part.property_account_position or False, id1)
if val.get('account_id', False):
d = self.onchange_account_id(cr, uid, ids, val['account_id'])
d = self.onchange_account_id(cr, uid, ids, account_id=val['account_id'], partner_id=part.id, context=context)
val.update(d['value'])
return {'value':val}
def onchange_account_id(self, cr, uid, ids, account_id=False, partner_id=False):
def onchange_account_id(self, cr, uid, ids, account_id=False, partner_id=False, context=None):
account_obj = self.pool.get('account.account')
partner_obj = self.pool.get('res.partner')
fiscal_pos_obj = self.pool.get('account.fiscal.position')
val = {}
if account_id:
res = account_obj.browse(cr, uid, account_id)
res = account_obj.browse(cr, uid, account_id, context=context)
tax_ids = res.tax_ids
if tax_ids and partner_id:
part = partner_obj.browse(cr, uid, partner_id)
part = partner_obj.browse(cr, uid, partner_id, context=context)
tax_id = fiscal_pos_obj.map_tax(cr, uid, part and part.property_account_position or False, tax_ids)[0]
else:
tax_id = tax_ids and tax_ids[0].id or False
@ -985,8 +980,7 @@ class account_move_line(osv.osv):
if context is None:
context = {}
period_pool = self.pool.get('account.period')
ctx = dict(context, account_period_prefer_normal=True)
pids = period_pool.find(cr, user, date, context=ctx)
pids = period_pool.find(cr, user, date, context=context)
if pids:
res.update({
'period_id':pids[0]

View File

@ -1112,7 +1112,7 @@
<field name="ref"/>
<field name="statement_id" invisible="1"/>
<field name="partner_id" on_change="onchange_partner_id(move_id, partner_id, account_id, debit, credit, date, journal_id)"/>
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',journal_id), ('company_id', '=', company_id)]" on_change="onchange_account_id(account_id)"/>
<field name="account_id" options='{"no_open":True}' domain="[('journal_id','=',journal_id), ('company_id', '=', company_id)]" on_change="onchange_account_id(account_id, partner_id, context)"/>
<field name="account_tax_id" options='{"no_open":True}' invisible="context.get('journal_type', False) not in ['sale','sale_refund','purchase','purchase_refund','general']"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" domain="[('type','not in',['view','template'])]" invisible="not context.get('analytic_journal_id',False)"/>
<field name="move_id" required="0"/>
@ -1194,7 +1194,12 @@
sequence="1"
groups="group_account_user"
/>
<record id="action_account_moves_all_tree" model="ir.actions.act_window">
<field name="name">Journal Items</field>
<field name="res_model">account.move.line</field>
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id}</field>
<field name="view_id" ref="view_move_line_tree"/>
</record>
<record id="view_move_line_tree_reconcile" model="ir.ui.view">
<field name="model">account.move.line</field>
<field eval="24" name="priority"/>
@ -1288,7 +1293,7 @@
<group col="6" colspan="4">
<field name="name"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(False,partner_id,account_id,debit,credit,date)"/>
<field name="partner_id" on_change="onchange_partner_id(False, partner_id, account_id, debit, credit, date, journal_id, context)"/>
<field name="journal_id"/>
<field name="period_id"/>
@ -1352,7 +1357,7 @@
<tree colors="blue:state == 'draft';black:state == 'posted'" editable="top" string="Journal Items">
<field name="invoice"/>
<field name="name"/>
<field name="partner_id" on_change="onchange_partner_id(False,partner_id,account_id,debit,credit,parent.date,parent.journal_id)"/>
<field name="partner_id" on_change="onchange_partner_id(False, partner_id, account_id, debit, credit, parent.date, parent.journal_id, context)"/>
<field name="account_id" domain="[('journal_id','=',parent.journal_id),('company_id', '=', parent.company_id)]"/>
<field name="date_maturity"/>
<field name="debit" sum="Total Debit"/>
@ -1771,23 +1776,6 @@
</field>
</record>
<!-- res.partner links -->
<act_window
context="{'search_default_unreconciled':True, 'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
domain="[('account_id.reconcile', '=', True),('account_id.type', 'in', ['receivable', 'payable'])]"
id="act_account_partner_account_move_all"
name="Receivables &amp; Payables"
res_model="account.move.line"
src_model="res.partner"/>
<act_window
context="{'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
id="act_account_partner_account_move"
name="Journal Items"
res_model="account.move.line"
src_model="res.partner"
groups="account.group_account_user"/>
<!-- Account Templates -->
<menuitem
id="account_template_folder"

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n"
"X-Generator: Launchpad (build 16564)\n"
"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n"
"X-Generator: Launchpad (build 16567)\n"
"Language: nl\n"
#. module: account

View File

@ -7,15 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-12-22 23:17+0000\n"
"Last-Translator: Fábio Martinelli - http://zupy.com.br "
"<webmaster@guaru.net>\n"
"PO-Revision-Date: 2013-04-18 17:44+0000\n"
"Last-Translator: Thiago Tognoli <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:19+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-04-19 05:24+0000\n"
"X-Generator: Launchpad (build 16567)\n"
#. module: account
#: model:process.transition,name:account.process_transition_supplierreconcilepaid0
@ -431,7 +430,7 @@ msgstr "Data de criação"
#. module: account
#: selection:account.journal,type:0
msgid "Purchase Refund"
msgstr "Devolução da Venda"
msgstr "Devolução de Compra"
#. module: account
#: selection:account.journal,type:0
@ -12678,13 +12677,6 @@ msgstr ""
#~ msgid "This period is already closed !"
#~ msgstr "Este período já está fechado"
#, python-format
#~ msgid ""
#~ "Selected Move lines does not have any account move enties in draft state"
#~ msgstr ""
#~ "As linhas do movimento selecionado nao tem nenhuma conta a ser movida para o "
#~ "estado de esboço"
#~ msgid "Unpaid Customer Refunds"
#~ msgstr "Reembolsos a clientes não pagos"
@ -13232,6 +13224,13 @@ msgstr ""
#~ msgid "Can not %s draft/proforma/cancel invoice."
#~ msgstr "Não pode %s provisório/proforma/cancelar fatura."
#, python-format
#~ msgid ""
#~ "Selected Move lines does not have any account move enties in draft state"
#~ msgstr ""
#~ "As linhas de movimento selecionadas não tem nenhum movimento nesta conta no "
#~ "modo provisório"
#, python-format
#~ msgid "Can not pay draft/proforma/cancel invoice."
#~ msgstr "Não se pode pagar uma fatura provisória/proforma/cancelada"

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-01-30 03:58+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
"PO-Revision-Date: 2013-04-25 09:04+0000\n"
"Last-Translator: Oliver Yuan <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:20+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-04-26 05:34+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: account
#: model:process.transition,name:account.process_transition_supplierreconcilepaid0
@ -10748,7 +10748,7 @@ msgstr "手动的发票税(非主营业务纳税)"
#: code:addons/account/account_invoice.py:550
#, python-format
msgid "The payment term of supplier does not have a payment term line."
msgstr ""
msgstr "供应商付款条件没有包含付款条件行"
#. module: account
#: field:account.account,parent_right:0

View File

@ -23,10 +23,16 @@ import datetime
from dateutil.relativedelta import relativedelta
import logging
from operator import itemgetter
from os.path import join as opj
import time
import urllib2
import urlparse
from openerp import tools
try:
import simplejson as json
except ImportError:
import json # noqa
from openerp.release import serie
from openerp.tools.translate import _
from openerp.osv import fields, osv
@ -38,13 +44,28 @@ class account_installer(osv.osv_memory):
def _get_charts(self, cr, uid, context=None):
modules = self.pool.get('ir.module.module')
# try get the list on apps server
try:
apps_server = self.pool.get('ir.config_parameter').get_param(cr, uid, 'apps.server', 'https://apps.openerp.com')
up = urlparse.urlparse(apps_server)
url = '{0.scheme}://{0.netloc}/apps/charts?serie={1}'.format(up, serie)
j = urllib2.urlopen(url, timeout=3).read()
apps_charts = json.loads(j)
charts = dict(apps_charts)
except Exception:
charts = dict()
# Looking for the module with the 'Account Charts' category
category_name, category_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'module_category_localization_account_charts')
ids = modules.search(cr, uid, [('category_id', '=', category_id)], context=context)
charts = list(
sorted(((m.name, m.shortdesc)
for m in modules.browse(cr, uid, ids, context=context)),
key=itemgetter(1)))
if ids:
charts.update((m.name, m.shortdesc) for m in modules.browse(cr, uid, ids, context=context))
charts = sorted(charts.items(), key=itemgetter(1))
charts.insert(0, ('configurable', _('Custom')))
return charts
@ -57,9 +78,9 @@ class account_installer(osv.osv_memory):
"country."),
'date_start': fields.date('Start Date', required=True),
'date_stop': fields.date('End Date', required=True),
'period': fields.selection([('month', 'Monthly'), ('3months','3 Monthly')], 'Periods', required=True),
'period': fields.selection([('month', 'Monthly'), ('3months', '3 Monthly')], 'Periods', required=True),
'company_id': fields.many2one('res.company', 'Company', required=True),
'has_default_company' : fields.boolean('Has Default Company', readonly=True),
'has_default_company': fields.boolean('Has Default Company', readonly=True),
}
def _default_company(self, cr, uid, context=None):
@ -78,30 +99,29 @@ class account_installer(osv.osv_memory):
'has_default_company': _default_has_default_company,
'charts': 'configurable'
}
def get_unconfigured_cmp(self, cr, uid, context=None):
""" get the list of companies that have not been configured yet
but don't care about the demo chart of accounts """
cmp_select = []
company_ids = self.pool.get('res.company').search(cr, uid, [], context=context)
cr.execute("SELECT company_id FROM account_account WHERE active = 't' AND account_account.parent_id IS NULL AND name != %s", ("Chart For Automated Tests",))
configured_cmp = [r[0] for r in cr.fetchall()]
return list(set(company_ids)-set(configured_cmp))
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."))
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
if context is None:context = {}
res = super(account_installer, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)
if context is None: context = {}
res = super(account_installer, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=False)
cmp_select = []
# display in the widget selection only the companies that haven't been configured yet
unconfigured_cmp = self.get_unconfigured_cmp(cr, uid, context=context)
for field in res['fields']:
if field == 'company_id':
res['fields'][field]['domain'] = [('id','in',unconfigured_cmp)]
res['fields'][field]['domain'] = [('id', 'in', unconfigured_cmp)]
res['fields'][field]['selection'] = [('', '')]
if unconfigured_cmp:
cmp_select = [(line.id, line.name) for line in self.pool.get('res.company').browse(cr, uid, unconfigured_cmp)]
@ -117,7 +137,7 @@ class account_installer(osv.osv_memory):
def execute(self, cr, uid, ids, context=None):
self.execute_simple(cr, uid, ids, context)
super(account_installer, self).execute(cr, uid, ids, context=context)
return super(account_installer, self).execute(cr, uid, ids, context=context)
def execute_simple(self, cr, uid, ids, context=None):
if context is None:
@ -129,8 +149,8 @@ class account_installer(osv.osv_memory):
if not f_ids:
name = code = res['date_start'][:4]
if int(name) != int(res['date_stop'][:4]):
name = res['date_start'][:4] +'-'+ res['date_stop'][:4]
code = res['date_start'][2:4] +'-'+ res['date_stop'][2:4]
name = res['date_start'][:4] + '-' + res['date_stop'][:4]
code = res['date_start'][2:4] + '-' + res['date_stop'][2:4]
vals = {
'name': name,
'code': code,
@ -150,7 +170,7 @@ class account_installer(osv.osv_memory):
chart = self.read(cr, uid, ids, ['charts'],
context=context)[0]['charts']
_logger.debug('Installing chart of accounts %s', chart)
return modules | set([chart])
return (modules | set([chart])) - set(['has_default_company', 'configurable'])
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -233,5 +233,10 @@ class res_partner(osv.osv):
'last_reconciliation_date': fields.datetime('Latest Full Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the last date where a reconciliation has been made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 different ways: either the last unreconciled debit/credit entry of this partner was reconciled, either the user pressed the button "Nothing more to reconcile" during the manual reconciliation process.')
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \
['debit_limit', 'property_account_payable', 'property_account_receivable', 'property_account_position',
'property_payment_term', 'property_supplier_payment_term', 'last_reconciliation_date']
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -50,6 +50,29 @@
</field>
</record>
<record id="action_account_analytic_account_form" model="ir.actions.act_window">
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id}</field>
<field name="name">Contracts/Analytic Accounts</field>
<field name="res_model">account.analytic.account</field>
<field name="view_mode">tree,form</field>
</record>
<record model="ir.ui.view" id="partner_view_buttons">
<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="arch" type="xml">
<xpath expr="//div[@name='buttons']" position="inside">
<button type="action" string="Invoices"
name="%(account.action_invoice_tree)d"
context="{'search_default_partner_id': active_id,'default_partner_id': active_id}" groups="account.group_account_invoice"/>
<button type="action" string="Journal Items" name="%(account.action_account_moves_all_tree)d" groups="account.group_account_user"/>
<button type="action" string="Contracts/Analytic Accounts" name="%(account.action_account_analytic_account_form)d"
groups="analytic.group_analytic_accounting"/>
</xpath>
</field>
</record>
<record id="action_account_fiscal_position_form" model="ir.actions.act_window">
<field name="name">Fiscal Positions</field>
<field name="res_model">account.fiscal.position</field>
@ -73,7 +96,7 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<page string="History" position="before" version="7.0">
<page string="Accounting" col="4">
<page string="Accounting" col="4" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<group>
<group>
<field name="property_account_position" widget="selection"/>
@ -103,20 +126,13 @@
</tree>
</field>
</page>
<page string="Accounting" name="accounting_disabled" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
<div>
<p>Accounting-related settings are managed on <button name="open_commercial_entity" type="object" string="the parent company" class="oe_link"/></p>
</div>
</page>
</page>
</field>
</record>
<!-- Partners info tab view-->
<act_window
id="action_analytic_open"
name="Contracts/Analytic Accounts"
res_model="account.analytic.account"
context="{'search_default_partner_id':[active_id], 'default_partner_id': active_id}"
src_model="res.partner"
view_type="form"
view_mode="tree,form"/>
</data>
</openerp>

View File

@ -31,7 +31,7 @@
<search string="Analytic Account">
<field name="name" filter_domain="['|', ('name','ilike',self), ('code','ilike',self)]" string="Analytic Account"/>
<field name="date"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="manager_id"/>
<field name="parent_id"/>
<field name="user_id"/>

View File

@ -81,7 +81,7 @@ class account_entries_report(osv.osv):
period_obj = self.pool.get('account.period')
for arg in args:
if arg[0] == 'period_id' and arg[2] == 'current_period':
current_period = period_obj.find(cr, uid)[0]
current_period = period_obj.find(cr, uid, context=context)[0]
args.append(['period_id','in',[current_period]])
break
elif arg[0] == 'period_id' and arg[2] == 'current_year':
@ -100,7 +100,7 @@ class account_entries_report(osv.osv):
fiscalyear_obj = self.pool.get('account.fiscalyear')
period_obj = self.pool.get('account.period')
if context.get('period', False) == 'current_period':
current_period = period_obj.find(cr, uid)[0]
current_period = period_obj.find(cr, uid, context=context)[0]
domain.append(['period_id','in',[current_period]])
elif context.get('year', False) == 'current_year':
current_year = fiscalyear_obj.find(cr, uid)

View File

@ -70,6 +70,7 @@ class account_invoice_report(osv.osv):
'categ_id': fields.many2one('product.category','Category of Product', readonly=True),
'journal_id': fields.many2one('account.journal', 'Journal', readonly=True),
'partner_id': fields.many2one('res.partner', 'Partner', readonly=True),
'commercial_partner_id': fields.many2one('res.partner', 'Partner Company', help="Commercial Entity"),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
'user_id': fields.many2one('res.users', 'Salesperson', readonly=True),
'price_total': fields.float('Total Without Tax', readonly=True),
@ -108,7 +109,7 @@ class account_invoice_report(osv.osv):
sub.fiscal_position, sub.user_id, sub.company_id, sub.nbr, sub.type, sub.state,
sub.categ_id, sub.date_due, sub.account_id, sub.account_line_id, sub.partner_bank_id,
sub.product_qty, sub.price_total / cr.rate as price_total, sub.price_average /cr.rate as price_average,
cr.rate as currency_rate, sub.residual / cr.rate as residual
cr.rate as currency_rate, sub.residual / cr.rate as residual, sub.commercial_partner_id as commercial_partner_id
"""
return select_str
@ -170,7 +171,8 @@ class account_invoice_report(osv.osv):
LEFT JOIN account_invoice a ON a.id = l.invoice_id
WHERE a.id = ai.id)
ELSE 1::bigint
END::numeric AS residual
END::numeric AS residual,
ai.commercial_partner_id as commercial_partner_id
"""
return select_str
@ -193,7 +195,7 @@ class account_invoice_report(osv.osv):
ai.partner_id, ai.payment_term, ai.period_id, u.name, ai.currency_id, ai.journal_id,
ai.fiscal_position, ai.user_id, ai.company_id, ai.type, ai.state, pt.categ_id,
ai.date_due, ai.account_id, ail.account_id, ai.partner_bank_id, ai.residual,
ai.amount_total, u.uom_type, u.category_id
ai.amount_total, u.uom_type, u.category_id, ai.commercial_partner_id
"""
return group_by_str

View File

@ -14,6 +14,7 @@
<field name="type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="commercial_partner_id" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="uom_name" invisible="not context.get('set_visible',False)"/>
<field name="categ_id" invisible="1"/>
@ -65,7 +66,8 @@
<field name="user_id" />
<field name="categ_id" filter_domain="[('categ_id', 'child_of', self)]"/>
<group expand="1" string="Group By...">
<filter string="Partner" name="partner" icon="terp-partner" context="{'group_by':'partner_id','residual_visible':True}"/>
<filter string="Partner" name="partner_id" context="{'group_by':'partner_id','residual_visible':True}"/>
<filter string="Commercial Partner" name="commercial_partner_id" context="{'group_by':'commercial_partner_id','residual_visible':True}"/>
<filter string="Salesperson" name='user' icon="terp-personal" context="{'group_by':'user_id'}"/>
<filter string="Due Date" icon="terp-go-today" context="{'group_by':'date_due'}"/>
<filter string="Period" icon="terp-go-month" context="{'group_by':'period_id'}" name="period"/>

View File

@ -26,7 +26,7 @@ openerp.account = function (instance) {
if (this.partners) {
this.$el.prepend(QWeb.render("AccountReconciliation", {widget: this}));
this.$(".oe_account_recon_previous").click(function() {
self.current_partner = (self.current_partner - 1) % self.partners.length;
self.current_partner = (((self.current_partner - 1) % self.partners.length) + self.partners.length) % self.partners.length;
self.search_by_partner();
});
this.$(".oe_account_recon_next").click(function() {

View File

@ -148,7 +148,6 @@ class account_move_line_reconcile_writeoff(osv.osv_memory):
context['analytic_id'] = data['analytic_id'][0]
if context['date_p']:
date = context['date_p']
ids = period_obj.find(cr, uid, dt=date, context=context)
if ids:
period_id = ids[0]

View File

@ -38,7 +38,7 @@ class account_tax_chart(osv.osv_memory):
def _get_period(self, cr, uid, context=None):
"""Return default period value"""
period_ids = self.pool.get('account.period').find(cr, uid)
period_ids = self.pool.get('account.period').find(cr, uid, context=context)
return period_ids and period_ids[0] or False
def account_tax_chart_open_window(self, cr, uid, ids, context=None):

View File

@ -67,6 +67,8 @@ class CashBoxIn(CashBox):
class CashBoxOut(CashBox):
_name = 'cash.box.out'
_columns = CashBox._columns.copy()
def _compute_values_for_statement_line(self, cr, uid, box, record, context=None):
amount = box.amount or 0.0
return {

View File

@ -213,7 +213,7 @@
<search string="Contracts">
<field name="name" filter_domain="['|', ('name','ilike',self),('code','ilike',self)]" string="Contract"/>
<field name="date"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="manager_id"/>
<field name="parent_id"/>
<filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="Contracts in progress (open, draft)"/>

View File

@ -82,7 +82,7 @@ class account_asset_asset(osv.osv):
return super(account_asset_asset, self).unlink(cr, uid, ids, context=context)
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid)
periods = self.pool.get('account.period').find(cr, uid, context=context)
if periods:
return periods[0]
else:

View File

@ -223,7 +223,7 @@
<filter icon="terp-check" string="Current" domain="[('state','in', ('draft','open'))]" help="Assets in draft and open states"/>
<filter icon="terp-dialog-close" string="Closed" domain="[('state','=', 'close')]" help="Assets in closed state"/>
<field name="category_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
</search>
</field>
</record>

View File

@ -49,7 +49,7 @@
<field name="asset_id"/>
<field name="asset_category_id"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group expand="1" string="Group By...">

View File

@ -30,7 +30,7 @@ class asset_depreciation_confirmation_wizard(osv.osv_memory):
}
def _get_period(self, cr, uid, context=None):
periods = self.pool.get('account.period').find(cr, uid)
periods = self.pool.get('account.period').find(cr, uid, context=context)
if periods:
return periods[0]
return False

View File

@ -10,7 +10,7 @@
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<tree string="Customer Followup">
<field name="name"/>
<field name="display_name"/>
<field name="payment_next_action_date"/>
<field name="payment_next_action"/>
<field name="user_id" invisible="1"/>
@ -29,7 +29,7 @@
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="display_name" position="after">
<field name="payment_responsible_id" invisible="1"/>
</field>
</field>

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n"
"X-Generator: Launchpad (build 16564)\n"
"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n"
"X-Generator: Launchpad (build 16567)\n"
"Language: nl\n"
#. module: account_followup

View File

@ -84,7 +84,7 @@ class account_voucher(osv.osv):
if context is None: context = {}
if context.get('period_id', False):
return context.get('period_id')
periods = self.pool.get('account.period').find(cr, uid)
periods = self.pool.get('account.period').find(cr, uid, context=context)
return periods and periods[0] or False
def _make_journal_search(self, cr, uid, ttype, context=None):

View File

@ -129,7 +129,7 @@
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<separator/>
<filter icon="terp-gtk-jump-to-ltr" string="To Review" domain="[('state','=','posted'), ('audit','=',False)]" help="To Review"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" />
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-12-19 18:04+0000\n"
"PO-Revision-Date: 2013-04-26 16:01+0000\n"
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
"Language-Team: Els Van Vossel\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:33+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-04-27 05:44+0000\n"
"X-Generator: Launchpad (build 16580)\n"
"Language: nl\n"
#. module: account_voucher
@ -138,6 +138,8 @@ msgid ""
"You can not change the journal as you already reconciled some statement "
"lines!"
msgstr ""
"U kunt het journaal niet veranderen, omdat er al uittreksellijnen zijn "
"afgepunt."
#. module: account_voucher
#: view:account.voucher:0
@ -148,7 +150,7 @@ msgstr "Goedkeuren"
#: model:ir.actions.act_window,name:account_voucher.action_vendor_payment
#: model:ir.ui.menu,name:account_voucher.menu_action_vendor_payment
msgid "Supplier Payments"
msgstr ""
msgstr "Leveranciersbetalingen"
#. module: account_voucher
#: model:ir.actions.act_window,help:account_voucher.action_purchase_receipt
@ -223,7 +225,7 @@ msgstr "Berichten"
#: model:ir.actions.act_window,name:account_voucher.action_purchase_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_purchase_receipt
msgid "Purchase Receipts"
msgstr ""
msgstr "Aankoopbewijzen"
#. module: account_voucher
#: field:account.voucher.line,move_line_id:0
@ -431,7 +433,7 @@ msgstr "Debet"
#: code:addons/account_voucher/account_voucher.py:1547
#, python-format
msgid "Unable to change journal !"
msgstr ""
msgstr "Het dagboek kan niet worden gewijzigd"
#. module: account_voucher
#: view:sale.receipt.report:0
@ -745,7 +747,7 @@ msgstr "Augustus"
#. module: account_voucher
#: view:account.voucher:0
msgid "Validate Payment"
msgstr ""
msgstr "Betaling bevestigen"
#. module: account_voucher
#: help:account.voucher,audit:0
@ -786,7 +788,7 @@ msgstr "Betaald"
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt
msgid "Sales Receipts"
msgstr ""
msgstr "Verkoopbewijzen"
#. module: account_voucher
#: field:account.voucher,message_is_follower:0
@ -834,7 +836,7 @@ msgstr "Onmiddellijk betalen"
#. module: account_voucher
#: field:account.voucher.line,type:0
msgid "Dr/Cr"
msgstr ""
msgstr "Db/Cr"
#. module: account_voucher
#: field:account.voucher,pre_line:0
@ -845,7 +847,7 @@ msgstr "Vorige betalingen?"
#: code:addons/account_voucher/account_voucher.py:1112
#, python-format
msgid "The invoice you are willing to pay is not valid anymore."
msgstr ""
msgstr "De factuur die u wilt betalen, is niet meer geldig."
#. module: account_voucher
#: selection:sale.receipt.report,month:0
@ -884,7 +886,7 @@ msgstr "Gelieve een reeks in te stellen voor het journaal."
#: 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 "Klantenbetalingen"
#. module: account_voucher
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all
@ -938,7 +940,7 @@ msgstr "Nummer"
#. module: account_voucher
#: selection:account.voucher.line,type:0
msgid "Credit"
msgstr ""
msgstr "Credit"
#. module: account_voucher
#: model:ir.model,name:account_voucher.model_account_bank_statement
@ -1279,7 +1281,7 @@ msgstr "Openstaand saldo"
#. module: account_voucher
#: model:mail.message.subtype,description:account_voucher.mt_voucher_state_change
msgid "Status <b>changed</b>"
msgstr ""
msgstr "Status <b>vgewijzigd</b>"
#. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1014

View File

@ -11,7 +11,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Customer"/>
<field name="partner_id" string="Customer" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('bank','cash'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">
@ -34,7 +34,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Supplier" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('bank','cash'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -10,7 +10,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Supplier" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('purchase','purchase_refund'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">
@ -32,7 +32,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Customer"/>
<field name="partner_id" string="Customer" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('sale','sale_refund'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -0,0 +1,28 @@
# Lithuanian 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-04-24 18:24+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Lithuanian <lt@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-04-25 05:20+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: auth_crypt
#: field:res.users,password_crypt:0
msgid "Encrypted Password"
msgstr "Užšifruotas slaptažodis"
#. module: auth_crypt
#: model:ir.model,name:auth_crypt.model_res_users
msgid "Users"
msgstr "Naudotojai"

View File

@ -0,0 +1,23 @@
# Lithuanian 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-04-24 18:21+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Lithuanian <lt@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-04-25 05:20+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: auth_oauth_signup
#: model:ir.model,name:auth_oauth_signup.model_res_users
msgid "Users"
msgstr "Naudotojai"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-04-16 04:37+0000\n"
"X-Generator: Launchpad (build 16564)\n"
"X-Launchpad-Export-Date: 2013-04-17 05:15+0000\n"
"X-Generator: Launchpad (build 16567)\n"
#. module: auth_signup
#: field:res.partner,signup_type:0

View File

@ -200,6 +200,9 @@ class res_users(osv.Model):
'partner_id': partner.id,
'email': values.get('email') or values.get('login'),
})
if partner.company_id:
values['company_id'] = partner.company_id.id
values['company_ids'] = [(6,0,[partner.company_id.id])]
self._signup_create_user(cr, uid, values, context=context)
else:
# no token, sign up an external user

File diff suppressed because it is too large Load Diff

View File

@ -20,12 +20,13 @@
##############################################################################
import base64
from StringIO import StringIO
from openerp.modules.module import get_module_resource
import openerp.modules.registry
from openerp.osv import osv
from openerp_sxw2rml import sxw2rml
from StringIO import StringIO
from openerp import addons
class report_xml(osv.osv):
_inherit = 'ir.actions.report.xml'
@ -36,9 +37,9 @@ class report_xml(osv.osv):
'''
sxwval = StringIO(base64.decodestring(file_sxw))
if file_type=='sxw':
fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb')
fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb')
if file_type=='odt':
fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb')
fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb')
return {'report_rml_content': str(sxw2rml(sxwval, xsl=fp.read()))}
def upload_report(self, cr, uid, report_id, file_sxw, file_type, context=None):
@ -47,9 +48,9 @@ class report_xml(osv.osv):
'''
sxwval = StringIO(base64.decodestring(file_sxw))
if file_type=='sxw':
fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb')
fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_oo2rml.xsl'),'rb')
if file_type=='odt':
fp = open(addons.get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb')
fp = open(get_module_resource('base_report_designer','openerp_sxw2rml', 'normalized_odt2rml.xsl'),'rb')
report = self.pool['ir.actions.report.xml'].write(cr, uid, [report_id], {
'report_sxw_content': base64.decodestring(file_sxw),
'report_rml_content': str(sxw2rml(sxwval, xsl=fp.read())),

View File

@ -20,7 +20,7 @@
<xpath expr="//separator[@string='title']" position="after">
<group colspan="8" height="450" width="750">
<field name="name" invisible="1"/>
<field name="plugin_file" filename="name"/>
<field name="plugin_file" filename="name" widget="url"/>
<separator string="Installation and Configuration Steps" colspan="4"/>
<field name="description" nolabel="1" colspan="8"/>
</group>

View File

@ -23,7 +23,6 @@ from openerp.osv import fields
from openerp.osv import osv
import base64
from openerp.tools.translate import _
from openerp import addons
class base_report_designer_installer(osv.osv_memory):
_name = 'base_report_designer.installer'
@ -31,13 +30,13 @@ class base_report_designer_installer(osv.osv_memory):
def default_get(self, cr, uid, fields, context=None):
data = super(base_report_designer_installer, self).default_get(cr, uid, fields, context=context)
plugin_file = open(addons.get_module_resource('base_report_designer','plugin', 'openerp_report_designer.zip'),'rb')
data['plugin_file'] = base64.encodestring(plugin_file.read())
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
data['plugin_file'] = base_url + '/base_report_designer/static/base-report-designer-plugin/openerp_report_designer.zip'
return data
_columns = {
'name':fields.char('File name', size=34),
'plugin_file':fields.binary('OpenObject Report Designer Plug-in', readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."),
'plugin_file':fields.char('OpenObject Report Designer Plug-in', size=256, readonly=True, help="OpenObject Report Designer plug-in file. Save as this file and install this plug-in in OpenOffice."),
'description':fields.text('Description', readonly=True)
}

View File

@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2012-10-01 11:22+0000\n"
"PO-Revision-Date: 2013-04-26 16:24+0000\n"
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:12+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-04-27 05:44+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Emails Integration"
msgstr ""
msgstr "E-mailintegratie"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -29,18 +29,19 @@ msgstr "Gast"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Contacts"
msgstr ""
msgstr "Contactpersonen"
#. module: base_setup
#: model:ir.model,name:base_setup.model_base_config_settings
msgid "base.config.settings"
msgstr ""
msgstr "base.config.settings"
#. module: base_setup
#: field:base.config.settings,module_auth_oauth:0
msgid ""
"Use external authentication providers, sign in with google, facebook, ..."
msgstr ""
"Gebruik externe verificatieproviders. Meld aan met Google, Facebook, ..."
#. module: base_setup
#: view:sale.config.settings:0
@ -54,11 +55,19 @@ msgid ""
"OpenERP using specific\n"
" plugins for your preferred email application."
msgstr ""
"OpenERP maakt het mogelijk om automatisch leads (of andere documenten)\n"
" aan te maken op basis van inkomende e-mails. U "
"kunt automatisch e-mails synchroniseren met OpenERP\n"
" met behulp van reguliere POP / IMAP-accounts, "
"via een direct e-mailintegratiescript voor uw\n"
" e-mailserver, of door zelf uw e-mails naar "
"OpenERP te sturen met behulp van specifieke\n"
" plug-ins voor uw favoriete e-mailprogramma."
#. module: base_setup
#: field:sale.config.settings,module_sale:0
msgid "SALE"
msgstr ""
msgstr "VERKOOP"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -68,24 +77,24 @@ msgstr "Lid"
#. module: base_setup
#: view:base.config.settings:0
msgid "Portal access"
msgstr ""
msgstr "Portaaltoegang"
#. module: base_setup
#: view:base.config.settings:0
msgid "Authentication"
msgstr ""
msgstr "Verificatie"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Quotations and Sales Orders"
msgstr ""
msgstr "Offertes en verkooporders"
#. module: base_setup
#: view:base.config.settings:0
#: model:ir.actions.act_window,name:base_setup.action_general_configuration
#: model:ir.ui.menu,name:base_setup.menu_general_configuration
msgid "General Settings"
msgstr ""
msgstr "Algemeen"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -95,12 +104,12 @@ msgstr "Donor"
#. module: base_setup
#: view:base.config.settings:0
msgid "Email"
msgstr ""
msgstr "E-mail"
#. module: base_setup
#: field:sale.config.settings,module_crm:0
msgid "CRM"
msgstr ""
msgstr "Relatiebeheer"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -110,32 +119,32 @@ msgstr "Patiënt"
#. module: base_setup
#: field:base.config.settings,module_base_import:0
msgid "Allow users to import data from CSV files"
msgstr ""
msgstr "Gebruikers mogen gegevens importeren uit csv-bestanden"
#. module: base_setup
#: field:base.config.settings,module_multi_company:0
msgid "Manage multiple companies"
msgstr ""
msgstr "Meerdere bedrijven beheren"
#. module: base_setup
#: view:sale.config.settings:0
msgid "On Mail Client"
msgstr ""
msgstr "Op e-mailclient"
#. module: base_setup
#: view:base.config.settings:0
msgid "--db-filter=YOUR_DATABAE"
msgstr ""
msgstr "--db-filter=UW_DATABASE"
#. module: base_setup
#: field:sale.config.settings,module_web_linkedin:0
msgid "Get contacts automatically from linkedIn"
msgstr ""
msgstr "Haal contactpersonen op uit LinkedIn"
#. module: base_setup
#: field:sale.config.settings,module_plugin_thunderbird:0
msgid "Enable Thunderbird plug-in"
msgstr ""
msgstr "Activeer de Thunderbirdplug-in"
#. module: base_setup
#: view:base.setup.terminology:0
@ -145,22 +154,22 @@ msgstr "res_config_contents"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Customer Features"
msgstr ""
msgstr "Klantenopties"
#. module: base_setup
#: view:base.config.settings:0
msgid "Import / Export"
msgstr ""
msgstr "Import / Export"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Sale Features"
msgstr ""
msgstr "Verkoopopties"
#. module: base_setup
#: field:sale.config.settings,module_plugin_outlook:0
msgid "Enable Outlook plug-in"
msgstr ""
msgstr "Activeer de Outlookplug-in"
#. module: base_setup
#: view:base.setup.terminology:0
@ -179,7 +188,7 @@ msgstr "Huurder"
#. module: base_setup
#: help:base.config.settings,module_share:0
msgid "Share or embbed any screen of openerp."
msgstr ""
msgstr "Gelijk welk scherm van OpenERP delen of insluiten"
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -192,6 +201,8 @@ msgid ""
"When you create a new contact (person or company), you will be able to load "
"all the data from LinkedIn (photos, address, etc)."
msgstr ""
"Als u een nieuwe contactpersoon maakt (persoon of bedrijf), kunt u alle "
"gegevens van LinkedIn laden (foto, adres, enz.)"
#. module: base_setup
#: help:base.config.settings,module_multi_company:0
@ -200,6 +211,9 @@ msgid ""
"companies.\n"
" This installs the module multi_company."
msgstr ""
"Werken in omgevingen met meerdere bedrijven, met de nodige "
"toegangsbeveiliging tussen de bedrijven.\n"
" Hiermee installeert u de module multi_company."
#. module: base_setup
#: view:base.config.settings:0
@ -208,6 +222,9 @@ msgid ""
"You can\n"
" launch the OpenERP Server with the option"
msgstr ""
"Het openbare portaal is alleen toegankelijk als u zich in een enkele "
"databasemodus bevindt. U kunt\n"
" de OpenERP-server starten met de optie"
#. module: base_setup
#: view:base.config.settings:0
@ -215,11 +232,13 @@ msgid ""
"You will find more options in your company details: address for the header "
"and footer, overdue payments texts, etc."
msgstr ""
"U vindt meer opties bij de bedrijfsgegevens: adres voor de kop- en "
"voettekst, teksten voor achterstallige betalingen, enz."
#. module: base_setup
#: model:ir.model,name:base_setup.model_sale_config_settings
msgid "sale.config.settings"
msgstr ""
msgstr "sale.config.settings"
#. module: base_setup
#: field:base.setup.terminology,partner:0
@ -238,6 +257,12 @@ msgid ""
"projects,\n"
" etc."
msgstr ""
"Wanneer u een document naar een klant stuurt,\n"
" (offerte, factuur), kan uw klant\n"
" aanmelden en zijn documenten bekijken,\n"
" uw bedrijfsnieuws lezen, zijn projecten "
"controleren,\n"
" enz."
#. module: base_setup
#: model:ir.model,name:base_setup.model_base_setup_terminology
@ -253,6 +278,8 @@ msgstr "Cliënt"
#: help:base.config.settings,module_portal_anonymous:0
msgid "Enable the public part of openerp, openerp becomes a public website."
msgstr ""
"Activeer het openbare deel van OpenERP; OpenERP wordt hiermee een openbare "
"website."
#. module: base_setup
#: help:sale.config.settings,module_plugin_thunderbird:0
@ -265,6 +292,13 @@ msgid ""
" Partner from the selected emails.\n"
" This installs the module plugin_thunderbird."
msgstr ""
"Met de plug-in kunt u e-mails met bijlagen koppelen aan de geselecteerde\n"
" OpenERP-objecten. U kunt een relatie of een lead kiezen en\n"
" de gekozen e-mail koppelen als een .eml-bestand als bijlage\n"
" aan het geselecteerde record. U kunt documenten aanmaken "
"voor CRM-lead\n"
" en relaties vanuit de geselecteerde e-mails. Hiermee "
"installeert u de module plugin_thunderbird."
#. module: base_setup
#: selection:base.setup.terminology,partner:0
@ -280,7 +314,7 @@ msgstr "Gebruik een andere benaming voor Klant"
#: model:ir.actions.act_window,name:base_setup.action_sale_config
#: view:sale.config.settings:0
msgid "Configure Sales"
msgstr ""
msgstr "Verkoop instellen"
#. module: base_setup
#: help:sale.config.settings,module_plugin_outlook:0
@ -293,16 +327,23 @@ msgid ""
" email into an OpenERP mail message with attachments.\n"
" This installs the module plugin_outlook."
msgstr ""
"Met de Outlookplug-in kunt u een object selecteren dat u wilt toevoegen\n"
" aan uw e-mail en de bijlagen van MS Outlook. U kunt een "
"relatie \n"
" of een lead kiezen en de geselecteerde e-mail archiveren in "
"een\n"
" OpenERP-mailbericht met bijlagen.\n"
" Hiermee installeert u de module plugin_outlook."
#. module: base_setup
#: view:base.config.settings:0
msgid "Options"
msgstr ""
msgstr "Opties"
#. module: base_setup
#: field:base.config.settings,module_portal:0
msgid "Activate the customer portal"
msgstr ""
msgstr "Klantenportaal activeren"
#. module: base_setup
#: view:base.config.settings:0
@ -311,36 +352,37 @@ msgid ""
" Once activated, the login page will be "
"replaced by the public website."
msgstr ""
"Na activering zal de aanmeldpagina worden vervangen door de openbare website."
#. module: base_setup
#: field:base.config.settings,module_share:0
msgid "Allow documents sharing"
msgstr ""
msgstr "Sta het delen van documenten toe"
#. module: base_setup
#: view:base.config.settings:0
msgid "(company news, jobs, contact form, etc.)"
msgstr ""
msgstr "(bedrijfsnieuws, vacatures, contactformulier, enz.)"
#. module: base_setup
#: field:base.config.settings,module_portal_anonymous:0
msgid "Activate the public portal"
msgstr ""
msgstr "Openbare portaal activeren"
#. module: base_setup
#: view:base.config.settings:0
msgid "Configure outgoing email servers"
msgstr ""
msgstr "Uitgaande e-mailservers instellen"
#. module: base_setup
#: view:sale.config.settings:0
msgid "Social Network Integration"
msgstr ""
msgstr "Integratie sociale netwerken"
#. module: base_setup
#: help:base.config.settings,module_portal:0
msgid "Give your customers access to their documents."
msgstr ""
msgstr "Geef uw klanten toegang tot hun documenten."
#. module: base_setup
#: view:base.config.settings:0
@ -352,7 +394,7 @@ msgstr "Afbreken"
#: view:base.config.settings:0
#: view:sale.config.settings:0
msgid "Apply"
msgstr ""
msgstr "Toepassen"
#. module: base_setup
#: view:base.setup.terminology:0
@ -363,12 +405,12 @@ msgstr "Kies uw terminologie"
#: view:base.config.settings:0
#: view:sale.config.settings:0
msgid "or"
msgstr ""
msgstr "of"
#. module: base_setup
#: view:base.config.settings:0
msgid "Configure your company data"
msgstr ""
msgstr "Uw bedrijfsgegevens instellen"
#~ msgid "Logo"
#~ msgstr "Logo"

View File

@ -134,6 +134,9 @@ class res_partner(osv.osv):
'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.")
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['vat_subjected']
def _construct_constraint_msg(self, cr, uid, ids, context=None):
def default_vat_check(cn, vn):
# by default, a VAT number is valid if:

View File

@ -0,0 +1,45 @@
# Lithuanian 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-04-24 18:20+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Lithuanian <lt@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-04-25 05:20+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: contacts
#: model:ir.actions.act_window,help:contacts.action_contacts
msgid ""
"<p class=\"oe_view_nocontent_create\">\n"
" Click to add a contact in your address book.\n"
" </p><p>\n"
" OpenERP helps you easily track all activities related to\n"
" a customer; discussions, history of business opportunities,\n"
" documents, etc.\n"
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
"Spauskite, kad sukurtumėte kontaktą adresų knygoje.\n"
"</p><p>\n"
"OpenERP pagalba galima stebėti visus veiksmus susijusius su\n"
"kontaktu; bendravimas, pardavimų galimybių istorija,\n"
"dokumentai, ir t.t.\n"
"</p>\n"
" "
#. module: contacts
#: model:ir.actions.act_window,name:contacts.action_contacts
#: model:ir.ui.menu,name:contacts.menu_contacts
msgid "Contacts"
msgstr "Kontaktai"

View File

@ -1053,6 +1053,14 @@ class crm_lead(base_stage, format_address, osv.osv):
message = _("%s a call for %s.%s") % (prefix, phonecall.date, suffix)
return self.message_post(cr, uid, ids, body=message, context=context)
def log_meeting(self, cr, uid, ids, meeting_subject, meeting_date, duration, context=None):
if not duration:
duration = _('unknown')
else:
duration = str(duration)
message = _("Meeting scheduled at '%s'<br> Subject: %s <br> Duration: %s hour(s)") % (meeting_date, meeting_subject, duration)
return self.message_post(cr, uid, ids, body=message, context=context)
def onchange_state(self, cr, uid, ids, state_id, context=None):
if state_id:
country_id=self.pool.get('res.country.state').browse(cr, uid, state_id, context).country_id.id

View File

@ -330,7 +330,7 @@
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="create_date"/>
<field name="country_id" context="{'invisible_country': False}"/>
<separator/>
@ -548,7 +548,7 @@
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike', self)]"/>
<field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<separator/>
<filter string="New" name="new" domain="[('state','=','draft')]" help="New Opportunities"/>
<filter string="In Progress" name="open" domain="[('state','=','open')]" help="Open Opportunities"/>

View File

@ -34,6 +34,13 @@ class crm_meeting(osv.Model):
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
}
def create(self, cr, uid, vals, context=None):
res = super(crm_meeting, self).create(cr, uid, vals, context=context)
obj = self.browse(cr, uid, res, context=context)
if obj.opportunity_id:
self.pool.get('crm.lead').log_meeting(cr, uid, [obj.opportunity_id.id], obj.name, obj.date, obj.duration, context=context)
return res
class calendar_attendee(osv.osv):
""" Calendar Attendee """

View File

@ -186,7 +186,7 @@
<separator/>
<filter string="Phone Calls Assigned to Me or My Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('user_id', '=', uid)]"
help="Phone Calls Assigned to the current user or with a team having the current user as team leader"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<field name="section_id" string="Sales Team"
groups="base.group_multi_salesteams"/>

View File

@ -1,20 +1,20 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * crm
# Els Van Vossel <evv@agaplan.eu>, 2012.
# Els Van Vossel <evv@agaplan.eu>, 2012, 2013.
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-10-02 07:29+0000\n"
"PO-Revision-Date: 2013-04-26 23:39+0000\n"
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
"Language-Team: Els Van Vossel\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:09+0000\n"
"X-Generator: Launchpad (build 16532)\n"
"X-Launchpad-Export-Date: 2013-04-27 05:44+0000\n"
"X-Generator: Launchpad (build 16580)\n"
"Language: nl\n"
#. module: crm
@ -28,6 +28,8 @@ msgid ""
"Allows you to configure your incoming mail server, and create leads from "
"incoming emails."
msgstr ""
"Hiermee kunt u de inkomende mailserver instellen en leads laten maken van "
"binnenkomende e-mails."
#. module: crm
#: code:addons/crm/crm_lead.py:881
@ -76,7 +78,7 @@ msgstr "Opportuniteiten kiezen"
#: model:res.groups,name:crm.group_fund_raising
#: field:sale.config.settings,group_fund_raising:0
msgid "Manage Fund Raising"
msgstr ""
msgstr "Fondsenwerving"
#. module: crm
#: view:crm.lead.report:0
@ -96,7 +98,7 @@ msgstr "Fasenaam"
#: view:crm.lead.report:0
#: view:crm.phonecall.report:0
msgid "Salesperson"
msgstr ""
msgstr "Verkoper"
#. module: crm
#: model:ir.model,name:crm.model_crm_lead_report
@ -113,18 +115,18 @@ msgstr "Dag"
#. module: crm
#: view:crm.lead:0
msgid "Company Name"
msgstr ""
msgstr "Bedrijfsnaam"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor6
msgid "Training"
msgstr ""
msgstr "Training"
#. module: crm
#: model:ir.actions.act_window,name:crm.crm_lead_categ_action
#: model:ir.ui.menu,name:crm.menu_crm_lead_categ
msgid "Sales Tags"
msgstr ""
msgstr "Verkooplabels"
#. module: crm
#: view:crm.lead.report:0
@ -137,6 +139,7 @@ msgstr "Verw. sluiting"
#: help:crm.phonecall,message_unread:0
msgid "If checked new messages require your attention."
msgstr ""
"Als dit is ingeschakeld, zijn er nieuwe berichten die uw aandacht vragen."
#. module: crm
#: help:crm.lead.report,creation_day:0
@ -182,6 +185,8 @@ msgid ""
"Holds the Chatter summary (number of messages, ...). This summary is "
"directly in html format in order to be inserted in kanban views."
msgstr ""
"Bevat de Chatsamenvatting (aantal berichten, ...). Deze samenvatting is in "
"html-formaat, zodat ze in de kanbanweergave kan worden gebruikt."
#. module: crm
#: code:addons/crm/crm_lead.py:624
@ -189,7 +194,7 @@ msgstr ""
#: code:addons/crm/crm_phonecall.py:280
#, python-format
msgid "Warning!"
msgstr ""
msgstr "Waarschuwing"
#. module: crm
#: view:crm.lead:0
@ -238,7 +243,7 @@ msgstr ""
#. module: crm
#: model:ir.actions.server,name:crm.action_email_reminder_lead
msgid "Reminder to User"
msgstr ""
msgstr "Herinnering voor gebruiker"
#. module: crm
#: field:crm.segmentation,segmentation_line:0
@ -266,7 +271,7 @@ msgstr "Leadanalyse"
#: code:addons/crm/crm_lead.py:1010
#, python-format
msgid "<b>%s a call</b> for the <em>%s</em>."
msgstr ""
msgstr "<b>%s een gesprek</b> voor <em>%s</em>."
#. module: crm
#: model:ir.actions.act_window,name:crm.crm_case_resource_type_act
@ -328,6 +333,16 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Klik als u een nieuwe klantensegmentering wilt instellen.\n"
" </p><p>\n"
" Maak specifiieke categorieën en ken deze toe aan uw\n"
" contactpersonen voor een betere interactie. Via\n"
" segmentering kunt u categorieën toekennen aan "
"contactpersonen\n"
" volgens de door u ingestelde criteria.\n"
" </p>\n"
" "
#. module: crm
#: field:crm.opportunity2phonecall,contact_name:0
@ -341,6 +356,7 @@ msgstr "Contactpersoon"
msgid ""
"When escalating to this team override the salesman with the team leader."
msgstr ""
"Bij escaleren naar dit team, wordt de verkoper vervangen door de teamleider."
#. module: crm
#: model:process.transition,name:crm.process_transition_opportunitymeeting0
@ -380,12 +396,25 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Klik om een opportuniteit voor deze klant te maken.\n"
" </p><p>\n"
" Met opportuniteiten kunt u uw verkooppijplijn en uw "
"mogelijke verkopen opvolgen,\n"
" voor een beter zicht op te verwachten inkomsten.\n"
" </p><p>\n"
" U kunt vergaderingen en telefoongesprekken plannen\n"
" voor opportuniteiten. U kunt van een opportuniteit een "
"offerte maken, documenten\n"
" toevoegen, discussies volgen, en nog veel meer.\n"
" </p>\n"
" "
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead7
#: view:crm.lead:0
msgid "Dead"
msgstr ""
msgstr "Dood"
#. module: crm
#: field:crm.case.section,message_unread:0
@ -393,7 +422,7 @@ msgstr ""
#: field:crm.lead,message_unread:0
#: field:crm.phonecall,message_unread:0
msgid "Unread Messages"
msgstr ""
msgstr "Ongelezen berichten"
#. module: crm
#: view:crm.segmentation:0
@ -407,7 +436,7 @@ msgstr "Segmentering"
#: selection:crm.lead2opportunity.partner.mass,action:0
#: selection:crm.partner.binding,action:0
msgid "Link to an existing customer"
msgstr ""
msgstr "Koppelen aan een bestaande relatie"
#. module: crm
#: field:crm.lead,write_date:0
@ -425,8 +454,8 @@ msgid ""
"This percentage depicts the default/average probability of the Case for this "
"stage to be a success"
msgstr ""
"Dit percentage drukt de standaard/gemiddelde slaagkans uit voor de zaak in "
"deze fase."
"Dit percentage drukt de standaard/gemiddelde slagingskans uit voor de zaak "
"in deze fase."
#. module: crm
#: view:crm.lead:0
@ -454,6 +483,7 @@ msgstr ""
#: view:crm.lead:0
msgid "Leads that are assigned to one of the sale teams I manage, or to me"
msgstr ""
"Leads toegewezen aan een van de verkoopteams onder mijn beheer, of aan mij"
#. module: crm
#: field:crm.lead,partner_address_email:0
@ -472,6 +502,15 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Klik als u een nieuw verkoopteam wilt maken.\n"
" </p><p>\n"
" Met verkoopteams organiseert u meerdere verkopers of "
"afdelingen in\n"
" aparte teams. Elk team werkt op zijn eigen\n"
" opportuniteitenlijst.\n"
" </p>\n"
" "
#. module: crm
#: model:process.transition,note:crm.process_transition_opportunitymeeting0
@ -485,7 +524,7 @@ msgstr "Gewone of telefonische vergadering over opportuniteit"
#: view:crm.phonecall.report:0
#: field:crm.phonecall.report,state:0
msgid "Status"
msgstr ""
msgstr "Status"
#. module: crm
#: view:crm.lead2opportunity.partner:0
@ -495,7 +534,7 @@ msgstr "Opportuniteit maken"
#. module: crm
#: view:sale.config.settings:0
msgid "Configure"
msgstr ""
msgstr "Instellen"
#. module: crm
#: view:crm.lead:0
@ -555,18 +594,26 @@ msgid ""
" If the call needs to be done then the status is set "
"to 'Not Held'."
msgstr ""
"De status wordt op 'Uit te voeren' gezet als er een zaak wordt gemaakt. "
" \n"
"Als de zaak lopende is, wordt de status op 'Open' gezet. "
" \n"
"Als het gesprek is gevoerd, wordt de status op 'Uitgevoerd' gezet. "
" \n"
"Als het gesprek nog moet worden uitgevoerd, gaat de status naar 'Niet "
"uitgevoerd'."
#. module: crm
#: field:crm.case.section,message_summary:0
#: field:crm.lead,message_summary:0
#: field:crm.phonecall,message_summary:0
msgid "Summary"
msgstr "Samenvatting"
msgstr "Overzicht"
#. module: crm
#: view:crm.merge.opportunity:0
msgid "Merge"
msgstr ""
msgstr "Samenvoegen"
#. module: crm
#: model:email.template,subject:crm.email_template_opportunity_mail
@ -589,6 +636,8 @@ msgid ""
"Reminder on Lead: [[object.id ]] [[object.partner_id and 'of ' "
"+object.partner_id.name or '']]"
msgstr ""
"Herinnering voor Lead: [[object.id ]] [[object.partner_id and 'van ' "
"+object.partner_id.name or '']]"
#. module: crm
#: view:crm.segmentation:0
@ -608,7 +657,7 @@ msgstr "De code van het verkoopteam moet uniek zijn"
#. module: crm
#: help:crm.lead,email_from:0
msgid "Email address of the contact"
msgstr ""
msgstr "E-mailadres van de contactpersoon"
#. module: crm
#: selection:crm.case.stage,state:0
@ -629,6 +678,13 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Klik als u een nieuwe categorie wilt maken.\n"
" </p><p>\n"
" Maak specifieke telefooncategorieën om beter de gesprekstypen\n"
" op te volgen in het systeem.\n"
" </p>\n"
" "
#. module: crm
#: help:crm.case.section,reply_to:0
@ -734,12 +790,12 @@ msgstr "Televisie"
#. module: crm
#: model:ir.actions.act_window,name:crm.action_crm_send_mass_convert
msgid "Convert to opportunities"
msgstr ""
msgstr "Omzetten naar opportuniteit"
#. module: crm
#: model:ir.model,name:crm.model_sale_config_settings
msgid "sale.config.settings"
msgstr ""
msgstr "sale.config.settings"
#. module: crm
#: view:crm.segmentation:0
@ -749,7 +805,7 @@ msgstr "Verwerking stoppen"
#. module: crm
#: field:crm.case.section,alias_id:0
msgid "Alias"
msgstr ""
msgstr "Alias"
#. module: crm
#: view:crm.phonecall:0
@ -761,6 +817,8 @@ msgstr "Telefoongesprekken zoeken"
msgid ""
"Leads/Opportunities that are assigned to one of the sale teams I manage"
msgstr ""
"Leads/Opportuniteiten die zijn toegewezen aan een van de verkoopteams onder "
"mijn beheer"
#. module: crm
#: field:calendar.attendee,categ_id:0
@ -781,7 +839,7 @@ msgstr "Van %s : %s"
#. module: crm
#: view:crm.lead2opportunity.partner.mass:0
msgid "Convert to Opportunities"
msgstr ""
msgstr "Omzetten naar opportuniteit"
#. module: crm
#: view:crm.lead2opportunity.partner:0
@ -790,7 +848,7 @@ msgstr ""
#: view:crm.opportunity2phonecall:0
#: view:crm.phonecall2phonecall:0
msgid "or"
msgstr ""
msgstr "of"
#. module: crm
#: field:crm.lead.report,create_date:0
@ -809,6 +867,8 @@ msgid ""
"Link between stages and sales teams. When set, this limitate the current "
"stage to the selected sales teams."
msgstr ""
"Koppeling tussen fasen en verkoopteams. Deze maken de huidige fase enkel "
"toegankelijk voor de gekozen verkoopteams."
#. module: crm
#: view:crm.case.stage:0
@ -847,7 +907,7 @@ msgstr "Relatiecategorie"
#. module: crm
#: field:crm.lead,probability:0
msgid "Success Rate (%)"
msgstr ""
msgstr "Slagingskans (%)"
#. module: crm
#: field:crm.segmentation,sales_purchase_active:0
@ -889,7 +949,7 @@ msgstr "Maart"
#. module: crm
#: view:crm.lead:0
msgid "Send Email"
msgstr ""
msgstr "E-mail verzenden"
#. module: crm
#: code:addons/crm/wizard/crm_lead_to_opportunity.py:89
@ -919,6 +979,8 @@ msgid ""
"Opportunities that are assigned to either me or one of the sale teams I "
"manage"
msgstr ""
"Opportuniteiten die zijn toegewezen aan een van de verkoopteams onder mijn "
"beheer of aan mij"
#. module: crm
#: help:crm.case.section,resource_calendar_id:0
@ -984,6 +1046,9 @@ msgid ""
"Allows you to track your customers/suppliers claims and grievances.\n"
" This installs the module crm_claim."
msgstr ""
"Hiermee kunt u klachten en problemen van klanten/ aan leveranciers "
"opvolgen.\n"
" Hiermee installeert u de module crm_claim."
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead6
@ -1058,7 +1123,7 @@ msgstr "Fase"
#. module: crm
#: view:crm.phonecall.report:0
msgid "Phone Calls that are assigned to me"
msgstr ""
msgstr "Aan mij toegewezen telefoongesprekken"
#. module: crm
#: field:crm.lead,user_login:0
@ -1086,11 +1151,13 @@ msgid ""
"Allows you to communicate with Customer, process Customer query, and "
"provide better help and support. This installs the module crm_helpdesk."
msgstr ""
"Hiermee kunt u met de klant communiceren, vragen beantwoorden en betere "
"ondersteuning verlenen. Hiermee installeert u de module crm_helpdesk."
#. module: crm
#: view:crm.lead:0
msgid "Delete"
msgstr ""
msgstr "Verwijderen"
#. module: crm
#: model:mail.message.subtype,description:crm.mt_lead_create
@ -1100,7 +1167,7 @@ msgstr ""
#. module: crm
#: view:crm.lead:0
msgid "í"
msgstr ""
msgstr "í"
#. module: crm
#: selection:crm.lead.report,creation_month:0
@ -1141,12 +1208,12 @@ msgstr ""
#. module: crm
#: view:crm.lead:0
msgid "oe_kanban_text_red"
msgstr ""
msgstr "oe_kanban_text_red"
#. module: crm
#: model:ir.ui.menu,name:crm.menu_crm_payment_mode_act
msgid "Payment Modes"
msgstr ""
msgstr "Betalingswijzen"
#. module: crm
#: field:crm.lead.report,opening_date:0
@ -1193,6 +1260,9 @@ msgid ""
"This field is used to distinguish stages related to Leads from stages "
"related to Opportunities, or to specify stages available for both types."
msgstr ""
"Dit veld dient om een onderscheid te maken tussen de fasen voor leads en die "
"voor opportuniteiten, of om fasen in te stellen die voor beide typen van "
"toepassing zijn."
#. module: crm
#: model:mail.message.subtype,name:crm.mt_lead_create
@ -1234,7 +1304,7 @@ msgstr "onbekend"
#: field:crm.lead,message_is_follower:0
#: field:crm.phonecall,message_is_follower:0
msgid "Is a Follower"
msgstr ""
msgstr "Is een volger"
#. module: crm
#: field:crm.opportunity2phonecall,date:0
@ -1247,7 +1317,7 @@ msgstr "Datum"
#. module: crm
#: model:crm.case.section,name:crm.crm_case_section_4
msgid "Online Support"
msgstr ""
msgstr "Onlineondersteuning"
#. module: crm
#: view:crm.lead.report:0
@ -1273,6 +1343,10 @@ msgid ""
"set to 'Done'. If the case needs to be reviewed then the Status is set to "
"'Pending'."
msgstr ""
"De status wordt op 'Voorlopig' gezet als de zaak wordt gemaakt. Als de zaak "
"lopende is, wordt de status op 'Open' gezet. Als de zaak is behandeld, wordt "
"de status op 'Gereed' gezet. Als de zaak moet worden bekeken, wordt de "
"status op 'Wachtend' gezet."
#. module: crm
#: model:crm.case.section,name:crm.crm_case_section_1
@ -1306,7 +1380,7 @@ msgstr "Segmenteringsomschrijving"
#. module: crm
#: view:crm.lead:0
msgid "Lead Description"
msgstr ""
msgstr "Leadomschrijving"
#. module: crm
#: code:addons/crm/crm_lead.py:565
@ -1317,7 +1391,7 @@ msgstr "Samengevoegde opportuniteiten"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor7
msgid "Consulting"
msgstr ""
msgstr "Consulting"
#. module: crm
#: field:crm.case.section,code:0
@ -1327,7 +1401,7 @@ msgstr "Code"
#. module: crm
#: view:sale.config.settings:0
msgid "Features"
msgstr ""
msgstr "Opties"
#. module: crm
#: field:crm.case.section,child_ids:0
@ -1342,7 +1416,7 @@ msgstr "Telefoongesprekken in status Uit te voeren en Open."
#. module: crm
#: field:crm.lead2opportunity.partner.mass,user_ids:0
msgid "Salesmen"
msgstr ""
msgstr "Verkopers"
#. module: crm
#: view:crm.lead:0
@ -1362,12 +1436,12 @@ msgstr "Annuleren"
#. module: crm
#: view:crm.lead:0
msgid "Opportunities Assigned to Me or My Team(s)"
msgstr ""
msgstr "Opportuniteiten voor mij of mijn team(s)"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor4
msgid "Information"
msgstr ""
msgstr "Informatie"
#. module: crm
#: view:crm.lead.report:0
@ -1389,7 +1463,7 @@ msgstr ""
#: field:crm.lead2opportunity.partner.mass,action:0
#: field:crm.partner.binding,action:0
msgid "Related Customer"
msgstr ""
msgstr "Gekoppelde klant"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor8
@ -1406,12 +1480,12 @@ msgstr "Lead/opportuniteit"
#: model:ir.actions.act_window,name:crm.action_merge_opportunities
#: model:ir.actions.act_window,name:crm.merge_opportunity_act
msgid "Merge leads/opportunities"
msgstr ""
msgstr "Leads/opportuniteiten samenvoegen"
#. module: crm
#: help:crm.case.stage,sequence:0
msgid "Used to order stages. Lower is better."
msgstr ""
msgstr "WOrdt gebruikt om fasen te rangschikken. Lager is beter."
#. module: crm
#: model:ir.actions.act_window,name:crm.crm_phonecall_categ_action
@ -1426,7 +1500,7 @@ msgstr "Leads/opportuniteiten in status Open."
#. module: crm
#: model:ir.model,name:crm.model_res_users
msgid "Users"
msgstr ""
msgstr "Gebruikers"
#. module: crm
#: model:mail.message.subtype,name:crm.mt_lead_stage
@ -1484,7 +1558,7 @@ msgstr "Naam"
#. module: crm
#: view:crm.lead.report:0
msgid "Leads/Opportunities that are assigned to me"
msgstr ""
msgstr "Leads/opportuniteiten die aan mij zijn toegekend"
#. module: crm
#: field:crm.lead.report,date_closed:0
@ -1502,12 +1576,12 @@ msgstr "Mijn zaken"
#: help:crm.lead,message_ids:0
#: help:crm.phonecall,message_ids:0
msgid "Messages and communication history"
msgstr ""
msgstr "Berichten en communicatiehistoriek"
#. module: crm
#: view:crm.lead:0
msgid "Show Countries"
msgstr ""
msgstr "Landen tonen"
#. module: crm
#: view:crm.lead:0
@ -1531,7 +1605,7 @@ msgstr "Prospect omzetten naar relatie"
#. module: crm
#: model:ir.model,name:crm.model_crm_payment_mode
msgid "CRM Payment Mode"
msgstr ""
msgstr "CRM betalingswijze"
#. module: crm
#: view:crm.lead.report:0
@ -1554,7 +1628,7 @@ msgstr "Groeperen op..."
#. module: crm
#: view:crm.merge.opportunity:0
msgid "Merge Leads/Opportunities"
msgstr ""
msgstr "Leads/opportuniteiten samenvoegen"
#. module: crm
#: field:crm.case.section,parent_id:0
@ -1566,7 +1640,7 @@ msgstr "Hoofdteam"
#: selection:crm.lead2opportunity.partner.mass,action:0
#: selection:crm.partner.binding,action:0
msgid "Do not link to a customer"
msgstr ""
msgstr "Geen relatie koppelen"
#. module: crm
#: field:crm.lead,date_action:0
@ -1580,11 +1654,14 @@ msgid ""
"stage. For example, if a stage is related to the status 'Close', when your "
"document reaches this stage, it is automatically closed."
msgstr ""
"De status van uw document wordt automatisch gewijzigd in de functie van de "
"gekozen fase. Als een fase gekoppeld is aan de status 'Gesloten', dan wordt "
"het document automatisch gesloten als het in deze status komt."
#. module: crm
#: view:crm.lead2opportunity.partner.mass:0
msgid "Assign opportunities to"
msgstr ""
msgstr "Opportuniteiten toewijzen aan"
#. module: crm
#: model:crm.case.categ,name:crm.categ_phone1
@ -1600,12 +1677,12 @@ msgstr "Maand van gesprek"
#: code:addons/crm/crm_phonecall.py:290
#, python-format
msgid "Partner has been <b>created</b>."
msgstr ""
msgstr "Relatie is <b>gemaakt</b>."
#. module: crm
#: field:sale.config.settings,module_crm_claim:0
msgid "Manage Customer Claims"
msgstr ""
msgstr "Klachten van klanten opvolgen"
#. module: crm
#: model:ir.actions.act_window,help:crm.action_report_crm_lead
@ -1618,7 +1695,7 @@ msgstr ""
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor3
msgid "Services"
msgstr ""
msgstr "Diensten"
#. module: crm
#: selection:crm.lead,priority:0
@ -1657,7 +1734,7 @@ msgstr "Antwoord aan"
#. module: crm
#: view:crm.lead:0
msgid "Display"
msgstr ""
msgstr "Weergeven"
#. module: crm
#: view:board.board:0
@ -1693,12 +1770,12 @@ msgstr "Extra informatie"
#. module: crm
#: view:crm.lead:0
msgid "Fund Raising"
msgstr ""
msgstr "Fondsenwerving"
#. module: crm
#: view:crm.lead:0
msgid "Edit..."
msgstr ""
msgstr "Bewerken…"
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead5
@ -1730,13 +1807,15 @@ msgstr "Lead naar opportuniteit / relatie"
#: help:crm.lead,partner_id:0
msgid "Linked partner (optional). Usually created when converting the lead."
msgstr ""
"Gekoppelde relatie (optioneel). Doorgaans gemaakt bij het omzetten van de "
"lead."
#. module: crm
#: field:crm.lead,payment_mode:0
#: view:crm.payment.mode:0
#: model:ir.actions.act_window,name:crm.action_crm_payment_mode
msgid "Payment Mode"
msgstr ""
msgstr "Betalingswijze"
#. module: crm
#: model:ir.model,name:crm.model_crm_lead2opportunity_partner_mass
@ -1746,19 +1825,19 @@ msgstr "Vele leads naar opportuniteit / relatie"
#. module: crm
#: view:sale.config.settings:0
msgid "On Mail Server"
msgstr ""
msgstr "Op mailserver"
#. module: crm
#: model:ir.actions.act_window,name:crm.open_board_statistical_dash
#: model:ir.ui.menu,name:crm.menu_board_statistics_dash
msgid "CRM"
msgstr ""
msgstr "CRM"
#. module: crm
#: model:ir.actions.act_window,name:crm.crm_segmentation_tree-act
#: model:ir.ui.menu,name:crm.menu_crm_segmentation-act
msgid "Contacts Segmentation"
msgstr ""
msgstr "Contactpersoonsegmentering"
#. module: crm
#: model:process.node,note:crm.process_node_meeting0
@ -1773,7 +1852,7 @@ msgstr "Televerkoop"
#. module: crm
#: view:crm.lead:0
msgid "Leads Assigned to Me or My Team(s)"
msgstr ""
msgstr "Leads voor mij of mijn team(s)"
#. module: crm
#: model:ir.model,name:crm.model_crm_segmentation_line
@ -1817,7 +1896,7 @@ msgstr "Lead / klant"
#. module: crm
#: model:crm.case.section,name:crm.crm_case_section_2
msgid "Support Department"
msgstr ""
msgstr "Supportafdeling"
#. module: crm
#: view:crm.lead.report:0
@ -1881,13 +1960,13 @@ msgstr ""
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor5
msgid "Design"
msgstr ""
msgstr "Ontwerp"
#. module: crm
#: selection:crm.lead2opportunity.partner,name:0
#: selection:crm.lead2opportunity.partner.mass,name:0
msgid "Merge with existing opportunities"
msgstr ""
msgstr "Samenvoegen met bestaande opportuniteiten"
#. module: crm
#: view:crm.phonecall.report:0
@ -1912,6 +1991,8 @@ msgid ""
"The name of the future partner company that will be created while converting "
"the lead into opportunity"
msgstr ""
"De naam van de toekomstige relatie die zal worden gemaakt als van de lead "
"een opportuniteit wordt gemaakt."
#. module: crm
#: field:crm.opportunity2phonecall,note:0
@ -1945,7 +2026,7 @@ msgstr "Openstaande opportuniteiten"
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead2
msgid "Email Campaign - Services"
msgstr ""
msgstr "E-mailcampagne - Diensten"
#. module: crm
#: selection:crm.case.stage,state:0
@ -2018,7 +2099,7 @@ msgstr ""
#: selection:crm.lead2opportunity.partner.mass,action:0
#: selection:crm.partner.binding,action:0
msgid "Create a new customer"
msgstr ""
msgstr "Een nieuwe klant maken"
#. module: crm
#: field:crm.lead.report,deadline_day:0
@ -2028,7 +2109,7 @@ msgstr "Verw. sluiting"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor2
msgid "Software"
msgstr ""
msgstr "Software"
#. module: crm
#: field:crm.case.section,change_responsible:0
@ -2063,12 +2144,12 @@ msgstr "Plaats"
#. module: crm
#: selection:crm.case.stage,type:0
msgid "Both"
msgstr ""
msgstr "Beide"
#. module: crm
#: view:crm.phonecall:0
msgid "Call Done"
msgstr ""
msgstr "Gesprek uitgevoerd"
#. module: crm
#: view:crm.phonecall:0
@ -2079,12 +2160,12 @@ msgstr "Verantwoordelijke"
#. module: crm
#: model:crm.case.section,name:crm.crm_case_section_3
msgid "Direct Marketing"
msgstr ""
msgstr "Direct Marketing"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor1
msgid "Product"
msgstr ""
msgstr "Product"
#. module: crm
#: field:crm.lead.report,creation_year:0
@ -2094,7 +2175,7 @@ msgstr "Creatiejaar"
#. module: crm
#: view:crm.lead2opportunity.partner.mass:0
msgid "Conversion Options"
msgstr ""
msgstr "Conversieopties"
#. module: crm
#: view:crm.case.section:0
@ -2106,7 +2187,7 @@ msgstr ""
#. module: crm
#: view:crm.lead:0
msgid "Address"
msgstr ""
msgstr "Adres"
#. module: crm
#: help:crm.case.section,alias_id:0
@ -2114,6 +2195,8 @@ msgid ""
"The email address associated with this team. New emails received will "
"automatically create new leads assigned to the team."
msgstr ""
"Het e-mailadres van het team. Nieuwe e-mails worden automatisch als lead "
"gemaakt en toegekend aan dit team."
#. module: crm
#: view:crm.lead:0
@ -2172,7 +2255,7 @@ msgstr "Verder verwerken"
#: selection:crm.lead2opportunity.partner.mass,name:0
#: model:ir.actions.act_window,name:crm.action_crm_lead2opportunity_partner
msgid "Convert to opportunity"
msgstr ""
msgstr "Omzetten naar opportuniteit"
#. module: crm
#: field:crm.opportunity2phonecall,user_id:0
@ -2214,6 +2297,8 @@ msgid ""
"This stage is not visible, for example in status bar or kanban view, when "
"there are no records in that stage to display."
msgstr ""
"Deze fase is niet zichtbaar, vb. in statusbalk of kanbanweergave, als er "
"zich geen records in deze fase bevinden."
#. module: crm
#: field:crm.lead.report,nbr:0
@ -2229,12 +2314,12 @@ msgstr "Verkoopteam aan wie de zaak toebehoort"
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead6
msgid "Banner Ads"
msgstr ""
msgstr "Kopadvertenties"
#. module: crm
#: field:crm.merge.opportunity,opportunity_ids:0
msgid "Leads/Opportunities"
msgstr ""
msgstr "Leads/opportuniteiten"
#. module: crm
#: field:crm.lead,fax:0
@ -2279,17 +2364,17 @@ msgstr "Objectnaam"
#. module: crm
#: view:crm.phonecall:0
msgid "Phone Calls Assigned to Me or My Team(s)"
msgstr ""
msgstr "Telefoongesprekken voor mij of mijn team(s)"
#. module: crm
#: view:crm.lead:0
msgid "Reset"
msgstr ""
msgstr "Herstellen"
#. module: crm
#: view:sale.config.settings:0
msgid "After-Sale Services"
msgstr ""
msgstr "Klantenservice"
#. module: crm
#: field:crm.case.section,message_ids:0
@ -2344,7 +2429,7 @@ msgstr ""
#. module: crm
#: field:crm.case.stage,state:0
msgid "Related Status"
msgstr ""
msgstr "Gekoppelde status"
#. module: crm
#: field:crm.phonecall,name:0
@ -2365,7 +2450,7 @@ msgstr "Een gesprek plannen/noteren"
#. module: crm
#: view:crm.merge.opportunity:0
msgid "Select Leads/Opportunities"
msgstr ""
msgstr "Leads/opportuniteiten kiezen"
#. module: crm
#: selection:crm.phonecall,state:0
@ -2390,7 +2475,7 @@ msgstr "Bevestigen"
#. module: crm
#: view:crm.lead:0
msgid "Unread messages"
msgstr ""
msgstr "Ongelezen berichten"
#. module: crm
#: field:crm.phonecall.report,section_id:0
@ -2407,7 +2492,7 @@ msgstr "Optionele expressie"
#: field:crm.lead,message_follower_ids:0
#: field:crm.phonecall,message_follower_ids:0
msgid "Followers"
msgstr ""
msgstr "Volgers"
#. module: crm
#: model:ir.actions.act_window,help:crm.crm_case_category_act_leads_all
@ -2430,7 +2515,7 @@ msgstr ""
#. module: crm
#: field:sale.config.settings,fetchmail_lead:0
msgid "Create leads from incoming mails"
msgstr ""
msgstr "Leads maken van binnenkomende mails"
#. module: crm
#: view:crm.lead:0
@ -2481,7 +2566,7 @@ msgstr "Opportuniteiten maken van leads"
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead3
msgid "Email Campaign - Products"
msgstr ""
msgstr "E-mailcampagne - Producten"
#. module: crm
#: model:ir.actions.act_window,help:crm.crm_case_categ_phone_incoming0
@ -2509,7 +2594,7 @@ msgstr "Allereerste contact met een nieuwe prospect"
#. module: crm
#: view:res.partner:0
msgid "Calls"
msgstr ""
msgstr "Gesprekken"
#. module: crm
#: field:crm.case.stage,on_change:0
@ -2519,7 +2604,7 @@ msgstr "Kans automatisch wijzigen"
#. module: crm
#: view:crm.phonecall.report:0
msgid "My Phone Calls"
msgstr ""
msgstr "Mijn telefoongesprekken"
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead3
@ -2530,7 +2615,7 @@ msgstr "Kwalificatie"
#: field:crm.lead2opportunity.partner,name:0
#: field:crm.lead2opportunity.partner.mass,name:0
msgid "Conversion Action"
msgstr ""
msgstr "Conversieactie"
#. module: crm
#: model:ir.actions.act_window,help:crm.crm_lead_categ_action
@ -2606,7 +2691,7 @@ msgstr "Verw. sluitingsjaar"
#. module: crm
#: model:ir.actions.client,name:crm.action_client_crm_menu
msgid "Open Sale Menu"
msgstr ""
msgstr "Het verkoopmenu openen"
#. module: crm
#: field:crm.lead,date_open:0
@ -2629,12 +2714,12 @@ msgstr "Een gesprek plannen/noteren"
#. module: crm
#: field:crm.lead,planned_cost:0
msgid "Planned Costs"
msgstr ""
msgstr "Geplande kosten"
#. module: crm
#: help:crm.lead,date_deadline:0
msgid "Estimate of the date on which the opportunity will be won."
msgstr ""
msgstr "Verwachte datum waarop de opportuniteit kan worden gerealiseerd."
#. module: crm
#: help:crm.lead,email_cc:0
@ -2698,7 +2783,7 @@ msgstr "Straat 2"
#. module: crm
#: field:sale.config.settings,module_crm_helpdesk:0
msgid "Manage Helpdesk and Support"
msgstr ""
msgstr "Helpdesk en ondersteuning"
#. module: crm
#: field:crm.lead.report,delay_open:0
@ -2785,7 +2870,7 @@ msgstr "Gesprek noteren"
#. module: crm
#: help:sale.config.settings,group_fund_raising:0
msgid "Allows you to trace and manage your activities for fund raising."
msgstr ""
msgstr "Hiermee kunt u activiteiten voor fondsenwerving beheren"
#. module: crm
#: field:crm.meeting,phonecall_id:0
@ -2797,6 +2882,8 @@ msgstr "Telefoongesprek"
#: view:crm.phonecall.report:0
msgid "Phone calls that are assigned to one of the sale teams I manage"
msgstr ""
"Telefoongesprekken die zijn toegewezen aan een van de verkoopteams onder "
"mijn beheer"
#. module: crm
#: view:crm.lead:0
@ -2806,7 +2893,7 @@ msgstr "Creatiedatum"
#. module: crm
#: view:crm.lead:0
msgid "at"
msgstr ""
msgstr "bij"
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead1
@ -2875,7 +2962,7 @@ msgstr ""
#. module: crm
#: view:crm.lead:0
msgid "Internal Notes"
msgstr ""
msgstr "Interne notities"
#. module: crm
#: view:crm.lead:0
@ -2895,7 +2982,7 @@ msgstr "Straat"
#. module: crm
#: field:crm.lead,referred:0
msgid "Referred By"
msgstr ""
msgstr "Doorverwezen via"
#. module: crm
#: view:crm.phonecall:0
@ -2940,6 +3027,7 @@ msgstr "Verloren"
#, python-format
msgid "Closed/Cancelled leads cannot be converted into opportunities."
msgstr ""
"Gesloten/geannuleerde leads kunnen niet in een opportuniteit worden omgezet"
#. module: crm
#: view:crm.lead:0
@ -4199,3 +4287,6 @@ msgstr ""
#~ msgid "Recurrent"
#~ msgstr "Recurrent"
#~ msgid "Conditions on Case Fields"
#~ msgstr "Voorwaardevelden"

View File

@ -82,7 +82,7 @@
groups="base.group_multi_salesteams"/>
<field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]" />
<field name="type_id"/>
<field name="channel_id"/>

View File

@ -64,7 +64,7 @@
groups="base.group_multi_salesteams"/>
<field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="creation_date"/>
<field name="opening_date"/>

View File

@ -4,8 +4,7 @@
Mail script will fetch his request from mail server. Then I process that mail after read EML file.
-
!python {model: mail.thread}: |
from openerp import addons
request_file = open(addons.get_module_resource('crm','test', 'customer_request.eml'),'rb')
request_file = open(openerp.modules.module.get_module_resource('crm','test', 'customer_request.eml'),'rb')
request_message = request_file.read()
self.message_process(cr, uid, 'crm.lead', request_message)
-

View File

@ -201,7 +201,7 @@
<filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]"/>
<separator/>
<filter string="Unassigned Claims" icon="terp-personal-" domain="[('user_id','=', False)]" help="Unassigned Claims" />
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" help="Partner" context="{'group_by':'partner_id'}"/>

View File

@ -65,7 +65,7 @@
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"
groups="base.group_multi_salesteams"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]"/>
<field name="categ_id" domain="[('object_id.model', '=', 'crm.claim')]"/>
<field name="priority"/>

View File

@ -4,8 +4,7 @@
Mail script will be fetched him request from mail server. so I process that mail after read EML file
-
!python {model: mail.thread}: |
from openerp import addons
request_file = open(addons.get_module_resource('crm_claim','test', 'customer_claim.eml'),'rb')
request_file = open(openerp.modules.module.get_module_resource('crm_claim','test', 'customer_claim.eml'),'rb')
request_message = request_file.read()
self.message_process(cr, uid, 'crm.claim', request_message)
-

View File

@ -152,7 +152,7 @@
<separator/>
<filter string="Assigned to Me or My Sales Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('section_id.member_ids', 'in', [uid])]"
help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" />
<field name="partner_id" />
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<field name="section_id" string="Sales Team" groups="base.group_multi_salesteams"/>
<group expand="0" string="Group By...">

View File

@ -62,6 +62,7 @@
<field name="user_id" string="Salesperson"/>
<field name="section_id" string="Sales Team" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<group expand="0" string="Extended Filters..." groups="base.group_no_one">
<field name="priority" string="Priority"/>
<field name="categ_id"/>

View File

@ -4,8 +4,7 @@
Mail script will be fetched him request from mail server. so I process that mail after read EML file
-
!python {model: mail.thread}: |
from openerp import addons
request_file = open(addons.get_module_resource('crm_helpdesk','test', 'customer_question.eml'),'rb')
request_file = open(openerp.modules.module.get_module_resource('crm_helpdesk','test', 'customer_question.eml'),'rb')
request_message = request_file.read()
self.message_process(cr, uid, 'crm.helpdesk', request_message)
-

View File

@ -47,10 +47,9 @@
-
!python {model: ir.attachment}: |
from document_webdav import test_davclient as te
import addons
dc = te.DAVClient()
dc.get_creds(self, cr, uid)
tdp = addons.get_module_resource('document_webdav', 'test_davclient.py')
tdp = openerp.modules.module.get_module_resource('document_webdav', 'test_davclient.py')
res = dc.gd_put(path=cr.dbname+'/Documents/test_davclient.py', srcpath=tdp)
-
I will try to get the file from the root
@ -60,5 +59,5 @@
import addons
dc = te.DAVClient()
dc.get_creds(self, cr, uid)
tdp = addons.get_module_resource('document_webdav', 'test_davclient.py')
tdp = openerp.modules.module.get_module_resource('document_webdav', 'test_davclient.py')
res = dc.gd_get(path=cr.dbname+'/Documents/test_davclient.py', crange=(4,508), compare=tdp)

View File

@ -608,7 +608,7 @@ try:
if base_path and base_path == '/':
dir_path = config.get_misc('static-http', 'dir_path', False)
else:
dir_path = openerp.addons.get_module_resource('document_webdav','public_html')
dir_path = openerp.modules.module.get_module_resource('document_webdav','public_html')
# an _ugly_ hack: we put that dir back in tools.config.misc, so that
# the StaticHttpHandler can find its dir_path.
config.misc.setdefault('static-http',{})['dir_path'] = dir_path

View File

@ -0,0 +1,489 @@
# Dutch (Belgium) 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-04-26 16:28+0000\n"
"Last-Translator: Els Van Vossel (Agaplan) <Unknown>\n"
"Language-Team: Dutch (Belgium) <nl_BE@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-04-27 05:44+0000\n"
"X-Generator: Launchpad (build 16580)\n"
#. module: email_template
#: field:email.template,email_from:0
#: field:email_template.preview,email_from:0
msgid "From"
msgstr "Van"
#. module: email_template
#: field:mail.compose.message,template_id:0
msgid "Template"
msgstr "Sjabloon"
#. module: email_template
#: help:email.template,ref_ir_value:0
#: help:email_template.preview,ref_ir_value:0
msgid "Sidebar button to open the sidebar action"
msgstr ""
#. module: email_template
#: field:res.partner,opt_out:0
msgid "Opt-Out"
msgstr "Uitschrijven"
#. module: email_template
#: field:email.template,email_to:0
#: field:email_template.preview,email_to:0
msgid "To (Emails)"
msgstr "Naar (E-mails)"
#. module: email_template
#: field:email.template,mail_server_id:0
#: field:email_template.preview,mail_server_id:0
msgid "Outgoing Mail Server"
msgstr "Uitgaande mailserver"
#. module: email_template
#: help:email.template,ref_ir_act_window:0
#: help:email_template.preview,ref_ir_act_window:0
msgid ""
"Sidebar action to make this template available on records of the related "
"document model"
msgstr ""
#. module: email_template
#: field:email.template,model_object_field:0
#: field:email_template.preview,model_object_field:0
msgid "Field"
msgstr "Veld"
#. module: email_template
#: help:email.template,email_from:0
#: help:email_template.preview,email_from:0
msgid "Sender address (placeholders may be used here)"
msgstr ""
"Adres van de afzender (variabele aanduidingen kunnen hier worden gebruikt)"
#. module: email_template
#: view:email.template:0
msgid "Remove context action"
msgstr "Contextactie verwijderen"
#. module: email_template
#: help:email.template,mail_server_id:0
#: help:email_template.preview,mail_server_id:0
msgid ""
"Optional preferred server for outgoing mails. If not set, the highest "
"priority one will be used."
msgstr ""
#. module: email_template
#: field:email.template,report_name:0
#: field:email_template.preview,report_name:0
msgid "Report Filename"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Preview"
msgstr ""
#. module: email_template
#: field:email.template,reply_to:0
#: field:email_template.preview,reply_to:0
msgid "Reply-To"
msgstr ""
#. module: email_template
#: view:mail.compose.message:0
msgid "Use template"
msgstr ""
#. module: email_template
#: field:email.template,body_html:0
#: field:email_template.preview,body_html:0
msgid "Body"
msgstr ""
#. module: email_template
#: code:addons/email_template/email_template.py:244
#, python-format
msgid "%s (copy)"
msgstr ""
#. module: email_template
#: help:email.template,user_signature:0
#: help:email_template.preview,user_signature:0
msgid ""
"If checked, the user's signature will be appended to the text version of the "
"message"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "SMTP Server"
msgstr ""
#. module: email_template
#: view:mail.compose.message:0
msgid "Save as new template"
msgstr ""
#. module: email_template
#: help:email.template,sub_object:0
#: help:email_template.preview,sub_object:0
msgid ""
"When a relationship field is selected as first field, this field shows the "
"document model the relationship goes to."
msgstr ""
#. module: email_template
#: model:ir.model,name:email_template.model_email_template
msgid "Email Templates"
msgstr ""
#. module: email_template
#: help:email.template,report_name:0
#: help:email_template.preview,report_name:0
msgid ""
"Name to use for the generated report file (may contain placeholders)\n"
"The extension can be omitted and will then come from the report type."
msgstr ""
#. module: email_template
#: field:email.template,ref_ir_act_window:0
#: field:email_template.preview,ref_ir_act_window:0
msgid "Sidebar action"
msgstr ""
#. module: email_template
#: help:email.template,lang:0
#: help:email_template.preview,lang:0
msgid ""
"Optional translation language (ISO code) to select when sending out an "
"email. If not set, the english version will be used. This should usually be "
"a placeholder expression that provides the appropriate language code, e.g. "
"${object.partner_id.lang.code}."
msgstr ""
#. module: email_template
#: field:email_template.preview,res_id:0
msgid "Sample Document"
msgstr ""
#. module: email_template
#: help:email.template,model_object_field:0
#: help:email_template.preview,model_object_field:0
msgid ""
"Select target field from the related document model.\n"
"If it is a relationship field you will be able to select a target field at "
"the destination of the relationship."
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Dynamic Value Builder"
msgstr ""
#. module: email_template
#: model:ir.actions.act_window,name:email_template.wizard_email_template_preview
msgid "Template Preview"
msgstr ""
#. module: email_template
#: view:mail.compose.message:0
msgid "Save as a new template"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid ""
"Display an option on related documents to open a composition wizard with "
"this template"
msgstr ""
#. module: email_template
#: help:email.template,email_cc:0
#: help:email_template.preview,email_cc:0
msgid "Carbon copy recipients (placeholders may be used here)"
msgstr ""
#. module: email_template
#: help:email.template,email_to:0
#: help:email_template.preview,email_to:0
msgid "Comma-separated recipient addresses (placeholders may be used here)"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Advanced"
msgstr ""
#. module: email_template
#: view:email_template.preview:0
msgid "Preview of"
msgstr ""
#. module: email_template
#: view:email_template.preview:0
msgid "Using sample document"
msgstr ""
#. module: email_template
#: view:email.template:0
#: model:ir.actions.act_window,name:email_template.action_email_template_tree_all
#: model:ir.ui.menu,name:email_template.menu_email_templates
msgid "Templates"
msgstr ""
#. module: email_template
#: field:email.template,name:0
#: field:email_template.preview,name:0
msgid "Name"
msgstr ""
#. module: email_template
#: field:email.template,lang:0
#: field:email_template.preview,lang:0
msgid "Language"
msgstr ""
#. module: email_template
#: model:ir.model,name:email_template.model_email_template_preview
msgid "Email Template Preview"
msgstr ""
#. module: email_template
#: view:email_template.preview:0
msgid "Email Preview"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid ""
"Remove the contextual action to use this template on related documents"
msgstr ""
#. module: email_template
#: field:email.template,copyvalue:0
#: field:email_template.preview,copyvalue:0
msgid "Placeholder Expression"
msgstr ""
#. module: email_template
#: field:email.template,sub_object:0
#: field:email_template.preview,sub_object:0
msgid "Sub-model"
msgstr ""
#. module: email_template
#: help:email.template,subject:0
#: help:email_template.preview,subject:0
msgid "Subject (placeholders may be used here)"
msgstr ""
#. module: email_template
#: help:email.template,reply_to:0
#: help:email_template.preview,reply_to:0
msgid "Preferred response address (placeholders may be used here)"
msgstr ""
#. module: email_template
#: field:email.template,ref_ir_value:0
#: field:email_template.preview,ref_ir_value:0
msgid "Sidebar Button"
msgstr ""
#. module: email_template
#: field:email.template,report_template:0
#: field:email_template.preview,report_template:0
msgid "Optional report to print and attach"
msgstr ""
#. module: email_template
#: help:email.template,null_value:0
#: help:email_template.preview,null_value:0
msgid "Optional value to use if the target field is empty"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Model"
msgstr ""
#. module: email_template
#: model:ir.model,name:email_template.model_mail_compose_message
msgid "Email composition wizard"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Add context action"
msgstr ""
#. module: email_template
#: help:email.template,model_id:0
#: help:email_template.preview,model_id:0
msgid "The kind of document with with this template can be used"
msgstr ""
#. module: email_template
#: field:email.template,email_recipients:0
#: field:email_template.preview,email_recipients:0
msgid "To (Partners)"
msgstr ""
#. module: email_template
#: field:email.template,auto_delete:0
#: field:email_template.preview,auto_delete:0
msgid "Auto Delete"
msgstr ""
#. module: email_template
#: help:email.template,copyvalue:0
#: help:email_template.preview,copyvalue:0
msgid ""
"Final placeholder expression, to be copy-pasted in the desired template "
"field."
msgstr ""
#. module: email_template
#: field:email.template,model:0
#: field:email_template.preview,model:0
msgid "Related Document Model"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Addressing"
msgstr ""
#. module: email_template
#: help:email.template,email_recipients:0
#: help:email_template.preview,email_recipients:0
msgid ""
"Comma-separated ids of recipient partners (placeholders may be used here)"
msgstr ""
#. module: email_template
#: field:email.template,attachment_ids:0
#: field:email_template.preview,attachment_ids:0
msgid "Attachments"
msgstr ""
#. module: email_template
#: code:addons/email_template/email_template.py:231
#, python-format
msgid "Deletion of the action record failed."
msgstr ""
#. module: email_template
#: field:email.template,email_cc:0
#: field:email_template.preview,email_cc:0
msgid "Cc"
msgstr ""
#. module: email_template
#: field:email.template,model_id:0
#: field:email_template.preview,model_id:0
msgid "Applies to"
msgstr ""
#. module: email_template
#: field:email.template,sub_model_object_field:0
#: field:email_template.preview,sub_model_object_field:0
msgid "Sub-field"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Email Details"
msgstr ""
#. module: email_template
#: code:addons/email_template/email_template.py:196
#, python-format
msgid "Send Mail (%s)"
msgstr ""
#. module: email_template
#: help:res.partner,opt_out:0
msgid ""
"If checked, this partner will not receive any automated email notifications, "
"such as the availability of invoices."
msgstr ""
#. module: email_template
#: help:email.template,auto_delete:0
#: help:email_template.preview,auto_delete:0
msgid "Permanently delete this email after sending it, to save space"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Group by..."
msgstr ""
#. module: email_template
#: help:email.template,sub_model_object_field:0
#: help:email_template.preview,sub_model_object_field:0
msgid ""
"When a relationship field is selected as first field, this field lets you "
"select the target field within the destination document model (sub-model)."
msgstr ""
#. module: email_template
#: code:addons/email_template/email_template.py:231
#, python-format
msgid "Warning"
msgstr ""
#. module: email_template
#: field:email.template,user_signature:0
#: field:email_template.preview,user_signature:0
msgid "Add Signature"
msgstr ""
#. module: email_template
#: model:ir.model,name:email_template.model_res_partner
msgid "Partner"
msgstr ""
#. module: email_template
#: field:email.template,null_value:0
#: field:email_template.preview,null_value:0
msgid "Default Value"
msgstr ""
#. module: email_template
#: help:email.template,attachment_ids:0
#: help:email_template.preview,attachment_ids:0
msgid ""
"You may attach files to this template, to be added to all emails created "
"from this template"
msgstr ""
#. module: email_template
#: help:email.template,body_html:0
#: help:email_template.preview,body_html:0
msgid "Rich-text/HTML version of the message (placeholders may be used here)"
msgstr ""
#. module: email_template
#: view:email.template:0
msgid "Contents"
msgstr ""
#. module: email_template
#: field:email.template,subject:0
#: field:email_template.preview,subject:0
msgid "Subject"
msgstr ""

View File

@ -19,10 +19,12 @@
#
##############################################################################
from openerp import addons
import logging
from openerp.modules.module import get_module_resource
from openerp.osv import fields, osv
from openerp import tools
_logger = logging.getLogger(__name__)
class hr_employee_category(osv.osv):
@ -259,7 +261,7 @@ class hr_employee(osv.osv):
return {'value': {'work_email' : work_email}}
def _get_default_image(self, cr, uid, context=None):
image_path = addons.get_module_resource('hr', 'static/src/img', 'default_image.png')
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 = {

View File

@ -52,6 +52,9 @@ class hr_expense_expense(osv.osv):
res[expense.id] = total
return res
def _get_expense_from_line(self, cr, uid, ids, context=None):
return [line.expense_id.id for line in self.pool.get('hr.expense.line').browse(cr, uid, ids, context=context)]
def _get_currency(self, cr, uid, context=None):
user = self.pool.get('res.users').browse(cr, uid, [uid], context=context)[0]
if user.company_id:
@ -84,7 +87,10 @@ class hr_expense_expense(osv.osv):
'account_move_id': fields.many2one('account.move', 'Ledger Posting'),
'line_ids': fields.one2many('hr.expense.line', 'expense_id', 'Expense Lines', readonly=True, states={'draft':[('readonly',False)]} ),
'note': fields.text('Note'),
'amount': fields.function(_amount, string='Total Amount', digits_compute=dp.get_precision('Account')),
'amount': fields.function(_amount, string='Total Amount', digits_compute=dp.get_precision('Account'),
store={
'hr.expense.line': (_get_expense_from_line, ['unit_amount','unit_quantity'], 10)
}),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'department_id':fields.many2one('hr.department','Department', readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True),

View File

@ -32,7 +32,7 @@
<field name="user_id" invisible="1"/>
<field name="name"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="amount"/>
<field name="amount" sum="Total Amount"/>
<field name="state"/>
</tree>
</field>

View File

@ -507,8 +507,9 @@ class hr_job(osv.osv):
def _auto_init(self, cr, context=None):
"""Installation hook to create aliases for all jobs and avoid constraint errors."""
self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job, self)._auto_init,
res = self.pool.get('mail.alias').migrate_to_alias(cr, self._name, self._table, super(hr_job,self)._auto_init,
self._columns['alias_id'], 'name', alias_prefix='job+', alias_defaults={'job_id': 'id'}, context=context)
return res
def create(self, cr, uid, vals, context=None):
create_context = dict(context, alias_model_name=self._name)

View File

@ -4,8 +4,7 @@
An applicant is interested in the job position. So he sends a resume by email.
-
!python {model: mail.thread}: |
from openerp import addons
request_file = open(addons.get_module_resource('hr_recruitment','test', 'resume.eml'),'rb')
request_file = open(openerp.modules.module.get_module_resource('hr_recruitment','test', 'resume.eml'),'rb')
request_message = request_file.read()
self.message_process(cr, uid, 'hr.applicant', request_message)
-

2
addons/im/__init__.py Normal file
View File

@ -0,0 +1,2 @@
import im

27
addons/im/__openerp__.py Normal file
View File

@ -0,0 +1,27 @@
{
'name' : 'Instant Messaging',
'version': '1.0',
'summary': 'Live Chat, Talks with Others',
'sequence': '18',
'category': 'Tools',
'complexity': 'easy',
'description':
"""
Instant Messaging
=================
Allows users to chat with each other in real time. Find other users easily and
chat in real time. It support several chats in parallel.
""",
'data': [
'security/ir.model.access.csv',
'security/im_security.xml',
],
'depends' : ['base'],
'js': ['static/src/js/*.js'],
'css': ['static/src/css/*.css'],
'qweb': ['static/src/xml/*.xml'],
'installable': True,
'auto_install': False,
'application': True,
}

351
addons/im/im.py Normal file
View File

@ -0,0 +1,351 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import openerp
import openerp.tools.config
import openerp.modules.registry
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
import datetime
from openerp.osv import osv, fields
import time
import logging
import json
import select
_logger = logging.getLogger(__name__)
def listen_channel(cr, channel_name, handle_message, check_stop=(lambda: False), check_stop_timer=60.):
"""
Begin a loop, listening on a PostgreSQL channel. This method does never terminate by default, you need to provide a check_stop
callback to do so. This method also assume that all notifications will include a message formated using JSON (see the
corresponding notify_channel() method).
:param db_name: database name
:param channel_name: the name of the PostgreSQL channel to listen
:param handle_message: function that will be called when a message is received. It takes one argument, the message
attached to the notification.
:type handle_message: function (one argument)
:param check_stop: function that will be called periodically (see the check_stop_timer argument). If it returns True
this function will stop to watch the channel.
:type check_stop: function (no arguments)
:param check_stop_timer: The maximum amount of time between calls to check_stop_timer (can be shorter if messages
are received).
"""
try:
conn = cr._cnx
cr.execute("listen " + channel_name + ";")
cr.commit();
stopping = False
while not stopping:
if check_stop():
stopping = True
break
if select.select([conn], [], [], check_stop_timer) == ([],[],[]):
pass
else:
conn.poll()
while conn.notifies:
message = json.loads(conn.notifies.pop().payload)
handle_message(message)
finally:
try:
cr.execute("unlisten " + channel_name + ";")
cr.commit()
except:
pass # can't do anything if that fails
def notify_channel(cr, channel_name, message):
"""
Send a message through a PostgreSQL channel. The message will be formatted using JSON. This method will
commit the given transaction because the notify command in Postgresql seems to work correctly when executed in
a separate transaction (despite what is written in the documentation).
:param cr: The cursor.
:param channel_name: The name of the PostgreSQL channel.
:param message: The message, must be JSON-compatible data.
"""
cr.commit()
cr.execute("notify " + channel_name + ", %s", [json.dumps(message)])
cr.commit()
POLL_TIMER = 30
DISCONNECTION_TIMER = POLL_TIMER + 5
WATCHER_ERROR_DELAY = 10
if openerp.evented:
import gevent
import gevent.event
class ImWatcher(object):
watchers = {}
@staticmethod
def get_watcher(db_name):
if not ImWatcher.watchers.get(db_name):
ImWatcher(db_name)
return ImWatcher.watchers[db_name]
def __init__(self, db_name):
self.db_name = db_name
ImWatcher.watchers[db_name] = self
self.waiting = 0
self.wait_id = 0
self.users = {}
self.users_watch = {}
gevent.spawn(self.loop)
def loop(self):
_logger.info("Begin watching on channel im_channel for database " + self.db_name)
stop = False
while not stop:
try:
registry = openerp.modules.registry.RegistryManager.get(self.db_name)
with registry.cursor() as cr:
listen_channel(cr, "im_channel", self.handle_message, self.check_stop)
stop = True
except:
# if something crash, we wait some time then try again
_logger.exception("Exception during watcher activity")
time.sleep(WATCHER_ERROR_DELAY)
_logger.info("End watching on channel im_channel for database " + self.db_name)
del ImWatcher.watchers[self.db_name]
def handle_message(self, message):
if message["type"] == "message":
for waiter in self.users.get(message["receiver"], {}).values():
waiter.set()
else: #type status
for waiter in self.users_watch.get(message["user"], {}).values():
waiter.set()
def check_stop(self):
return self.waiting == 0
def _get_wait_id(self):
self.wait_id += 1
return self.wait_id
def stop(self, user_id, watch_users, timeout=None):
wait_id = self._get_wait_id()
event = gevent.event.Event()
self.waiting += 1
self.users.setdefault(user_id, {})[wait_id] = event
for watch in watch_users:
self.users_watch.setdefault(watch, {})[wait_id] = event
try:
event.wait(timeout)
finally:
for watch in watch_users:
del self.users_watch[watch][wait_id]
if len(self.users_watch[watch]) == 0:
del self.users_watch[watch]
del self.users[user_id][wait_id]
if len(self.users[user_id]) == 0:
del self.users[user_id]
self.waiting -= 1
class LongPollingController(openerp.addons.web.http.Controller):
_cp_path = '/longpolling/im'
@openerp.addons.web.http.jsonrequest
def poll(self, req, last=None, users_watch=None, db=None, uid=None, password=None, uuid=None):
assert_uuid(uuid)
if not openerp.evented:
raise Exception("Not usable in a server not running gevent")
if db is not None:
req.session._db = db
req.session._uid = uid
req.session._password = password
req.session.model('im.user').im_connect(uuid=uuid, context=req.context)
my_id = req.session.model('im.user').get_by_user_id(uuid or req.session._uid, req.context)["id"]
num = 0
while True:
res = req.session.model('im.message').get_messages(last, users_watch, uuid=uuid, context=req.context)
if num >= 1 or len(res["res"]) > 0:
return res
last = res["last"]
num += 1
ImWatcher.get_watcher(res["dbname"]).stop(my_id, users_watch or [], POLL_TIMER)
@openerp.addons.web.http.jsonrequest
def activated(self, req):
return not not openerp.evented
@openerp.addons.web.http.jsonrequest
def gen_uuid(self, req):
import uuid
return "%s" % uuid.uuid1()
def assert_uuid(uuid):
if not isinstance(uuid, (str, unicode, type(None))):
raise Exception("%s is not a uuid" % uuid)
class im_message(osv.osv):
_name = 'im.message'
_order = "date desc"
_columns = {
'message': fields.char(string="Message", size=200, required=True),
'from_id': fields.many2one("im.user", "From", required= True, ondelete='cascade'),
'to_id': fields.many2one("im.user", "To", required=True, select=True, ondelete='cascade'),
'date': fields.datetime("Date", required=True, select=True),
}
_defaults = {
'date': lambda *args: datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}
def get_messages(self, cr, uid, last=None, users_watch=None, uuid=None, context=None):
assert_uuid(uuid)
users_watch = users_watch or []
# complex stuff to determine the last message to show
users = self.pool.get("im.user")
my_id = users.get_by_user_id(cr, uid, uuid or uid, context=context)["id"]
c_user = users.browse(cr, openerp.SUPERUSER_ID, my_id, context=context)
if last:
if c_user.im_last_received < last:
users.write(cr, openerp.SUPERUSER_ID, my_id, {'im_last_received': last}, context=context)
else:
last = c_user.im_last_received or -1
# how fun it is to always need to reorder results from read
mess_ids = self.search(cr, openerp.SUPERUSER_ID, [['id', '>', last], ['to_id', '=', my_id]], order="id", context=context)
mess = self.read(cr, openerp.SUPERUSER_ID, mess_ids, ["id", "message", "from_id", "date"], context=context)
index = {}
for i in xrange(len(mess)):
index[mess[i]["id"]] = mess[i]
mess = []
for i in mess_ids:
mess.append(index[i])
if len(mess) > 0:
last = mess[-1]["id"]
users_status = users.read(cr, openerp.SUPERUSER_ID, users_watch, ["im_status"], context=context)
return {"res": mess, "last": last, "dbname": cr.dbname, "users_status": users_status}
def post(self, cr, uid, message, to_user_id, uuid=None, context=None):
assert_uuid(uuid)
my_id = self.pool.get('im.user').get_by_user_id(cr, uid, uuid or uid)["id"]
self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_user_id}, context=context)
notify_channel(cr, "im_channel", {'type': 'message', 'receiver': to_user_id})
return False
class im_user(osv.osv):
_name = "im.user"
def _im_status(self, cr, uid, ids, something, something_else, context=None):
res = {}
current = datetime.datetime.now()
delta = datetime.timedelta(0, DISCONNECTION_TIMER)
data = self.read(cr, openerp.SUPERUSER_ID, ids, ["im_last_status_update", "im_last_status"], context=context)
for obj in data:
last_update = datetime.datetime.strptime(obj["im_last_status_update"], DEFAULT_SERVER_DATETIME_FORMAT)
res[obj["id"]] = obj["im_last_status"] and (last_update + delta) > current
return res
def search_users(self, cr, uid, domain, fields, limit, context=None):
# do not user openerp.SUPERUSER_ID, reserved to normal users
found = self.pool.get('res.users').search(cr, uid, domain, limit=limit, context=context)
found = self.get_by_user_ids(cr, uid, found, context=context)
return self.read(cr, uid, found, fields, context=context)
def im_connect(self, cr, uid, uuid=None, context=None):
assert_uuid(uuid)
return self._im_change_status(cr, uid, True, uuid, context)
def im_disconnect(self, cr, uid, uuid=None, context=None):
assert_uuid(uuid)
return self._im_change_status(cr, uid, False, uuid, context)
def _im_change_status(self, cr, uid, new_one, uuid=None, context=None):
assert_uuid(uuid)
id = self.get_by_user_id(cr, uid, uuid or uid, context=context)["id"]
current_status = self.read(cr, openerp.SUPERUSER_ID, id, ["im_status"], context=None)["im_status"]
self.write(cr, openerp.SUPERUSER_ID, id, {"im_last_status": new_one,
"im_last_status_update": datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context)
if current_status != new_one:
notify_channel(cr, "im_channel", {'type': 'status', 'user': id})
return True
def get_by_user_id(self, cr, uid, id, context=None):
ids = self.get_by_user_ids(cr, uid, [id], context=context)
return ids[0]
def get_by_user_ids(self, cr, uid, ids, context=None):
user_ids = [x for x in ids if isinstance(x, int)]
uuids = [x for x in ids if isinstance(x, (str, unicode))]
users = self.search(cr, openerp.SUPERUSER_ID, ["|", ["user", "in", user_ids], ["uuid", "in", uuids]], context=None)
records = self.read(cr, openerp.SUPERUSER_ID, users, ["user", "uuid"], context=None)
inside = {}
for i in records:
if i["user"]:
inside[i["user"][0]] = True
elif ["uuid"]:
inside[i["uuid"]] = True
not_inside = {}
for i in ids:
if not (i in inside):
not_inside[i] = True
for to_create in not_inside.keys():
if isinstance(to_create, int):
created = self.create(cr, openerp.SUPERUSER_ID, {"user": to_create}, context=context)
records.append({"id": created, "user": [to_create, ""]})
else:
created = self.create(cr, openerp.SUPERUSER_ID, {"uuid": to_create}, context=context)
records.append({"id": created, "uuid": to_create})
return records
def assign_name(self, cr, uid, uuid, name, context=None):
assert_uuid(uuid)
id = self.get_by_user_id(cr, uid, uuid or uid, context=context)["id"]
self.write(cr, openerp.SUPERUSER_ID, id, {"assigned_name": name}, context=context)
return True
def _get_name(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = record.assigned_name
if record.user:
res[record.id] = record.user.name
continue
return res
_columns = {
'name': fields.function(_get_name, type='char', size=200, string="Name", store=True, readonly=True),
'assigned_name': fields.char(string="Assigned Name", size=200, required=False),
'image': fields.related('user', 'image_small', type='binary', string="Image", readonly=True),
'user': fields.many2one("res.users", string="User", select=True, ondelete='cascade'),
'uuid': fields.char(string="UUID", size=50, select=True),
'im_last_received': fields.integer(string="Instant Messaging Last Received Message"),
'im_last_status': fields.boolean(strint="Instant Messaging Last Status"),
'im_last_status_update': fields.datetime(string="Instant Messaging Last Status Update"),
'im_status': fields.function(_im_status, string="Instant Messaging Status", type='boolean'),
}
_defaults = {
'im_last_received': -1,
'im_last_status': False,
'im_last_status_update': lambda *args: datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="message_rule_1" model="ir.rule">
<field name="name">Can only read messages that you sent or messages sent to you</field>
<field name="model_id" ref="model_im_message"/>
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
<field name="domain_force">["|", ('to_id.user', '=', user.id), ('from_id.user', '=', user.id)]</field>
<field name="perm_unlink" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
</record>
<record id="users_rule_1" model="ir.rule">
<field name="name">Can only modify your user</field>
<field name="model_id" ref="model_im_user"/>
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
<field name="domain_force">[('user', '=', user.id)]</field>
<field name="perm_unlink" eval="0"/>
<field name="perm_write" eval="1"/>
<field name="perm_read" eval="0"/>
<field name="perm_create" eval="0"/>
</record>
</data>
</openerp>

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_im_message,im.message,model_im_message,base.group_user,1,0,1,0
access_im_user,im.user,model_im_user,base.group_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_im_message im.message model_im_message base.group_user 1 0 1 0
3 access_im_user im.user model_im_user base.group_user 1 1 1 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,258 @@
.openerp .oe_im {
position: fixed;
background-color: #E8EBEF;
width: 220px;
border-left: 1px solid #AEB9BD;
}
/* button */
.openerp .oe_topbar_imbutton {
cursor: pointer;
}
/* search stuff */
.openerp .oe_im_frame_header {
position: relative;
background: #dedede;
background: -moz-linear-gradient(#fcfcfc, #dedede);
background: -webkit-gradient(linear, left top, left bottom, from(#fcfcfc), to(#dedede));
border-bottom: 1px solid border-color !important;
padding: 5px;
}
.openerp .oe_im_frame_header .oe_im_searchbox {
width: 168px;
padding: 1px 21px 1px 19px;
font-size: 13px;
-moz-border-radius: 13px;
-webkit-border-radius: 13px;
border-radius: 13px;
}
.openerp .oe_im_frame_header .oe_im_search_icon {
position: absolute;
color: #888;
top: 2px;
left: 9px;
font-size: 28px;
font-family: "entypoRegular" !important;
font-weight: 300 !important;
}
.openerp .oe_im_frame_header .oe_im_search_clear {
display: none;
position: absolute;
right: 11px;
top: 4px;
font-size: 26px;
color: #b6b6b6;
cursor: pointer;
}
.openerp .oe_im_frame_header .oe_im_search_clear:hover {
color: #888;
}
/* users */
.openerp .oe_im_users {
padding-bottom: 38px;
}
.openerp .oe_im_user {
position: relative;
padding: 2px 6px;
cursor: pointer;
font-size: 13px;
margin-bottom: 3px;
}
.openerp .oe_im_user:hover {
background: lightGrey;
}
.openerp .oe_im_user_clip {
display: inline-block;
width: 26px;
height: 26px;
margin-right: 4px;
-moz-box-shadow: 0 0 2px 1px rgba(0,0,0,0.25);
-webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
}
.openerp .oe_im_user_avatar {
width: 26px;
height: auto;
}
.openerp .oe_im_user_name {
width: 162px;
line-height: 26px;
padding-right: 15px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
position: relative;
}
.openerp .oe_im_user_online {
display: none;
position: absolute;
top: 9.5px;
right: 11px;
width: 11px;
height: 11px;
vertical-align: middle;
border: 0;
}
/* conversations */
.openerp .oe_im_chatview {
position: fixed;
overflow: hidden;
bottom: 6px;
margin-right: 6px;
background: rgba(60, 60, 60, 0.8);
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 0 3px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
width: 240px;
}
.openerp .oe_im_chatview .oe_im_chatview_disconnected {
display:none;
z-index: 100;
width: 100%;
background: #E8EBEF;
padding: 5px;
font-size: 11px;
color: #999;
line-height: 14px;
height: 28px;
overflow: hidden;
}
.openerp .oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_disconnected {
display: block;
}
.openerp .oe_im_chatview .oe_im_chatview_header {
padding: 3px 6px 2px;
background: #DEDEDE;
background: -moz-linear-gradient(#FCFCFC, #DEDEDE);
background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE));
-moz-border-radius: 3px 3px 0 0;
-webkit-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
border-bottom: 1px solid #AEB9BD;
cursor: pointer;
}
.openerp .oe_im_chatview .oe_im_chatview_close {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
font-size: 18px;
line-height: 16px;
float: right;
font-weight: bold;
color: black;
text-shadow: 0 1px 0 white;
opacity: 0.2;
}
.openerp .oe_im_chatview .oe_im_chatview_content {
overflow: auto;
height: 287px;
}
.openerp .oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_content {
height: 249px;
}
.openerp .oe_im_chatview .oe_im_chatview_footer {
position: relative;
padding: 3px;
border-top: 1px solid #AEB9BD;
background: #DEDEDE;
background: -moz-linear-gradient(#FCFCFC, #DEDEDE);
background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE));
-moz-border-radius: 0 0 3px 3px;
-webkit-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
.openerp .oe_im_chatview .oe_im_chatview_input {
width: 222px;
font-family: Lato, Helvetica, sans-serif;
font-size: 13px;
color: #333;
padding: 1px 5px;
border: 1px solid #AEB9BD;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: inset 0 1px 4px rgba(0,0,0,0.2);
-webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2);
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2);
}
.openerp .oe_im_chatview .oe_im_chatview_bubble {
background: white;
position: relative;
padding: 3px;
margin: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.openerp .oe_im_chatview .oe_im_chatview_clip {
position: relative;
float: left;
width: 26px;
height: 26px;
margin-right: 4px;
-moz-box-shadow: 0 0 2px 1px rgba(0,0,0,0.25);
-webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
}
.openerp .oe_im_chatview .oe_im_chatview_avatar {
float: left;
width: 26px;
height: auto;
clip: rect(0, 26px, 26px, 0);
max-width: 100%;
width: auto 9;
height: auto;
vertical-align: middle;
border: 0;
-ms-interpolation-mode: bicubic;
}
.openerp .oe_im_chatview .oe_im_chatview_time {
position: absolute;
right: 0px;
top: 0px;
margin: 3px;
text-align: right;
line-height: 13px;
font-size: 11px;
color: #999;
width: 60px;
overflow: hidden;
}
.openerp .oe_im_chatview .oe_im_chatview_from {
margin: 0 0 2px 0;
line-height: 14px;
font-weight: bold;
font-size: 12px;
width: 140px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: #3A87AD;
}
.openerp .oe_im_chatview .oe_im_chatview_bubble_list {
}
.openerp .oe_im_chatview .oe_im_chatview_bubble_item {
margin: 0 0 2px 30px;
line-height: 14px;
word-wrap: break-word;
}
.openerp .oe_im_chatview_online {
display: none;
margin-top: -4px;
width: 11px;
height: 11px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -0,0 +1,463 @@
openerp.im = function(instance) {
var USERS_LIMIT = 20;
var ERROR_DELAY = 5000;
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.UserMenu.include({
do_update: function(){
var self = this;
this.update_promise.then(function() {
var im = new instance.im.InstantMessaging(self);
im.appendTo(instance.client.$el);
var button = new instance.im.ImTopButton(this);
button.on("clicked", im, im.switch_display);
button.appendTo(instance.webclient.$el.find('.oe_systray'));
});
return this._super.apply(this, arguments);
},
});
instance.im.ImTopButton = instance.web.Widget.extend({
template:'ImTopButton',
events: {
"click": "clicked",
},
clicked: function() {
this.trigger("clicked");
},
});
instance.im.InstantMessaging = instance.web.Widget.extend({
template: "InstantMessaging",
events: {
"keydown .oe_im_searchbox": "input_change",
"keyup .oe_im_searchbox": "input_change",
"change .oe_im_searchbox": "input_change",
},
init: function(parent) {
this._super(parent);
this.shown = false;
this.set("right_offset", 0);
this.set("current_search", "");
this.users = [];
this.c_manager = new instance.im.ConversationManager(this);
this.on("change:right_offset", this.c_manager, _.bind(function() {
this.c_manager.set("right_offset", this.get("right_offset"));
}, this));
this.user_search_dm = new instance.web.DropMisordered();
},
start: function() {
this.$el.css("right", -this.$el.outerWidth());
$(window).scroll(_.bind(this.calc_box, this));
$(window).resize(_.bind(this.calc_box, this));
this.calc_box();
this.on("change:current_search", this, this.search_changed);
this.search_changed();
var self = this;
return this.c_manager.start_polling();
},
calc_box: function() {
var $topbar = instance.client.$(".oe_topbar");
var top = $topbar.offset().top + $topbar.height();
top = Math.max(top - $(window).scrollTop(), 0);
this.$el.css("top", top);
this.$el.css("bottom", 0);
},
input_change: function() {
this.set("current_search", this.$(".oe_im_searchbox").val());
},
search_changed: function(e) {
var users = new instance.web.Model("im.user");
var self = this;
return this.user_search_dm.add(users.call("search_users",
[[["name", "ilike", this.get("current_search")], ["id", "<>", instance.session.uid]],
["name", "user", "uuid", "im_status"], USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) {
self.c_manager.add_to_user_cache(result);
self.$(".oe_im_input").val("");
var old_users = self.users;
self.users = [];
_.each(result, function(user) {
var widget = new instance.im.UserWidget(self, self.c_manager.get_user(user.id));
widget.appendTo(self.$(".oe_im_users"));
widget.on("activate_user", self, self.activate_user);
self.users.push(widget);
});
_.each(old_users, function(user) {
user.destroy();
});
});
},
switch_display: function() {
var fct = _.bind(function(place) {
this.set("right_offset", place + this.$el.outerWidth());
}, this);
var opt = {
step: fct,
};
if (this.shown) {
this.$el.animate({
right: -this.$el.outerWidth(),
}, opt);
} else {
if (! this.c_manager.get_activated()) {
this.do_warn("Instant Messaging is not activated on this server.", "");
return;
}
this.$el.animate({
right: 0,
}, opt);
}
this.shown = ! this.shown;
},
activate_user: function(user) {
this.c_manager.activate_user(user, true);
},
});
instance.im.UserWidget = instance.web.Widget.extend({
"template": "UserWidget",
events: {
"click": "activate_user",
},
init: function(parent, user) {
this._super(parent);
this.user = user;
this.user.add_watcher();
},
start: function() {
var change_status = function() {
this.$(".oe_im_user_online").toggle(this.user.get("im_status") === true);
};
this.user.on("change:im_status", this, change_status);
change_status.call(this);
},
activate_user: function() {
this.trigger("activate_user", this.user);
},
destroy: function() {
this.user.remove_watcher();
this._super();
},
});
instance.im.ImUser = instance.web.Class.extend(instance.web.PropertiesMixin, {
init: function(parent, user_rec) {
instance.web.PropertiesMixin.init.call(this, parent);
user_rec.image_url = instance.session.url("/im/static/src/img/avatar/avatar.jpeg");
if (user_rec.user)
user_rec.image_url = instance.session.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.user[0]});
this.set(user_rec);
this.set("watcher_count", 0);
this.on("change:watcher_count", this, function() {
if (this.get("watcher_count") === 0)
this.destroy();
});
},
destroy: function() {
this.trigger("destroyed");
instance.web.PropertiesMixin.destroy.call(this);
},
add_watcher: function() {
this.set("watcher_count", this.get("watcher_count") + 1);
},
remove_watcher: function() {
this.set("watcher_count", this.get("watcher_count") - 1);
},
});
instance.im.ConversationManager = instance.web.Controller.extend({
init: function(parent) {
this._super(parent);
this.set("right_offset", 0);
this.conversations = [];
this.users = {};
this.on("change:right_offset", this, this.calc_positions);
this.set("window_focus", true);
this.set("waiting_messages", 0);
this.focus_hdl = _.bind(function() {
this.set("window_focus", true);
}, this);
$(window).bind("focus", this.focus_hdl);
this.blur_hdl = _.bind(function() {
this.set("window_focus", false);
}, this);
$(window).bind("blur", this.blur_hdl);
this.on("change:window_focus", this, this.window_focus_change);
this.window_focus_change();
this.on("change:waiting_messages", this, this.messages_change);
this.messages_change();
this.create_ting();
this.activated = false;
this.users_cache = {};
this.last = null;
this.unload_event_handler = _.bind(this.unload, this);
},
start_polling: function() {
var self = this;
return new instance.web.Model("im.user").call("get_by_user_id", [instance.session.uid]).then(function(my_id) {
self.my_id = my_id["id"];
return self.ensure_users([self.my_id]).then(function() {
var me = self.users_cache[self.my_id];
delete self.users_cache[self.my_id];
self.me = me;
self.rpc("/longpolling/im/activated", {}, {shadow: true}).then(function(activated) {
if (activated) {
self.activated = true;
$(window).on("unload", self.unload_event_handler);
self.poll();
}
}, function(a, e) {
e.preventDefault();
});
});
});
},
unload: function() {
return new instance.web.Model("im.user").call("im_disconnect", [], {context: new instance.web.CompoundContext()});
},
ensure_users: function(user_ids) {
var no_cache = {};
_.each(user_ids, function(el) {
if (! this.users_cache[el])
no_cache[el] = el;
}, this);
var self = this;
if (_.size(no_cache) === 0)
return $.when();
else
return new instance.web.Model("im.user").call("read", [_.values(no_cache), ["name", "user", "uuid", "im_status"]],
{context: new instance.web.CompoundContext()}).then(function(users) {
self.add_to_user_cache(users);
});
},
add_to_user_cache: function(user_recs) {
_.each(user_recs, function(user_rec) {
if (! this.users_cache[user_rec.id]) {
var user = new instance.im.ImUser(this, user_rec);
this.users_cache[user_rec.id] = user;
user.on("destroyed", this, function() {
delete this.users_cache[user_rec.id];
});
}
}, this);
},
get_user: function(user_id) {
return this.users_cache[user_id];
},
poll: function() {
var self = this;
var user_ids = _.map(this.users_cache, function(el) {
return el.get("id");
});
this.rpc("/longpolling/im/poll", {
last: this.last,
users_watch: user_ids,
context: instance.web.pyeval.eval('context', {}),
}, {shadow: true}).then(function(result) {
_.each(result.users_status, function(el) {
if (self.get_user(el.id))
self.get_user(el.id).set(el);
});
self.last = result.last;
var user_ids = _.pluck(_.pluck(result.res, "from_id"), 0);
self.ensure_users(user_ids).then(function() {
_.each(result.res, function(mes) {
var user = self.get_user(mes.from_id[0]);
self.received_message(mes, user);
});
self.poll();
});
}, function(unused, e) {
e.preventDefault();
setTimeout(_.bind(self.poll, self), ERROR_DELAY);
});
},
get_activated: function() {
return this.activated;
},
create_ting: function() {
var kitten = jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined;
this.ting = new Audio(instance.webclient.session.origin + "/im/static/src/audio/" + (kitten ? "purr" : "Ting") +
(new Audio().canPlayType("audio/ogg; codecs=vorbis") ? ".ogg" : ".mp3"));
},
window_focus_change: function() {
if (this.get("window_focus")) {
this.set("waiting_messages", 0);
}
},
messages_change: function() {
if (! instance.webclient.set_title_part)
return;
instance.webclient.set_title_part("aa_im_messages", this.get("waiting_messages") === 0 ? undefined :
_.str.sprintf(_t("%d Messages"), this.get("waiting_messages")));
},
activate_user: function(user, focus) {
var conv = this.users[user.get('id')];
if (! conv) {
conv = new instance.im.Conversation(this, user, this.me);
conv.appendTo(instance.client.$el);
conv.on("destroyed", this, function() {
this.conversations = _.without(this.conversations, conv);
delete this.users[conv.user.get('id')];
this.calc_positions();
});
this.conversations.push(conv);
this.users[user.get('id')] = conv;
this.calc_positions();
}
if (focus)
conv.focus();
return conv;
},
received_message: function(message, user) {
if (! this.get("window_focus")) {
this.set("waiting_messages", this.get("waiting_messages") + 1);
this.ting.play();
this.create_ting();
}
var conv = this.activate_user(user);
conv.received_message(message);
},
calc_positions: function() {
var current = this.get("right_offset");
_.each(_.range(this.conversations.length), function(i) {
this.conversations[i].set("right_position", current);
current += this.conversations[i].$el.outerWidth(true);
}, this);
},
destroy: function() {
$(window).off("unload", this.unload_event_handler);
$(window).unbind("blur", this.blur_hdl);
$(window).unbind("focus", this.focus_hdl);
this._super();
},
});
instance.im.Conversation = instance.web.Widget.extend({
"template": "Conversation",
events: {
"keydown input": "send_message",
"click .oe_im_chatview_close": "destroy",
"click .oe_im_chatview_header": "show_hide",
},
init: function(parent, user, me) {
this._super(parent);
this.me = me;
this.user = user;
this.user.add_watcher();
this.set("right_position", 0);
this.shown = true;
this.set("pending", 0);
},
start: function() {
var change_status = function() {
this.$el.toggleClass("oe_im_chatview_disconnected_status", this.user.get("im_status") === false);
this.$(".oe_im_chatview_online").toggle(this.user.get("im_status") === true);
this._go_bottom();
};
this.user.on("change:im_status", this, change_status);
change_status.call(this);
this.on("change:right_position", this, this.calc_pos);
this.full_height = this.$el.height();
this.calc_pos();
this.on("change:pending", this, _.bind(function() {
if (this.get("pending") === 0) {
this.$(".oe_im_chatview_nbr_messages").text("");
} else {
this.$(".oe_im_chatview_nbr_messages").text("(" + this.get("pending") + ")");
}
}, this));
},
show_hide: function() {
if (this.shown) {
this.$el.animate({
height: this.$(".oe_im_chatview_header").outerHeight(),
});
} else {
this.$el.animate({
height: this.full_height,
});
}
this.shown = ! this.shown;
if (this.shown) {
this.set("pending", 0);
}
},
calc_pos: function() {
this.$el.css("right", this.get("right_position"));
},
received_message: function(message) {
if (this.shown) {
this.set("pending", 0);
} else {
this.set("pending", this.get("pending") + 1);
}
this._add_bubble(this.user, message.message, message.date);
},
send_message: function(e) {
if(e && e.which !== 13) {
return;
}
var mes = this.$("input").val();
this.$("input").val("");
var send_it = _.bind(function() {
var model = new instance.web.Model("im.message");
return model.call("post", [mes, this.user.get('id')],
{context: new instance.web.CompoundContext()});
}, this);
var tries = 0;
send_it().then(_.bind(function() {
this._add_bubble(this.me, mes, instance.web.datetime_to_str(new Date()));
}, this), function(error, e) {
e.preventDefault();
tries += 1;
if (tries < 3)
return send_it();
});
},
_add_bubble: function(user, item, date) {
var items = [item];
if (user === this.last_user) {
this.last_bubble.remove();
items = this.last_items.concat(items);
}
this.last_user = user;
this.last_items = items;
date = instance.web.str_to_datetime(date);
var now = new Date();
var diff = now - date;
if (diff > (1000 * 60 * 60 * 24)) {
date = $.timeago(date);
} else {
date = date.toString(Date.CultureInfo.formatPatterns.shortTime);
}
this.last_bubble = $(QWeb.render("Conversation.bubble", {"items": items, "user": user, "time": date}));
$(this.$(".oe_im_chatview_content").children()[0]).append(this.last_bubble);
this._go_bottom();
},
_go_bottom: function() {
this.$(".oe_im_chatview_content").scrollTop($(this.$(".oe_im_chatview_content").children()[0]).height());
},
focus: function() {
this.$(".oe_im_chatview_input").focus();
if (! this.shown)
this.show_hide();
},
destroy: function() {
this.user.remove_watcher();
this.trigger("destroyed");
return this._super();
},
});
}

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- vim:fdl=1:
-->
<templates xml:space="preserve">
<t t-name="InstantMessaging">
<div class="oe_im">
<div class="oe_im_frame_header">
<span class="oe_e oe_im_search_icon">ô</span>
<input class="oe_im_searchbox" t-att-placeholder="_t('Search users...')"/>
<span class="oe_e oe_im_search_clear">[</span>
</div>
<div class="oe_im_users"></div>
<div class="oe_im_content"></div>
</div>
</t>
<t t-name="ImTopButton">
<div t-att-title='_t("Display Instant Messaging")' class="oe_topbar_item oe_topbar_imbutton">
<span class="oe_e">+</span>
</div>
</t>
<t t-name="UserWidget">
<div class="oe_im_user">
<span class="oe_im_user_clip">
<img t-att-src='widget.user.get("image_url")' class="oe_im_user_avatar"/>
</span>
<span class="oe_im_user_name"><t t-esc="widget.user.get('name')"/></span>
<img t-att-src="_s +'/im/static/src/img/green.png'" class="oe_im_user_online"/>
</div>
</t>
<t t-name="Conversation">
<div class="oe_im_chatview">
<div class="oe_im_chatview_header">
<img t-att-src="_s +'/im/static/src/img/green.png'" class="oe_im_chatview_online"/>
<t t-esc="widget.user.get('name') || 'Anonymous'"/>
<scan class="oe_im_chatview_nbr_messages" />
<button class="oe_im_chatview_close">×</button>
</div>
<div class="oe_im_chatview_disconnected">
<t t-esc='_.str.sprintf(_t("%s is offline. He/She will receive your messages on his/her next connection."), widget.user.get("name") || "Anonymous")'/>
</div>
<div class="oe_im_chatview_content">
<div></div>
</div>
<div class="oe_im_chatview_footer">
<input class="oe_im_chatview_input" t-att-placeholder="_t('Say something...')" />
</div>
</div>
</t>
<t t-name="Conversation.bubble">
<div class="oe_im_chatview_bubble">
<div class="oe_im_chatview_clip">
<img class="oe_im_chatview_avatar" t-att-src='user.get("image_url")'/>
</div>
<div class="oe_im_chatview_from"><t t-esc="user.get('name') || 'Anonymous'"/></div>
<div class="oe_im_chatview_bubble_list">
<t t-foreach="items" t-as="item">
<div class="oe_im_chatview_bubble_item"><t t-esc="item"/></div>
</t>
</div>
<div class="oe_im_chatview_time"><t t-esc="time"/></div>
</div>
</t>
</templates>

View File

@ -0,0 +1,2 @@
import im_livechat

View File

@ -0,0 +1,29 @@
{
'name' : 'Live Support',
'version': '1.0',
'summary': 'Live Chat with Visitors/Customers',
'category': 'Tools',
'complexity': 'easy',
'description':
"""
Live Chat Support
=================
Allow to drop instant messaging widgets on any web page that will communicate
with the current server and dispatch visitors request amongst several live
chat operators.
""",
'data': [
"security/im_livechat_security.xml",
"security/ir.model.access.csv",
"im_livechat_view.xml",
],
'demo': [
"im_livechat_demo.xml",
],
'depends' : ["im", "mail", "portal_anonymous"],
'installable': True,
'auto_install': False,
'application': True,
}

View File

@ -0,0 +1,245 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import openerp
import openerp.addons.im.im as im
import json
import random
import jinja2
from openerp.osv import osv, fields
from openerp import tools
env = jinja2.Environment(
loader=jinja2.PackageLoader('openerp.addons.im_livechat', "."),
autoescape=False
)
env.filters["json"] = json.dumps
class LiveChatController(openerp.addons.web.http.Controller):
_cp_path = '/im_livechat'
@openerp.addons.web.http.httprequest
def loader(self, req, **kwargs):
p = json.loads(kwargs["p"])
db = p["db"]
channel = p["channel"]
user_name = p.get("user_name", None)
req.session._db = db
req.session._uid = None
req.session._login = "anonymous"
req.session._password = "anonymous"
info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel)
info["db"] = db
info["channel"] = channel
info["userName"] = user_name
return req.make_response(env.get_template("loader.js").render(info),
headers=[('Content-Type', "text/javascript")])
@openerp.addons.web.http.httprequest
def web_page(self, req, **kwargs):
p = json.loads(kwargs["p"])
db = p["db"]
channel = p["channel"]
req.session._db = db
req.session._uid = None
req.session._login = "anonymous"
req.session._password = "anonymous"
script = req.session.model('im_livechat.channel').read(channel, ["script"])["script"]
info = req.session.model('im_livechat.channel').get_info_for_chat_src(channel)
info["script"] = script
return req.make_response(env.get_template("web_page.html").render(info),
headers=[('Content-Type', "text/html")])
@openerp.addons.web.http.jsonrequest
def available(self, req, db, channel):
req.session._db = db
req.session._uid = None
req.session._login = "anonymous"
req.session._password = "anonymous"
return req.session.model('im_livechat.channel').get_available_user(channel) > 0
class im_livechat_channel(osv.osv):
_name = 'im_livechat.channel'
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('im_livechat', 'static/src/img', 'default.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
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)
def _are_you_inside(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = False
for user in record.user_ids:
if user.id == uid:
res[record.id] = True
break
return res
def _script(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = env.get_template("include.html").render({
"url": self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url'),
"parameters": {"db":cr.dbname, "channel":record.id},
})
return res
def _web_page(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url') + \
"/im_livechat/web_page?p=" + json.dumps({"db":cr.dbname, "channel":record.id})
return res
_columns = {
'name': fields.char(string="Channel Name", size=200, required=True),
'user_ids': fields.many2many('res.users', 'im_livechat_channel_im_user', 'channel_id', 'user_id', string="Users"),
'are_you_inside': fields.function(_are_you_inside, type='boolean', string='Are you inside the matrix?', store=False),
'script': fields.function(_script, type='text', string='Script', store=False),
'web_page': fields.function(_web_page, type='url', string='Web Page', store=False, size="200"),
'button_text': fields.char(string="Text of the Button", size=200),
'input_placeholder': fields.char(string="Chat Input Placeholder", size=200),
'default_message': fields.char(string="Welcome Message", size=200, help="This is an automated 'welcome' message that your visitor will see when they initiate a new chat session."),
# image: all image fields are base64 encoded and PIL-supported
'image': fields.binary("Photo",
help="This field holds the image used as photo for the group, limited to 1024x1024px."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized photo", type="binary", multi="_get_image",
store={
'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized photo of the group. It is automatically "\
"resized as a 128x128px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-sized photo", type="binary", multi="_get_image",
store={
'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized photo of the group. It is automatically "\
"resized as a 64x64px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
}
def _default_user_ids(self, cr, uid, context=None):
return [(6, 0, [uid])]
_defaults = {
'button_text': "Have a Question? Chat with us.",
'input_placeholder': "How may I help you?",
'default_message': '',
'user_ids': _default_user_ids,
'image': _get_default_image,
}
def get_available_user(self, cr, uid, channel_id, context=None):
channel = self.browse(cr, openerp.SUPERUSER_ID, channel_id, context=context)
users = []
for user in channel.user_ids:
iuid = self.pool.get("im.user").get_by_user_id(cr, uid, user.id, context=context)["id"]
imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context)
if imuser.im_status:
users.append(imuser)
if len(users) == 0:
return False
return random.choice(users).id
def test_channel(self, cr, uid, channel, context=None):
if not channel:
return {}
return {
'url': self.browse(cr, uid, channel[0], context=context or {}).web_page,
'type': 'ir.actions.act_url'
}
def get_info_for_chat_src(self, cr, uid, channel, context=None):
url = self.pool.get('ir.config_parameter').get_param(cr, openerp.SUPERUSER_ID, 'web.base.url')
chan = self.browse(cr, uid, channel, context=context)
return {
"url": url,
'buttonText': chan.button_text,
'inputPlaceholder': chan.input_placeholder,
'defaultMessage': chan.default_message,
"channelName": chan.name,
}
def join(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'user_ids': [(4, uid)]})
return True
def quit(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'user_ids': [(3, uid)]})
return True
class im_message(osv.osv):
_inherit = 'im.message'
def _support_member(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = False
if record.to_id.user and record.from_id.user:
continue
elif record.to_id.user:
res[record.id] = record.to_id.user.id
elif record.from_id.user:
res[record.id] = record.from_id.user.id
return res
def _customer(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = False
if record.to_id.uuid and record.from_id.uuid:
continue
elif record.to_id.uuid:
res[record.id] = record.to_id.id
elif record.from_id.uuid:
res[record.id] = record.from_id.id
return res
def _direction(self, cr, uid, ids, name, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
res[record.id] = False
if not not record.to_id.user and not not record.from_id.user:
continue
elif not not record.to_id.user:
res[record.id] = "c2s"
elif not not record.from_id.user:
res[record.id] = "s2c"
return res
_columns = {
'support_member_id': fields.function(_support_member, type='many2one', relation='res.users', string='Support Member', store=True, select=True),
'customer_id': fields.function(_customer, type='many2one', relation='im.user', string='Customer', store=True, select=True),
'direction': fields.function(_direction, type="selection", selection=[("s2c", "Support Member to Customer"), ("c2s", "Customer to Support Member")],
string='Direction', store=False),
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="channel_website" model="im_livechat.channel">
<field name="name">YourWebsite.com</field>
<field name="default_message">Hello, how may I help you?</field>
</record>
<record id="group_im_livechat" model="res.groups">
<field name="users" eval="[(4, ref('base.user_demo'))]"/>
</record>
</data>
</openerp>

View File

@ -0,0 +1,146 @@
<?xml version="1.0"?>
<openerp>
<data>
<menuitem id="im_livechat" name="Live Chat" parent="mail.mail_feeds_main" groups="group_im_livechat"/>
<record model="ir.actions.act_window" id="action_support_channels">
<field name="name">Live Chat Channels</field>
<field name="res_model">im_livechat.channel</field>
<field name="view_mode">kanban,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new live chat channel.
</p><p>
You can create channels for each website on which you want
to integrate the live chat widget, allowing you website
visitors to talk in real time with your operators.
</p><p>
Each channel has it's own URL that you can send by email to
your customers in order to start chatting with you.
</p>
</field>
</record>
<menuitem name="Channels" parent="im_livechat" id="support_channels" action="action_support_channels" groups="group_im_livechat"/>
<record model="ir.ui.view" id="support_channel_kanban">
<field name="name">support_channel.kanban</field>
<field name="model">im_livechat.channel</field>
<field name="arch" type="xml">
<kanban>
<field name="name"/>
<field name="web_page"/>
<field name="are_you_inside"/>
<field name="user_ids"/>
<templates>
<t t-name="kanban-box">
<div class="oe_group_image">
<a type="open"><img t-att-src="kanban_image('im_livechat.channel', 'image_medium', record.id.value)" class="oe_group_photo"/></a>
</div>
<div class="oe_group_details">
<h4><a type="open"><field name="name"/></a></h4>
<div class="oe_kanban_footer_left">
<span>
<span class="oe_e">+</span> <t t-esc="(record.user_ids.raw_value || []).length"/>
</span>
</div>
<div class="oe_group_button">
<button t-if="record.are_you_inside.raw_value" name="quit" type="object" class="oe_group_join">Quit</button>
<button t-if="! record.are_you_inside.raw_value" name="join" type="object">Join</button>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="support_channel_form" model="ir.ui.view">
<field name="name">support_channel.form</field>
<field name="model">im_livechat.channel</field>
<field name="arch" type="xml">
<form string="Support Channels" version="7.0">
<sheet>
<field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" placeholder="e.g. YourWebsite.com"/>
</h1>
<div>
<button type="object" name="join" class="oe_highlight" string="Join Channel" attrs='{"invisible": [["are_you_inside", "=", True]]}'/>
<button type="object" name="quit" string="Leave Channel" attrs='{"invisible": [["are_you_inside", "=", False]]}'/>
<button type="object" name="test_channel" string="Test" attrs='{"invisible": [["web_page", "=", False]]}'/>
<field name="are_you_inside" invisible="1"/>
</div>
</div>
<group>
<group string="Operators">
<field name="user_ids" widget="many2many_kanban" nolabel="1" colspan="2">
<kanban>
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div>
<a t-if="! read_only_mode" type="delete" style="position: absolute; right: 0; padding: 4px; diplay: inline-block">X</a>
<div class="oe_group_details" style="min-height: 40px">
<img t-att-src="kanban_image('res.users', 'image', record.id.value)"
class="oe_avatar oe_kanban_avatar_smallbox" style="float:left; margin-right: 10px;"/>
<h4><field name="name"/></h4>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</group>
<group string="Options">
<field name="button_text"/>
<field name="input_placeholder"/>
<field name="default_message" placeholder="e.g. Hello, how may I help you?"/>
</group>
</group>
<div attrs='{"invisible": [["web_page", "=", False]]}'>
<separator string="How to use the Live Chat widget?"/>
<p>
Copy and paste this code into your website, within the &amp;lt;head&amp;gt; tag:
</p>
<field name="script" readonly="1" class="oe_tag"/>
<p>
or copy this url and send it by email to your customers or suppliers:
</p>
<field name="web_page" readonly="1" class="oe_tag"/>
</div>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="action_history">
<field name="name">History</field>
<field name="res_model">im.message</field>
<field name="view_mode">list</field>
<field name="domain">["|", ('to_id.user', '=', None), ('from_id.user', '=', None)]</field>
</record>
<menuitem name="History" parent="im_livechat" id="history" action="action_history" groups="group_im_livechat_manager"/>
<record id="im_message_form" model="ir.ui.view">
<field name="name">im.message.tree</field>
<field name="model">im.message</field>
<field name="arch" type="xml">
<tree string="History">
<field name="date"/>
<field name="support_member_id"/>
<field name="customer_id"/>
<field name="direction"/>
<field name="message"/>
</tree>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,2 @@
<script type="text/javascript" src="{{url}}/im_livechat/static/ext/static/js/require.js"></script>
<script type="text/javascript" src='{{url}}/im_livechat/loader?p={{parameters | json | escape}}'></script>

View File

@ -0,0 +1,24 @@
require.config({
context: "oelivesupport",
baseUrl: {{url | json}} + "/im_livechat/static/ext/static/js",
shim: {
underscore: {
init: function() {
return _.noConflict();
},
},
"jquery.achtung": {
deps: ['jquery'],
},
},
})(["livesupport", "jquery"], function(livesupport, jQuery) {
jQuery.noConflict();
livesupport.main({{url | json}}, {{db | json}}, "anonymous", "anonymous", {{channel | json}}, {
buttonText: {{buttonText | json}},
inputPlaceholder: {{inputPlaceholder | json}},
defaultMessage: {{(defaultMessage or None) | json}},
auto: window.oe_im_livechat_auto || false,
userName: {{userName | json}} || undefined,
});
});

View File

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="module_category_im_livechat" model="ir.module.category">
<field name="name">Live Support</field>
<field name="sequence" eval="20" />
</record>
<record id="group_im_livechat" model="res.groups">
<field name="name">User</field>
<field name="category_id" ref="module_category_im_livechat"/>
<field name="comment">The user will be able to join support channels.</field>
</record>
<record id="group_im_livechat_manager" model="res.groups">
<field name="name">Manager</field>
<field name="comment">The user will be able to delete support channels.</field>
<field name="category_id" ref="module_category_im_livechat"/>
<field name="implied_ids" eval="[(4, ref('im_livechat.group_im_livechat'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
<record id="message_rule_1" model="ir.rule">
<field name="name">Live Support Managers can read messages from live support</field>
<field name="model_id" ref="im.model_im_message"/>
<field name="groups" eval="[(6,0,[ref('im_livechat.group_im_livechat_manager')])]"/>
<field name="domain_force">["|", ('to_id.user', '=', None), ('from_id.user', '=', None)]</field>
<field name="perm_unlink" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
</record>
</data>
</openerp>

View File

@ -0,0 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_ls_chann1,im_livechat.channel,model_im_livechat_channel,,1,0,0,0
access_ls_chann2,im_livechat.channel,model_im_livechat_channel,group_im_livechat,1,1,1,0
access_ls_chann3,im_livechat.channel,model_im_livechat_channel,group_im_livechat_manager,1,1,1,1
access_ls_message,im_livechat.im.message,im.model_im_message,portal.group_anonymous,0,0,0,0
access_im_user,im_livechat.im.user,im.model_im_user,portal.group_anonymous,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ls_chann1 im_livechat.channel model_im_livechat_channel 1 0 0 0
3 access_ls_chann2 im_livechat.channel model_im_livechat_channel group_im_livechat 1 1 1 0
4 access_ls_chann3 im_livechat.channel model_im_livechat_channel group_im_livechat_manager 1 1 1 1
5 access_ls_message im_livechat.im.message im.model_im_message portal.group_anonymous 0 0 0 0
6 access_im_user im_livechat.im.user im.model_im_user portal.group_anonymous 1 0 0 0

View File

@ -0,0 +1,3 @@
static/js/livesupport_templates.js: static/js/livesupport_templates.html
python static/js/to_jsonp.py static/js/livesupport_templates.html oe_livesupport_templates_callback > static/js/livesupport_templates.js

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,190 @@
.openerp_style { /* base style of openerp */
font-family: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif;
color: #4c4c4c;
font-size: 13px;
background: white;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
}
/* button */
.oe_chat_button {
position: fixed;
bottom: 0px;
right: 6px;
display: inline-block;
min-width: 100px;
background-color: rgba(60, 60, 60, 0.6);
font-family: 'Lucida Grande', 'Lucida Sans Unicode', Arial, Verdana, sans-serif;
font-size: 14px;
font-weight: bold;
padding: 10px;
color: white;
text-shadow: rgb(59, 76, 88) 1px 1px 0px;
border: 1px solid rgb(80, 80, 80);
border-bottom: 0px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
cursor: pointer;
}
/* conversations */
.oe_im_chatview {
position: fixed;
overflow: hidden;
bottom: 42px;
margin-right: 6px;
background: rgba(60, 60, 60, 0.8);
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 0 3px rgba(0,0,0,0.3), 0 2px 4px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3), 0 2px 4px rgba(0, 0, 0, 0.3);
width: 240px;
}
.oe_im_chatview .oe_im_chatview_disconnected {
display:none;
z-index: 100;
width: 100%;
background: #E8EBEF;
padding: 5px;
font-size: 11px;
color: #999;
line-height: 14px;
height: 28px;
overflow: hidden;
}
.oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_disconnected {
display: block;
}
.oe_im_chatview .oe_im_chatview_header {
padding: 3px 6px 2px;
background: #DEDEDE;
background: -moz-linear-gradient(#FCFCFC, #DEDEDE);
background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE));
-moz-border-radius: 3px 3px 0 0;
-webkit-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
border-bottom: 1px solid #AEB9BD;
cursor: pointer;
}
.oe_im_chatview .oe_im_chatview_close {
padding: 0;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
font-size: 18px;
line-height: 16px;
float: right;
font-weight: bold;
color: black;
text-shadow: 0 1px 0 white;
opacity: 0.2;
}
.oe_im_chatview .oe_im_chatview_content {
overflow: auto;
height: 287px;
width: 240px;
}
.oe_im_chatview.oe_im_chatview_disconnected_status .oe_im_chatview_content {
height: 249px;
}
.oe_im_chatview .oe_im_chatview_footer {
position: relative;
padding: 3px;
border-top: 1px solid #AEB9BD;
background: #DEDEDE;
background: -moz-linear-gradient(#FCFCFC, #DEDEDE);
background: -webkit-gradient(linear, left top, left bottom, from(#FCFCFC), to(#DEDEDE));
-moz-border-radius: 0 0 3px 3px;
-webkit-border-radius: 0 0 3px 3px;
border-radius: 0 0 3px 3px;
}
.oe_im_chatview .oe_im_chatview_input {
width: 222px;
font-family: Lato, Helvetica, sans-serif;
font-size: 13px;
color: #333;
padding: 1px 5px;
border: 1px solid #AEB9BD;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: inset 0 1px 4px rgba(0,0,0,0.2);
-webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2);
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.2);
}
.oe_im_chatview .oe_im_chatview_bubble {
background: white;
position: relative;
padding: 3px;
margin: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
.oe_im_chatview .oe_im_chatview_clip {
position: relative;
float: left;
width: 26px;
height: 26px;
margin-right: 4px;
-moz-box-shadow: 0 0 2px 1px rgba(0,0,0,0.25);
-webkit-box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.25);
}
.oe_im_chatview .oe_im_chatview_avatar {
float: left;
width: 26px;
height: auto;
clip: rect(0, 26px, 26px, 0);
max-width: 100%;
width: auto 9;
height: auto;
vertical-align: middle;
border: 0;
-ms-interpolation-mode: bicubic;
}
.oe_im_chatview .oe_im_chatview_time {
position: absolute;
right: 0px;
top: 0px;
margin: 3px;
text-align: right;
line-height: 13px;
font-size: 11px;
color: #999;
width: 60px;
overflow: hidden;
}
.oe_im_chatview .oe_im_chatview_from {
margin: 0 0 2px 0;
line-height: 14px;
font-weight: bold;
font-size: 12px;
width: 140px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: #3A87AD;
}
.oe_im_chatview .oe_im_chatview_bubble_list {
}
.oe_im_chatview .oe_im_chatview_bubble_item {
margin: 0 0 2px 30px;
line-height: 14px;
word-wrap: break-word;
}
.oe_im_chatview_online {
display: none;
margin-top: -4px;
width: 11px;
height: 11px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Some files were not shown because too many files have changed in this diff Show More