[MRG] merge with lp:openobject-addons

bzr revid: tpa@tinyerp.com-20130821054505-l3e9h86gsqa60jp9
This commit is contained in:
Turkesh Patel (Open ERP) 2013-08-21 11:15:05 +05:30
commit f21aa3c371
107 changed files with 20441 additions and 14309 deletions

View File

@ -1 +1,2 @@
.*
**/node_modules

View File

@ -561,10 +561,14 @@ class account_invoice(osv.osv):
def onchange_payment_term_date_invoice(self, cr, uid, ids, payment_term_id, date_invoice):
res = {}
if isinstance(ids, (int, long)):
ids = [ids]
if not date_invoice:
date_invoice = time.strftime('%Y-%m-%d')
if not payment_term_id:
return {'value':{'date_due': date_invoice}} #To make sure the invoice has a due date when no payment term
inv = self.browse(cr, uid, ids[0])
#To make sure the invoice due date should contain due date which is entered by user when there is no payment term defined
return {'value':{'date_due': inv.date_due and inv.date_due or date_invoice}}
pterm_list = self.pool.get('account.payment.term').compute(cr, uid, payment_term_id, value=1, date_ref=date_invoice)
if pterm_list:
pterm_list = [line[0] for line in pterm_list]

View File

@ -800,7 +800,7 @@ class account_move_line(osv.osv):
r_id = move_rec_obj.create(cr, uid, {
'type': type,
'line_partial_ids': map(lambda x: (4,x,False), merges+unmerge)
})
}, context=context)
move_rec_obj.reconcile_partial_check(cr, uid, [r_id] + merges_rec, context=context)
return True

View File

@ -266,7 +266,7 @@ class account_invoice(osv.osv, EDIMixin):
params = {
"cmd": "_xclick",
"business": inv.company_id.paypal_account,
"item_name": inv.company_id.name + " Invoice " + inv.number,
"item_name": "%s Invoice %s" % (inv.company_id.name, inv.number or ''),
"invoice": inv.number,
"amount": inv.residual,
"currency_code": inv.currency_id.name,

View File

@ -25,7 +25,7 @@ from dateutil.relativedelta import relativedelta
from operator import itemgetter
from os.path import join as opj
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT as DF
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from openerp.tools.translate import _
from openerp.osv import fields, osv
from openerp import tools

View File

@ -67,9 +67,10 @@
Then I cancel Bank Statements and verifies that it raises a warning
-
!python {model: account.bank.statement}: |
from openerp.osv import osv
try:
self.button_cancel(cr, uid, [ref("account_bank_statement_0")])
assert False, "An exception should have been raised, the journal should not let us cancel moves!"
except Exception:
except osv.except_osv:
# exception was raised as expected, as the journal does not allow cancelling moves
pass

View File

@ -73,14 +73,16 @@
I cancel the account move which is in posted state and verifies that it gives warning message
-
!python {model: account.move}: |
from openerp.osv import osv
inv_obj = self.pool.get('account.invoice')
inv = inv_obj.browse(cr, uid, ref('account_invoice_supplier0'))
try:
mov_cancel = self.button_cancel(cr, uid, [inv.move_id.id], {'lang': u'en_US', 'tz': False,
'active_model': 'ir.ui.menu', 'journal_type': 'purchase', 'active_ids': [ref('menu_action_invoice_tree2')],
'type': 'in_invoice', 'active_id': ref('menu_action_invoice_tree2')})
except Exception, e:
assert e, 'Warning message has not been raised'
assert False, "This should never happen!"
except osv.except_osv:
pass
-
I verify that 'Period Sum' and 'Year sum' of the tax code are the expected values
-

View File

@ -11,7 +11,8 @@
<separator string="Aged Partner Balance"/>
<label string="Aged Partner Balance is a more detailed report of your receivables by intervals. When opening that report, OpenERP asks for the name of the company, the fiscal period and the size of the interval to be analyzed (in days). OpenERP then calculates a table of credit balance by period. So if you request an interval of 30 days OpenERP generates an analysis of creditors for the past month, past two months, and so on. "/>
<group col="4">
<field name="chart_account_id" widget='selection'/>
<field name="chart_account_id" widget='selection' on_change="onchange_chart_id(chart_account_id, context)"/>
<field name="fiscalyear_id" invisible="1"/>
<newline/>
<field name="date_from"/>
<field name="period_length"/>

View File

@ -34,7 +34,10 @@ class account_common_report(osv.osv_memory):
res = {}
if chart_account_id:
company_id = self.pool.get('account.account').browse(cr, uid, chart_account_id, context=context).company_id.id
res['value'] = {'company_id': company_id}
now = time.strftime('%Y-%m-%d')
domain = [('company_id', '=', company_id), ('date_start', '<', now), ('date_stop', '>', now)]
fiscalyears = self.pool.get('account.fiscalyear').search(cr, uid, domain, limit=1)
res['value'] = {'company_id': company_id, 'fiscalyear_id': fiscalyears and fiscalyears[0] or False}
return res
_columns = {
@ -124,10 +127,11 @@ class account_common_report(osv.osv_memory):
now = time.strftime('%Y-%m-%d')
company_id = False
ids = context.get('active_ids', [])
domain = [('date_start', '<', now), ('date_stop', '>', now)]
if ids and context.get('active_model') == 'account.account':
company_id = self.pool.get('account.account').browse(cr, uid, ids[0], context=context).company_id.id
domain += [('company_id', '=', company_id)]
else: # use current company id
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
domain = [('company_id', '=', company_id), ('date_start', '<', now), ('date_stop', '>', now)]
fiscalyears = self.pool.get('account.fiscalyear').search(cr, uid, domain, limit=1)
return fiscalyears and fiscalyears[0] or False

View File

@ -31,10 +31,10 @@ from openerp.report import report_sxw
class res_currency(osv.osv):
_inherit = "res.currency"
def _get_current_rate(self, cr, uid, ids, name, arg, context=None):
def _get_current_rate(self, cr, uid, ids, raise_on_no_rate=True, context=None):
if context is None:
context = {}
res = super(res_currency, self)._get_current_rate(cr, uid, ids, name, arg, context=context)
res = super(res_currency, self)._get_current_rate(cr, uid, ids, raise_on_no_rate, context=context)
if context.get('voucher_special_currency') in ids and context.get('voucher_special_currency_rate'):
res[context.get('voucher_special_currency')] = context.get('voucher_special_currency_rate')
return res
@ -932,6 +932,8 @@ class account_voucher(osv.osv):
move_pool = self.pool.get('account.move')
for voucher in self.browse(cr, uid, ids, context=context):
# refresh to make sure you don't unlink an already removed move
voucher.refresh()
recs = []
for line in voucher.move_ids:
if line.reconcile_id:
@ -1182,7 +1184,7 @@ class account_voucher(osv.osv):
for line in voucher.line_ids:
#create one move line per voucher line where amount is not 0.0
# AND (second part of the clause) only if the original move line was not having debit = credit = 0 (which is a legal value)
if not line.amount and not (line.move_line_id and not float_compare(line.move_line_id.debit, line.move_line_id.credit, precision_rounding=prec) and not float_compare(line.move_line_id.debit, 0.0, precision_rounding=prec)):
if not line.amount and not (line.move_line_id and not float_compare(line.move_line_id.debit, line.move_line_id.credit, precision_digits=prec) and not float_compare(line.move_line_id.debit, 0.0, precision_digits=prec)):
continue
# convert the amount set on the voucher line into the currency of the voucher's company
# this calls res_curreny.compute() with the right context, so that it will take either the rate on the voucher if it is relevant or will use the default behaviour
@ -1282,10 +1284,8 @@ class account_voucher(osv.osv):
}
new_id = move_line_obj.create(cr, uid, move_line_foreign_currency, context=context)
rec_ids.append(new_id)
if line.move_line_id.id:
rec_lst_ids.append(rec_ids)
return (tot_line, rec_lst_ids)
def writeoff_move_line_get(self, cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None):

View File

@ -332,14 +332,15 @@
<group>
<group>
<field name="writeoff_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="payment_option" required="1"/>
<field name="payment_option" required="1" attrs="{'invisible':[('writeoff_amount','=',0)]}"/>
<field name="writeoff_acc_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)], 'required':[('payment_option','=','with_writeoff')]}"
domain="[('type','=','other')]"/>
<field name="comment"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)]}"/>
<field name="analytic_id"
groups="analytic.group_analytic_accounting"/>
groups="analytic.group_analytic_accounting"
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)]}"/>
</group>
<group>
</group>
@ -494,14 +495,15 @@
</group>
<group>
<field name="writeoff_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="payment_option" required="1"/>
<field name="payment_option" required="1" attrs="{'invisible':[('writeoff_amount','=',0)]}"/>
<field name="writeoff_acc_id"
attrs="{'invisible':[('payment_option','!=','with_writeoff')], 'required':[('payment_option','=','with_writeoff')]}"
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)], 'required':[('payment_option','=','with_writeoff')]}"
domain="[('type','=','other')]"/>
<field name="comment"
attrs="{'invisible':[('payment_option','!=','with_writeoff')]}"/>
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)]}"/>
<field name="analytic_id"
groups="analytic.group_analytic_accounting"/>
groups="analytic.group_analytic_accounting"
attrs="{'invisible':['|', ('payment_option','!=','with_writeoff'), ('writeoff_amount','=',0)]}"/>
</group>
</group>
</page>

View File

@ -120,7 +120,7 @@ class res_users(osv.osv):
def set_pw(self, cr, uid, id, name, value, args, context):
if value:
encrypted = md5crypt(value, gen_salt())
cr.execute('update res_users set password_crypt=%s where id=%s', (encrypted, int(id)))
cr.execute("update res_users set password='', password_crypt=%s where id=%s", (encrypted, id))
del value
def get_pw( self, cr, uid, ids, name, args, context ):
@ -143,7 +143,7 @@ class res_users(osv.osv):
cr.execute('SELECT password, password_crypt FROM res_users WHERE id=%s AND active', (uid,))
if cr.rowcount:
stored_password, stored_password_crypt = cr.fetchone()
if password and not stored_password_crypt:
if stored_password and not stored_password_crypt:
salt = gen_salt()
stored_password_crypt = md5crypt(stored_password, salt)
cr.execute("UPDATE res_users SET password='', password_crypt=%s WHERE id=%s", (stored_password_crypt, uid))
@ -151,14 +151,15 @@ class res_users(osv.osv):
return super(res_users, self).check_credentials(cr, uid, password)
except openerp.exceptions.AccessDenied:
# check md5crypt
if stored_password_crypt[:len(magic_md5)] == magic_md5:
salt = stored_password_crypt[len(magic_md5):11]
if stored_password_crypt == md5crypt(password, salt):
return
elif stored_password_crypt[:len(magic_md5)] == magic_sha256:
salt = stored_password_crypt[len(magic_md5):11]
if stored_password_crypt == md5crypt(password, salt):
return
if stored_password_crypt:
if stored_password_crypt[:len(magic_md5)] == magic_md5:
salt = stored_password_crypt[len(magic_md5):11]
if stored_password_crypt == md5crypt(password, salt):
return
elif stored_password_crypt[:len(magic_md5)] == magic_sha256:
salt = stored_password_crypt[len(magic_md5):11]
if stored_password_crypt == md5crypt(password, salt):
return
# Reraise password incorrect
raise

View File

@ -92,11 +92,6 @@ allows pre-setting the default groups and menus of the first-time users.
user with the same login (and a blank password), then rename this new
user to a username that does not exist in LDAP, and setup its groups
the way you want.
Interaction with base_crypt:
----------------------------
The base_crypt module is not compatible with this module, and will disable LDAP
authentication if installed at the same time.
""",
'website' : 'http://www.openerp.com',
'category' : 'Authentication',

View File

@ -26,6 +26,7 @@ import openerp.exceptions
from openerp import tools
from openerp.osv import fields, osv
from openerp import SUPERUSER_ID
from openerp.modules.registry import RegistryManager
_logger = logging.getLogger(__name__)
class CompanyLDAP(osv.osv):
@ -190,9 +191,9 @@ class CompanyLDAP(osv.osv):
user_obj = self.pool['res.users']
values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry)
if conf['user']:
values['active'] = True
user_id = user_obj.copy(cr, SUPERUSER_ID, conf['user'],
default={'active': True})
user_obj.write(cr, SUPERUSER_ID, user_id, values)
default=values)
else:
user_id = user_obj.create(cr, SUPERUSER_ID, values)
return user_id
@ -243,41 +244,31 @@ class users(osv.osv):
user_id = super(users, self).login(db, login, password)
if user_id:
return user_id
cr = self.pool.db.cursor()
ldap_obj = self.pool['res.company.ldap']
for conf in ldap_obj.get_ldap_dicts(cr):
entry = ldap_obj.authenticate(conf, login, password)
if entry:
user_id = ldap_obj.get_or_create_user(
cr, SUPERUSER_ID, conf, login, entry)
if user_id:
cr.execute("""UPDATE res_users
SET login_date=now() AT TIME ZONE 'UTC'
WHERE login=%s""",
(tools.ustr(login),))
cr.commit()
break
cr.close()
return user_id
def check(self, db, uid, passwd):
try:
return super(users,self).check(db, uid, passwd)
except openerp.exceptions.AccessDenied:
pass
cr = self.pool.db.cursor()
cr.execute('SELECT login FROM res_users WHERE id=%s AND active=TRUE',
(int(uid),))
res = cr.fetchone()
if res:
ldap_obj = self.pool['res.company.ldap']
registry = RegistryManager.get(db)
with registry.cursor() as cr:
ldap_obj = registry.get('res.company.ldap')
for conf in ldap_obj.get_ldap_dicts(cr):
if ldap_obj.authenticate(conf, res[0], passwd):
self._uid_cache.setdefault(db, {})[uid] = passwd
cr.close()
return True
cr.close()
raise openerp.exceptions.AccessDenied()
entry = ldap_obj.authenticate(conf, login, password)
if entry:
user_id = ldap_obj.get_or_create_user(
cr, SUPERUSER_ID, conf, login, entry)
if user_id:
break
return user_id
def check_credentials(self, cr, uid, password):
try:
super(users, self).check_credentials(cr, uid, password)
except openerp.exceptions.AccessDenied:
cr.execute('SELECT login FROM res_users WHERE id=%s AND active=TRUE',
(int(uid),))
res = cr.fetchone()
if res:
ldap_obj = self.pool['res.company.ldap']
for conf in ldap_obj.get_ldap_dicts(cr):
if ldap_obj.authenticate(conf, res[0], password):
return
raise
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,4 +1,6 @@
openerp.auth_oauth = function(instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.Login.include({
@ -9,9 +11,11 @@ openerp.auth_oauth = function(instance) {
this.$el.on('click', 'a.zocial', this.on_oauth_sign_in);
this.oauth_providers = [];
if(this.params.oauth_error === 1) {
this.do_warn("Sign up error.","Sign up is not allowed on this database.");
this.do_warn(_t("Sign up error"),_t("Sign up is not allowed on this database."), true);
} else if(this.params.oauth_error === 2) {
this.do_warn("Authentication error","");
this.do_warn(_t("Authentication error"),_t("Access Denied"), true);
} else if(this.params.oauth_error === 3) {
this.do_warn(_t("Authentication error"),_t("You do not have access to this database or your invitation has expired. Please ask for an invitation and be sure to follow the link in your invitation email."), true);
}
return d.done(this.do_oauth_load).fail(function() {
self.do_oauth_load([]);

View File

@ -23,6 +23,7 @@ import logging
import simplejson
import openerp
from openerp.addons.auth_signup.res_users import SignupError
from openerp.osv import osv, fields
_logger = logging.getLogger(__name__)
@ -35,7 +36,7 @@ class res_users(osv.Model):
try:
login = super(res_users, self)._auth_oauth_signin(cr, uid, provider, validation, params, context=context)
except openerp.exceptions.AccessDenied:
except openerp.exceptions.AccessDenied, access_denied_exception:
if context and context.get('no_user_creation'):
return None
state = simplejson.loads(params['state'])
@ -52,6 +53,8 @@ class res_users(osv.Model):
'oauth_access_token': params['access_token'],
'active': True,
}
_, login, _ = self.signup(cr, uid, values, token, context=context)
try:
_, login, _ = self.signup(cr, uid, values, token, context=context)
except SignupError:
raise access_denied_exception
return login

View File

@ -26,7 +26,7 @@ from urlparse import urljoin
from openerp.addons.base.ir.ir_mail_server import MailDeliveryException
from openerp.osv import osv, fields
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval
from ast import literal_eval
from openerp.tools.translate import _
class SignupError(Exception):
@ -221,12 +221,12 @@ class res_users(osv.Model):
def _signup_create_user(self, cr, uid, values, context=None):
""" create a new user from the template user """
ir_config_parameter = self.pool.get('ir.config_parameter')
template_user_id = safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id', 'False'))
template_user_id = literal_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.template_user_id', 'False'))
assert template_user_id and self.exists(cr, uid, template_user_id, context=context), 'Signup: invalid template user'
# check that uninvited users may sign up
if 'partner_id' not in values:
if not safe_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')):
if not literal_eval(ir_config_parameter.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')):
raise SignupError('Signup is not allowed for uninvited users')
assert values.get('login'), "Signup: no login given for new user"

View File

@ -1187,8 +1187,8 @@ rule or repeating pattern of time to exclude from the recurring rule."),
context = {}
result = []
for data in super(calendar_event, self).read(cr, uid, select, ['rrule', 'exdate', 'exrule', 'date'], context=context):
if not data['rrule']:
for data in super(calendar_event, self).read(cr, uid, select, ['rrule', 'recurrency', 'exdate', 'exrule', 'date'], context=context):
if not data['recurrency'] or not data['rrule']:
result.append(data['id'])
continue
event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S")

View File

@ -1,7 +1,7 @@
#########################################################################
#
# Copyright (c) 2003-2004 Danny Brewer d29583@groovegarden.com
# Copyright (C) 2004-2010 OpenERP SA (<http://openerp.com>).
# Copyright (C) 2004-2013 OpenERP SA (<http://openerp.com>).
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -78,7 +78,7 @@ class ExportToRML( unohelper.Base, XJobExecutor ):
res = self.sock.execute(database, uid, self.password, 'ir.actions.report.xml', 'sxwtorml',base64.encodestring(data),file_type)
if res['report_rml_content']:
write_data_to_file( get_absolute_file_path( filename[7:] ), res['report_rml_content'] )
write_data_to_file(get_absolute_file_path(filename), res['report_rml_content'])
except Exception,e:
import traceback,sys
info = reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback))
@ -99,8 +99,12 @@ class ExportToRML( unohelper.Base, XJobExecutor ):
oFileDialog.setDefaultName(f_path )
sPath = oFileDialog.execute() == 1 and oFileDialog.Files[0] or None
sPath = oFileDialog.execute() == 1 and oFileDialog.Files[0] or ''
oFileDialog.dispose()
sPath = sPath[7:]
if sPath.startswith('localhost/'):
slash = int(os.name == 'nt')
sPath = sPath[9 + slash:]
return sPath
if __name__<>"package" and __name__=="__main__":

View File

@ -381,6 +381,10 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
_.each(data.contexts, context.add, context);
_.each(data.domains, domain.add, domain);
context.add({
group_by: instance.web.pyeval.eval('groupbys', data.groupbys || [])
});
var c = instance.web.pyeval.eval('context', context);
for(var k in c) {
if (c.hasOwnProperty(k) && /^search_default_/.test(k)) {

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-08-13 02:17+0000\n"
"PO-Revision-Date: 2013-08-15 15:46+0000\n"
"Last-Translator: Laureano Kloss <Unknown>\n"
"Language-Team: Spanish (Argentina) <es_AR@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-08-13 05:00+0000\n"
"X-Launchpad-Export-Date: 2013-08-16 05:12+0000\n"
"X-Generator: Launchpad (build 16723)\n"
#. module: crm
@ -540,7 +540,7 @@ msgstr "Crear oportunidad"
#. module: crm
#: view:sale.config.settings:0
msgid "Configure"
msgstr ""
msgstr "Configurar"
#. module: crm
#: view:crm.lead:0
@ -550,19 +550,19 @@ msgstr "Escalar"
#. module: crm
#: view:crm.lead:0
msgid "Mailings"
msgstr ""
msgstr "Mailings"
#. module: crm
#: model:mail.message.subtype,description:crm.mt_lead_stage
msgid "Stage changed"
msgstr ""
msgstr "Etapa cambiada"
#. module: crm
#: selection:crm.lead.report,creation_month:0
#: selection:crm.lead.report,deadline_month:0
#: selection:crm.phonecall.report,month:0
msgid "June"
msgstr ""
msgstr "Junio"
#. module: crm
#: selection:crm.segmentation,state:0
@ -572,19 +572,19 @@ msgstr "No está en ejecución"
#. module: crm
#: field:crm.lead.report,planned_revenue:0
msgid "Planned Revenue"
msgstr "Ingreso planeado"
msgstr "Ingreso previsto"
#. module: crm
#: field:crm.lead,planned_revenue:0
msgid "Expected Revenue"
msgstr ""
msgstr "Ingreso esperado"
#. module: crm
#: selection:crm.lead.report,creation_month:0
#: selection:crm.lead.report,deadline_month:0
#: selection:crm.phonecall.report,month:0
msgid "October"
msgstr ""
msgstr "Octubre"
#. module: crm
#: view:crm.segmentation:0
@ -600,23 +600,27 @@ msgid ""
" If the call needs to be done then the status is set "
"to 'Not Held'."
msgstr ""
"El estado se establece a 'Para hacer', cuando un caso es creado. Si el caso "
"está en progreso el estado se establece a 'Abierto'. Cuando la llamada "
"finaliza, el estado se establece a 'Realizada'. si la llamada requiere ser "
"realizada entonces el estado se establece a 'No realizada'"
#. module: crm
#: field:crm.case.section,message_summary:0
#: field:crm.lead,message_summary:0
#: field:crm.phonecall,message_summary:0
msgid "Summary"
msgstr ""
msgstr "Resumen"
#. module: crm
#: view:crm.merge.opportunity:0
msgid "Merge"
msgstr ""
msgstr "Fusionar"
#. module: crm
#: model:email.template,subject:crm.email_template_opportunity_mail
msgid "Opportunity ${object.name | h})"
msgstr ""
msgstr "Oportunidad ${object.name | h})"
#. module: crm
#: view:crm.case.categ:0
@ -626,7 +630,7 @@ msgstr "Categoría del caso"
#. module: crm
#: field:crm.lead,partner_address_name:0
msgid "Partner Contact Name"
msgstr ""
msgstr "Nombre del contacto de la empresa"
#. module: crm
#: model:ir.actions.server,subject:crm.action_email_reminder_lead
@ -634,6 +638,8 @@ msgid ""
"Reminder on Lead: [[object.id ]] [[object.partner_id and 'of ' "
"+object.partner_id.name or '']]"
msgstr ""
"Recordatorio en iniciativa: [[object.id ]] [[object.partner_id and 'of ' "
"+object.partner_id.name or '']]"
#. module: crm
#: view:crm.segmentation:0
@ -643,24 +649,24 @@ msgstr "Opciones de perfiles"
#. module: crm
#: view:crm.phonecall.report:0
msgid "#Phone calls"
msgstr ""
msgstr "#Llamadas telefónicas"
#. module: crm
#: sql_constraint:crm.case.section:0
msgid "The code of the sales team must be unique !"
msgstr ""
msgstr "¡El código del equipo de ventas debe ser único!"
#. module: crm
#: help:crm.lead,email_from:0
msgid "Email address of the contact"
msgstr ""
msgstr "Dirección de correo electrónico del contacto"
#. module: crm
#: selection:crm.case.stage,state:0
#: view:crm.lead:0
#: selection:crm.lead,state:0
msgid "In Progress"
msgstr ""
msgstr "En proceso"
#. module: crm
#: model:ir.actions.act_window,help:crm.crm_phonecall_categ_action
@ -674,6 +680,13 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
"Pulse para añadir una nueva categoría.\n"
"</p><p>\n"
"Cree categorías específicas de llamadas telefónicas para definir mejor el "
"tipo de llamadas registradas en el sistema.\n"
"</p>\n"
" "
#. module: crm
#: help:crm.case.section,reply_to:0
@ -681,54 +694,57 @@ msgid ""
"The email address put in the 'Reply-To' of all emails sent by OpenERP about "
"cases in this sales team"
msgstr ""
"La dirección de correo electrónico usada como \"Responder a\" de todos los "
"correos electrónicos enviados por OpenERP para los casos de este equipo de "
"ventas."
#. module: crm
#: field:crm.lead.report,creation_month:0
msgid "Creation Month"
msgstr ""
msgstr "Mes de creación"
#. module: crm
#: field:crm.case.section,resource_calendar_id:0
#: model:ir.ui.menu,name:crm.menu_action_resource_calendar_form
msgid "Working Time"
msgstr ""
msgstr "Horario de trabajo"
#. module: crm
#: view:crm.segmentation.line:0
msgid "Partner Segmentation Lines"
msgstr "Líneas de Segmentación de Empresa"
msgstr "Líneas de segmentación de empresa"
#. module: crm
#: model:ir.actions.act_window,name:crm.action_report_crm_phonecall
#: model:ir.ui.menu,name:crm.menu_report_crm_phonecalls_tree
msgid "Phone Calls Analysis"
msgstr ""
msgstr "Análisis de llamadas"
#. module: crm
#: view:crm.lead:0
msgid "Leads Form"
msgstr ""
msgstr "Formulario de iniciativas"
#. module: crm
#: view:crm.segmentation:0
#: model:ir.model,name:crm.model_crm_segmentation
msgid "Partner Segmentation"
msgstr "Segmentación de Empresa"
msgstr "Segmentación de empresa"
#. module: crm
#: field:crm.lead,company_currency:0
msgid "Currency"
msgstr ""
msgstr "Moneda"
#. module: crm
#: field:crm.lead.report,probable_revenue:0
msgid "Probable Revenue"
msgstr ""
msgstr "Ingreso estimado"
#. module: crm
#: help:crm.lead.report,creation_month:0
msgid "Creation month"
msgstr ""
msgstr "Mes de creación"
#. module: crm
#: help:crm.segmentation,name:0
@ -743,17 +759,17 @@ msgstr "Probabilidad (%)"
#. module: crm
#: sql_constraint:crm.lead:0
msgid "The probability of closing the deal should be between 0% and 100%!"
msgstr ""
msgstr "¡La probabilidad de cierre debería estar entre 0% y 100%!"
#. module: crm
#: view:crm.lead:0
msgid "Leads Generation"
msgstr ""
msgstr "Generación de iniciativas"
#. module: crm
#: view:board.board:0
msgid "Statistics Dashboard"
msgstr ""
msgstr "Tablero de estadísticas"
#. module: crm
#: code:addons/crm/crm_lead.py:878
@ -767,48 +783,50 @@ msgstr ""
#: field:res.partner,opportunity_count:0
#, python-format
msgid "Opportunity"
msgstr ""
msgstr "Oportunidad"
#. module: crm
#: model:crm.case.resource.type,name:crm.type_lead7
msgid "Television"
msgstr ""
msgstr "Televisión"
#. module: crm
#: model:ir.actions.act_window,name:crm.action_crm_send_mass_convert
msgid "Convert to opportunities"
msgstr ""
msgstr "Convertir a oportunidad"
#. 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
msgid "Stop Process"
msgstr "Detener Proceso"
msgstr "Detener el proceso"
#. module: crm
#: field:crm.case.section,alias_id:0
msgid "Alias"
msgstr ""
msgstr "Alias"
#. module: crm
#: view:crm.phonecall:0
msgid "Search Phonecalls"
msgstr ""
msgstr "Buscar llamadas"
#. module: crm
#: view:crm.lead.report:0
msgid ""
"Leads/Opportunities that are assigned to one of the sale teams I manage"
msgstr ""
"Iniciativas/Oportunidades que están asignadas a uno de los equipos de venta "
"que gestiono"
#. module: crm
#: field:calendar.attendee,categ_id:0
msgid "Event Type"
msgstr ""
msgstr "Tipo de evento"
#. module: crm
#: field:crm.segmentation,exclusif:0
@ -819,12 +837,12 @@ msgstr "Exclusivo"
#: code:addons/crm/crm_lead.py:600
#, python-format
msgid "From %s : %s"
msgstr ""
msgstr "Desde %s : %s"
#. module: crm
#: view:crm.lead2opportunity.partner.mass:0
msgid "Convert to Opportunities"
msgstr ""
msgstr "Convertir a oportunidad"
#. module: crm
#: view:crm.lead2opportunity.partner:0
@ -833,13 +851,13 @@ msgstr ""
#: view:crm.opportunity2phonecall:0
#: view:crm.phonecall2phonecall:0
msgid "or"
msgstr ""
msgstr "o"
#. module: crm
#: field:crm.lead.report,create_date:0
#: field:crm.phonecall.report,create_date:0
msgid "Create Date"
msgstr ""
msgstr "Fecha de creación"
#. module: crm
#: field:crm.lead,ref2:0
@ -852,22 +870,24 @@ msgid ""
"Link between stages and sales teams. When set, this limitate the current "
"stage to the selected sales teams."
msgstr ""
"Enlace entre etapas y equipos de ventas. Cuando se asigna, las etapas están "
"limitadas al equipo de venta seleccionado."
#. module: crm
#: view:crm.case.stage:0
#: field:crm.case.stage,requirements:0
msgid "Requirements"
msgstr ""
msgstr "Requisitos"
#. module: crm
#: field:crm.lead,zip:0
msgid "Zip"
msgstr ""
msgstr "Código postal"
#. module: crm
#: view:crm.phonecall:0
msgid "Unassigned Phonecalls"
msgstr ""
msgstr "Llamadas sin asignar"
#. module: crm
#: view:crm.lead:0
@ -880,17 +900,17 @@ msgstr ""
#: model:process.node,name:crm.process_node_opportunities0
#: view:res.partner:0
msgid "Opportunities"
msgstr ""
msgstr "Oportunidades"
#. module: crm
#: field:crm.segmentation,categ_id:0
msgid "Partner Category"
msgstr "Categoría de partner"
msgstr "Categoría de empresa"
#. module: crm
#: field:crm.lead,probability:0
msgid "Success Rate (%)"
msgstr ""
msgstr "Tasa de éxito (%)"
#. module: crm
#: field:crm.segmentation,sales_purchase_active:0
@ -900,50 +920,50 @@ msgstr "Utiliza las reglas de compra-ventas"
#. module: crm
#: model:crm.case.categ,name:crm.categ_phone2
msgid "Outbound"
msgstr ""
msgstr "Saliente"
#. module: crm
#: view:crm.lead:0
msgid "Mark Won"
msgstr ""
msgstr "Marcar como ganado"
#. module: crm
#: model:ir.filters,name:crm.filter_usa_lead
msgid "Leads from USA"
msgstr ""
msgstr "Iniciativas de EEUU"
#. module: crm
#: view:crm.lead:0
msgid "Mark Lost"
msgstr ""
msgstr "Marcar perdido"
#. module: crm
#: model:ir.filters,name:crm.filter_draft_lead
msgid "Draft Leads"
msgstr ""
msgstr "Iniciativas borrador"
#. module: crm
#: selection:crm.lead.report,creation_month:0
#: selection:crm.lead.report,deadline_month:0
#: selection:crm.phonecall.report,month:0
msgid "March"
msgstr ""
msgstr "Marzo"
#. module: crm
#: view:crm.lead:0
msgid "Send Email"
msgstr ""
msgstr "Enviar correo electrónico"
#. module: crm
#: code:addons/crm/wizard/crm_lead_to_opportunity.py:89
#, python-format
msgid "Warning !"
msgstr "Atención !"
msgstr "Alerta!"
#. module: crm
#: field:crm.lead,day_open:0
msgid "Days to Open"
msgstr ""
msgstr "Días para abrir"
#. module: crm
#: field:crm.lead,mobile:0

View File

@ -68,11 +68,14 @@ class document_file(osv.osv):
]
def check(self, cr, uid, ids, mode, context=None, values=None):
"""Check access wrt. res_model, relax the rule of ir.attachment parent
With 'document' installed, everybody will have access to attachments of
any resources they can *read*.
"""
return super(document_file, self).check(cr, uid, ids, mode='read', context=context, values=values)
"""Overwrite check to verify access on directory to validate specifications of doc/access_permissions.rst"""
super(document_file, self).check(cr, uid, ids, mode, context=context, values=values)
if ids:
self.pool.get('ir.model.access').check(cr, uid, 'document.directory', mode)
# use SQL to avoid recursive loop on read
cr.execute('SELECT DISTINCT parent_id from ir_attachment WHERE id in %s AND parent_id is not NULL', (tuple(ids),))
self.pool.get('document.directory').check_access_rule(cr, uid, [parent_id for (parent_id,) in cr.fetchall()], mode, context=context)
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
# Grab ids, bypassing 'count'

View File

@ -157,7 +157,8 @@ class mail_compose_message(osv.TransientModel):
values['body'] = values.pop('body_html', '')
# transform email_to, email_cc into partner_ids
partner_ids = self._get_or_create_partners_from_values(cr, uid, values, context=context)
ctx = dict((k, v) for k, v in (context or {}).items() if not k.startswith('default_'))
partner_ids = self._get_or_create_partners_from_values(cr, uid, values, context=ctx)
# legacy template behavior: void values do not erase existing values and the
# related key is removed from the values dict
if partner_ids:

View File

@ -173,10 +173,9 @@ class account_analytic_line(osv.osv):
data = {}
journal_types = {}
price = 0.0
# prepare for iteration on journal and accounts
for line in self.pool.get('account.analytic.line').browse(cr, uid, ids, context=context):
price += line.amount*-1
line_name = line.name
if line.journal_id.type not in journal_types:
journal_types[line.journal_id.type] = set()
journal_types[line.journal_id.type].add(line.account_id.id)
@ -217,53 +216,56 @@ class account_analytic_line(osv.osv):
last_invoice = invoice_obj.create(cr, uid, curr_invoice, context=context2)
invoices.append(last_invoice)
cr.execute("""SELECT product_id, user_id, to_invoice, sum(unit_amount), product_uom_id
cr.execute("""SELECT product_id, user_id, to_invoice, sum(amount), sum(unit_amount), product_uom_id
FROM account_analytic_line as line LEFT JOIN account_analytic_journal journal ON (line.journal_id = journal.id)
WHERE account_id = %s
AND line.id IN %s AND journal.type = %s AND to_invoice IS NOT NULL
GROUP BY product_id, user_id, to_invoice, product_uom_id""", (account.id, tuple(ids), journal_type))
for product_id, user_id, factor_id, qty, uom in cr.fetchall():
for product_id, user_id, factor_id, total_price, qty, uom in cr.fetchall():
context2.update({'uom': uom})
if data.get('product'):
# force product, use its public price
product_id = data['product'][0]
product = product_obj.browse(cr, uid, product_id, context=context2)
unit_price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, context2)
elif journal_type == 'general' and product_id:
# timesheets, use sale price
unit_price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, context2)
else:
# expenses, using price from amount field
unit_price = total_price*-1.0 / qty
factor = invoice_factor_obj.browse(cr, uid, factor_id, context=context2)
factor_name = factor.customer_name and line_name + ' - ' + factor.customer_name or line_name
# factor_name = factor.customer_name and line_name + ' - ' + factor.customer_name or line_name
factor_name = factor.customer_name
curr_line = {
'price_unit': price,
'price_unit': unit_price,
'quantity': qty,
'product_id': product_id or False,
'discount': factor.factor,
'invoice_id': last_invoice,
'name': factor_name,
'uos_id': uom,
'account_analytic_id': account.id,
}
product = product_obj.browse(cr, uid, product_id, context=context2)
if product:
factor_name = product_obj.name_get(cr, uid, [product_id], context=context2)[0][1]
if factor.customer_name:
factor_name += ' - ' + factor.customer_name
ctx = context.copy()
ctx.update({'uom': uom})
# check force product
if data.get('product'):
price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, ctx)
general_account = product.property_account_income or product.categ_id.property_account_income_categ
if not general_account:
raise osv.except_osv(_("Configuration Error!"), _("Please define income account for product '%s'.") % product.name)
taxes = product.taxes_id or general_account.tax_ids
tax = fiscal_pos_obj.map_tax(cr, uid, account.partner_id.property_account_position, taxes)
curr_line.update({
'price_unit': price,
'invoice_line_tax_id': [(6,0,tax )],
'name': factor_name,
'product_id': product_id,
'invoice_line_tax_id': [(6,0,tax)],
'account_id': general_account.id,
})
#
# Compute for lines
#
@ -284,7 +286,6 @@ class account_analytic_line(osv.osv):
if data.get('name', False):
details.append(line['name'])
note.append(u' - '.join(map(lambda x: unicode(x) or '',details)))
if note:
curr_line['name'] += "\n" + ("\n".join(map(lambda x: unicode(x) or '',note)))
invoice_line_obj.create(cr, uid, curr_line, context=context)

View File

@ -61,12 +61,13 @@
!python {model: hr_timesheet_sheet.sheet}: |
uid = ref('base.user_root')
from openerp import netsvc
from openerp.osv import osv
try:
self.button_confirm(cr, uid, [ref('hr_timesheet_sheet_sheet_deddk0')], {"active_ids":
[ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form")],"active_id": ref("hr_timesheet_sheet.menu_act_hr_timesheet_sheet_form"),
})
assert True, "The validation of the timesheet was unexpectedly accepted despite the 2:30 hours of difference"
except:
assert False, "The validation of the timesheet was unexpectedly accepted despite the 2:30 hours of difference"
except osv.except_osv:
pass
-
I Modified the timesheet record and make the difference less than 1 hour.

20
addons/im/Gruntfile.js Normal file
View File

@ -0,0 +1,20 @@
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
src: ['static/src/js/*.js'],
options: {
sub: true, //[] instead of .
evil: true, //eval
laxbreak: true, //unsafe line breaks
},
},
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('test', []);
grunt.registerTask('default', ['jshint']);
};

View File

@ -18,7 +18,10 @@ chat in real time. It support several chats in parallel.
'security/im_security.xml',
],
'depends' : ['base', 'web'],
'js': ['static/src/js/*.js'],
'js': [
'static/src/js/im_common.js',
'static/src/js/im.js',
],
'css': ['static/src/css/*.css'],
'qweb': ['static/src/xml/*.xml'],
'installable': True,

View File

@ -130,7 +130,7 @@ class LongPollingController(http.Controller):
return "%s" % uuid.uuid1()
def assert_uuid(uuid):
if not isinstance(uuid, (str, unicode, type(None))):
if not isinstance(uuid, (str, unicode, type(None))) and uuid != False:
raise Exception("%s is not a uuid" % uuid)

6
addons/im/package.json Normal file
View File

@ -0,0 +1,6 @@
{
"devDependencies": {
"grunt": "*",
"grunt-contrib-jshint": "*"
}
}

View File

@ -105,160 +105,3 @@
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;
}

View File

@ -36,7 +36,7 @@
.oe_im_chatview {
position: fixed;
overflow: hidden;
bottom: 42px;
margin-bottom: 5px;
margin-right: 6px;
background: rgba(60, 60, 60, 0.8);
-moz-border-radius: 3px;

View File

@ -1,17 +1,25 @@
openerp.im = function(instance) {
(function() {
"use strict";
var instance = openerp;
openerp.im = {};
var USERS_LIMIT = 20;
var ERROR_DELAY = 5000;
var _t = instance.web._t,
_lt = instance.web._lt;
var _t = instance.web._t;
var QWeb = instance.web.qweb;
instance.web.UserMenu.include({
do_update: function(){
var self = this;
this.update_promise.then(function() {
im_common.notification = function(message) {
instance.client.do_warn(message);
};
im_common.connection = openerp.session;
var im = new instance.im.InstantMessaging(self);
im.appendTo(instance.client.$el);
var button = new instance.im.ImTopButton(this);
@ -45,7 +53,7 @@ openerp.im = function(instance) {
this.set("right_offset", 0);
this.set("current_search", "");
this.users = [];
this.c_manager = new instance.im.ConversationManager(this);
this.c_manager = new im_common.ConversationManager(this);
this.on("change:right_offset", this.c_manager, _.bind(function() {
this.c_manager.set("right_offset", this.get("right_offset"));
}, this));
@ -148,323 +156,4 @@ openerp.im = function(instance) {
},
});
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() {
if (typeof(Audio) === "undefined") {
this.ting = {play: function() {}};
return;
}
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();
if (! mes.trim()) {
return;
}
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,408 @@
/*
This file must compile in EcmaScript 3 and work in IE7.
Prerequisites to use this module:
- load the im_common.xml qweb template into openerp.qweb
- implement all the stuff defined later
*/
(function() {
function declare($, _, openerp) {
/* jshint es3: true */
"use strict";
var im_common = {};
/*
All of this must be defined to use this module
*/
_.extend(im_common, {
notification: function(message) {
throw new Error("Not implemented");
},
connection: null
});
var _t = openerp._t;
var ERROR_DELAY = 5000;
im_common.ImUser = openerp.Class.extend(openerp.PropertiesMixin, {
init: function(parent, user_rec) {
openerp.PropertiesMixin.init.call(this, parent);
user_rec.image_url = im_common.connection.url("/im/static/src/img/avatar/avatar.jpeg");
// TODO : check it works correctly
if (user_rec.user)
user_rec.image_url = im_common.connection.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.user[0]});
/*if (user_rec.image)
user_rec.image_url = "data:image/png;base64," + user_rec.image;*/
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");
openerp.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);
}
});
im_common.ConversationManager = openerp.Class.extend(openerp.PropertiesMixin, {
init: function(parent, options) {
openerp.PropertiesMixin.init.call(this, parent);
this.options = _.clone(options) || {};
_.defaults(this.options, {
inputPlaceholder: _t("Say something..."),
defaultMessage: null,
userName: _t("Anonymous"),
anonymous_mode: false
});
this.set("right_offset", 0);
this.set("bottom_offset", 0);
this.conversations = [];
this.users = {};
this.on("change:right_offset", this, this.calc_positions);
this.on("change:bottom_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;
var auth_def = null;
var user_id = null;
if (this.options.anonymous_mode) {
var uuid = localStorage["oe_livesupport_uuid"];
var def = $.when(uuid);
if (! uuid) {
def = im_common.connection.rpc("/longpolling/im/gen_uuid", {});
}
var anonymous_user_id = null;
auth_def = def.then(function(uuid) {
localStorage["oe_livesupport_uuid"] = uuid;
return im_common.connection.model("im.user").call("get_by_user_id", [uuid]);
}).then(function(my_id) {
user_id = my_id["id"];
return im_common.connection.model("im.user").call("assign_name", [uuid, self.options.userName]);
});
} else {
auth_def = im_common.connection.model("im.user").call("get_by_user_id",
[im_common.connection.uid]).then(function(my_id) {
user_id = my_id["id"];
});
}
return auth_def.then(function() {
self.my_id = user_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;
me.set("name", _t("You"));
return im_common.connection.rpc("/longpolling/im/activated", {}, {shadow: true});
}).then(function(activated) {
if (activated) {
self.activated = true;
$(window).on("unload", self.unload_event_handler);
self.poll();
} else {
return $.Deferred().reject();
}
}, function(a, e) {
e.preventDefault();
});
},
unload: function() {
return im_common.connection.model("im.user").call("im_disconnect", [], {uuid: this.me.get("uuid"), context: {}});
},
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 im_common.connection.model("im.user").call("read", [_.values(no_cache), []]).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 im_common.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");
});
im_common.connection.rpc("/longpolling/im/poll", {
last: this.last,
users_watch: user_ids,
uuid: self.me.get("uuid")
}, {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() {
if (typeof(Audio) === "undefined") {
this.ting = {play: function() {}};
return;
}
var kitten = jQuery.deparam !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined;
this.ting = new Audio(im_common.connection.url(
"/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 (! openerp.webclient || !openerp.webclient.set_title_part)
return;
openerp.webclient.set_title_part("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 im_common.Conversation(this, user, this.me, this.options);
conv.appendTo($("body"));
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("bottom_position", this.get("bottom_offset"));
this.conversations[i].set("right_position", current);
current += this.conversations[i].$().outerWidth(true);
}, this);
},
destroy: function() {
$(window).off("unload", this.unload_event_handler);
$(window).unbind("blur", this.blur_hdl);
$(window).unbind("focus", this.focus_hdl);
openerp.PropertiesMixin.destroy.call(this);
}
});
im_common.Conversation = openerp.Widget.extend({
className: "openerp_style oe_im_chatview",
events: {
"keydown input": "send_message",
"click .oe_im_chatview_close": "destroy",
"click .oe_im_chatview_header": "show_hide"
},
init: function(parent, user, me, options) {
this._super(parent);
this.options = options;
this.me = me;
this.user = user;
this.user.add_watcher();
this.set("right_position", 0);
this.set("bottom_position", 0);
this.shown = true;
this.set("pending", 0);
this.inputPlaceholder = this.options.defaultInputPlaceholder;
},
start: function() {
this.$().append(openerp.qweb.render("im_common.conversation", {widget: this, to_url: _.bind(im_common.connection.url, im_common.connection)}));
var change_status = function() {
this.$().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.on("change:bottom_position", this, this.calc_pos);
this.full_height = this.$().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.$().animate({
height: this.$(".oe_im_chatview_header").outerHeight()
});
} else {
this.$().animate({
height: this.full_height
});
}
this.shown = ! this.shown;
if (this.shown) {
this.set("pending", 0);
}
},
calc_pos: function() {
this.$().css("right", this.get("right_position"));
this.$().css("bottom", this.get("bottom_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, openerp.str_to_datetime(message.date));
},
send_message: function(e) {
if(e && e.which !== 13) {
return;
}
var mes = this.$("input").val();
if (! mes.trim()) {
return;
}
this.$("input").val("");
var send_it = _.bind(function() {
var model = im_common.connection.model("im.message");
return model.call("post", [mes, this.user.get('id')], {uuid: this.me.get("uuid"), context: {}});
}, this);
var tries = 0;
send_it().then(_.bind(function() {
this._add_bubble(this.me, mes, 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;
var zpad = function(str, size) {
str = "" + str;
return new Array(size - str.length + 1).join('0') + str;
};
date = "" + zpad(date.getHours(), 2) + ":" + zpad(date.getMinutes(), 2);
this.last_bubble = $(openerp.qweb.render("im_common.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();
}
});
return im_common;
}
if (typeof(define) !== "undefined") {
define(["jquery", "underscore", "openerp"], declare);
} else {
window.im_common = declare($, _, openerp);
}
})();

View File

@ -27,37 +27,4 @@
<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,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="im_common.conversation">
<div class="oe_im_chatview_header">
<img t-att-src="to_url('/im/static/src/img/green.png')" class="oe_im_chatview_online"/>
<t t-esc="widget.user.get('name')"/>
<scan class="oe_im_chatview_nbr_messages" />
<button class="oe_im_chatview_close">×</button>
</div>
<div class="oe_im_chatview_disconnected">
<t t-esc='widget.user.get("name") + _t(" is offline. He/She will receive your messages on his/her next connection.")'/>
</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="widget.inputPlaceholder" />
</div>
</t>
<t t-name="im_common.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')"/></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

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

View File

@ -1,19 +1,40 @@
(function() {
var tmpQWeb2 = window.QWeb2;
require.config({
context: "oelivesupport",
baseUrl: {{url | json}} + "/im_livechat/static/ext/static/js",
baseUrl: {{url | json}},
paths: {
jquery: "im_livechat/static/ext/static/lib/jquery/jquery",
underscore: "im_livechat/static/ext/static/lib/underscore/underscore",
qweb2: "im_livechat/static/ext/static/lib/qweb/qweb2",
openerp: "web/static/src/js/openerpframework",
"jquery.achtung": "im_livechat/static/ext/static/lib/jquery-achtung/src/ui.achtung",
livesupport: "im_livechat/static/ext/static/js/livesupport",
im_common: "im/static/src/js/im_common"
},
shim: {
underscore: {
init: function() {
return _.noConflict();
},
},
qweb2: {
init: function() {
var QWeb2 = window.QWeb2;
window.QWeb2 = tmpQWeb2;
return QWeb2;
},
},
"jquery.achtung": {
deps: ['jquery'],
},
},
})(["livesupport", "jquery"], function(livesupport, jQuery) {
jQuery.noConflict();
console.log("loaded live support");
livesupport.main({{url | json}}, {{db | json}}, "anonymous", "anonymous", {{channel | json}}, {
buttonText: {{buttonText | json}},
inputPlaceholder: {{inputPlaceholder | json}},
@ -22,3 +43,5 @@ require.config({
userName: {{userName | json}} || undefined,
});
});
})();

View File

@ -0,0 +1,3 @@
{
"directory": "static/lib/"
}

View File

@ -0,0 +1,20 @@
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
src: ['static/js/*.js'],
options: {
sub: true, //[] instead of .
evil: true, //eval
laxbreak: true, //unsafe line breaks
},
},
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('test', []);
grunt.registerTask('default', ['jshint']);
};

View File

@ -0,0 +1,18 @@
{
"name": "im_livechat",
"version": "0.0.0",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "1.8.3",
"underscore": "1.3.1",
"qweb": "git@github.com:OpenERP/qweb.git#~1.0.0",
"jquery-achtung": "git://github.com/joshvarner/jquery-achtung.git",
"requirejs": "~2.1.8"
}
}

View File

@ -0,0 +1,6 @@
{
"devDependencies": {
"grunt": "*",
"grunt-contrib-jshint": "*"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

View File

@ -1,273 +0,0 @@
/**
* achtung 0.3.0
*
* Growl-like notifications for jQuery
*
* Copyright (c) 2009 Josh Varner <josh@voxwerk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @license http://www.opensource.org/licenses/mit-license.php
* @author Josh Varner <josh@voxwerk.com>
*/
/*globals jQuery,clearTimeout,document,navigator,setTimeout
*/
(function($) {
/**
* This is based on the jQuery UI $.widget code. I would have just made this
* a $.widget but I didn't want the jQuery UI dependency.
*/
$.fn.achtung = function(options)
{
var isMethodCall = (typeof options === 'string'),
args = Array.prototype.slice.call(arguments, 0),
name = 'achtung';
// handle initialization and non-getter methods
return this.each(function() {
var instance = $.data(this, name);
// prevent calls to internal methods
if (isMethodCall && options.substring(0, 1) === '_') {
return this;
}
// constructor
(!instance && !isMethodCall &&
$.data(this, name, new $.achtung(this))._init(args));
// method call
(instance && isMethodCall && $.isFunction(instance[options]) &&
instance[options].apply(instance, args.slice(1)));
});
};
$.achtung = function(element)
{
var args = Array.prototype.slice.call(arguments, 0), $el;
if (!element || !element.nodeType) {
$el = $('<div />');
return $el.achtung.apply($el, args);
}
this.$container = $(element);
};
/**
* Static members
**/
$.extend($.achtung, {
version: '0.3.0',
$overlay: false,
defaults: {
timeout: 10,
disableClose: false,
icon: false,
className: '',
animateClassSwitch: false,
showEffects: {'opacity':'toggle','height':'toggle'},
hideEffects: {'opacity':'toggle','height':'toggle'},
showEffectDuration: 500,
hideEffectDuration: 700
}
});
/**
* Non-static members
**/
$.extend($.achtung.prototype, {
$container: false,
closeTimer: false,
options: {},
_init: function(args)
{
var o, self = this;
args = $.isArray(args) ? args : [];
args.unshift($.achtung.defaults);
args.unshift({});
o = this.options = $.extend.apply($, args);
if (!$.achtung.$overlay) {
$.achtung.$overlay = $('<div id="achtung-overlay"></div>').appendTo(document.body);
}
if (!o.disableClose) {
$('<span class="achtung-close-button ui-icon ui-icon-close" />')
.click(function () { self.close(); })
.hover(function () { $(this).addClass('achtung-close-button-hover'); },
function () { $(this).removeClass('achtung-close-button-hover'); })
.prependTo(this.$container);
}
this.changeIcon(o.icon, true);
if (o.message) {
this.$container.append($('<span class="achtung-message">' + o.message + '</span>'));
}
(o.className && this.$container.addClass(o.className));
(o.css && this.$container.css(o.css));
this.$container
.addClass('achtung')
.appendTo($.achtung.$overlay);
if (o.showEffects) {
this.$container.toggle();
} else {
this.$container.show();
}
if (o.timeout > 0) {
this.timeout(o.timeout);
}
},
timeout: function(timeout)
{
var self = this;
if (this.closeTimer) {
clearTimeout(this.closeTimer);
}
this.closeTimer = setTimeout(function() { self.close(); }, timeout * 1000);
this.options.timeout = timeout;
},
/**
* Change the CSS class associated with this message, using
* a transition if available (not availble in Safari/Webkit).
* If no transition is available, the switch is immediate.
*
* #LATER Check if this has been corrected in Webkit or jQuery UI
* #TODO Make transition time configurable
* @param newClass string Name of new class to associate
*/
changeClass: function(newClass)
{
var self = this;
if (this.options.className === newClass) {
return;
}
this.$container.queue(function() {
if (!self.options.animateClassSwitch ||
/webkit/.test(navigator.userAgent.toLowerCase()) ||
!$.isFunction($.fn.switchClass)) {
self.$container.removeClass(self.options.className);
self.$container.addClass(newClass);
} else {
self.$container.switchClass(self.options.className, newClass, 500);
}
self.options.className = newClass;
self.$container.dequeue();
});
},
changeIcon: function(newIcon, force)
{
var self = this;
if ((force !== true || newIcon === false) && this.options.icon === newIcon) {
return;
}
if (force || this.options.icon === false) {
this.$container.prepend($('<span class="achtung-message-icon ui-icon ' + newIcon + '" />'));
this.options.icon = newIcon;
return;
} else if (newIcon === false) {
this.$container.find('.achtung-message-icon').remove();
this.options.icon = false;
return;
}
this.$container.queue(function() {
var $span = $('.achtung-message-icon', self.$container);
if (!self.options.animateClassSwitch ||
/webkit/.test(navigator.userAgent.toLowerCase()) ||
!$.isFunction($.fn.switchClass)) {
$span.removeClass(self.options.icon);
$span.addClass(newIcon);
} else {
$span.switchClass(self.options.icon, newIcon, 500);
}
self.options.icon = newIcon;
self.$container.dequeue();
});
},
changeMessage: function(newMessage)
{
this.$container.queue(function() {
$('.achtung-message', $(this)).html(newMessage);
$(this).dequeue();
});
},
update: function(options)
{
(options.className && this.changeClass(options.className));
(options.css && this.$container.css(options.css));
(typeof(options.icon) !== 'undefined' && this.changeIcon(options.icon));
(options.message && this.changeMessage(options.message));
(options.timeout && this.timeout(options.timeout));
},
close: function()
{
var o = this.options, $container = this.$container;
if (o.hideEffects) {
this.$container.animate(o.hideEffects, o.hideEffectDuration);
} else {
this.$container.hide();
}
$container.queue(function() {
$container.removeData('achtung');
$container.remove();
if ($.achtung.$overlay && $.achtung.$overlay.is(':empty')) {
$.achtung.$overlay.remove();
$.achtung.$overlay = false;
}
$container.dequeue();
});
}
});
})(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="chatButton">
<t t-esc="widget.text"/>
</t>
</templates>

View File

@ -1,46 +1,48 @@
define(["nova", "underscore", "oeclient", "require", "jquery",
"jquery.achtung"], function(nova, _, oeclient, require, $) {
/*
This file must compile in EcmaScript 3 and work in IE7.
*/
define(["openerp", "im_common", "underscore", "require", "jquery",
"jquery.achtung"], function(openerp, im_common, _, require, $) {
/* jshint es3: true */
"use strict";
var _t = openerp._t;
var livesupport = {};
var templateEngine = new nova.TemplateEngine();
templateEngine.extendEnvironment({"toUrl": _.bind(require.toUrl, require)});
var connection;
var defaultInputPlaceholder;
var userName;
livesupport.main = function(server_url, db, login, password, channel, options) {
var defs = [];
options = options || {};
_.defaults(options, {
buttonText: "Chat with one of our collaborators",
inputPlaceholder: "How may I help you?",
buttonText: _t("Chat with one of our collaborators"),
inputPlaceholder: _t("How may I help you?"),
defaultMessage: null,
auto: false,
userName: "Anonymous",
userName: _t("Anonymous"),
anonymous_mode: true
});
defaultInputPlaceholder = options.inputPlaceholder;
userName = options.userName;
defs.push($.ajax({
url: require.toUrl("./livesupport_templates.js"),
jsonp: false,
jsonpCallback: "oe_livesupport_templates_callback",
dataType: "jsonp",
cache: true,
}).then(function(content) {
return templateEngine.loadFileContent(content);
}));
defs.push(add_css("../css/livesupport.css"));
defs.push(add_css("./jquery.achtung.css"));
$.when.apply($, defs).then(function() {
console.log("starting live support customer app");
connection = new oeclient.Connection(new oeclient.JsonpRPCConnector(server_url), db, login, password);
connection.connector.call("/im_livechat/available", {db: db, channel: channel}).then(function(activated) {
im_common.notification = notification;
console.log("starting live support customer app");
im_common.connection = new openerp.Session(null, server_url, { override_session: true });
return im_common.connection.session_authenticate(db, login, password).then(function() {
var defs = [];
defs.push(add_css("/im/static/src/css/im_common.css"));
defs.push(add_css("/im_livechat/static/ext/static/lib/jquery-achtung/src/ui.achtung.css"));
defs.push(im_common.connection.rpc('/web/proxy/load', {path: '/im_livechat/static/ext/static/js/livechat.xml'}).then(function(xml) {
openerp.qweb.add_template(xml);
}));
defs.push(im_common.connection.rpc('/web/proxy/load', {path: '/im/static/src/xml/im_common.xml'}).then(function(xml) {
openerp.qweb.add_template(xml);
}));
return $.when.apply($, defs);
}).then(function() {
return im_common.connection.rpc("/im_livechat/available", {db: db, channel: channel}).then(function(activated) {
if (! activated & ! options.auto)
return;
var button = new livesupport.ChatButton(null, channel, options);
var button = new im_common.ChatButton(null, channel, options);
button.appendTo($("body"));
if (options.auto)
button.click();
@ -50,7 +52,7 @@ define(["nova", "underscore", "oeclient", "require", "jquery",
var add_css = function(relative_file_name) {
var css_def = $.Deferred();
$('<link rel="stylesheet" href="' + require.toUrl(relative_file_name) + '"></link>')
$('<link rel="stylesheet" href="' + im_common.connection.url(relative_file_name) + '"></link>')
.appendTo($("head")).ready(function() {
css_def.resolve();
});
@ -61,25 +63,24 @@ define(["nova", "underscore", "oeclient", "require", "jquery",
$.achtung({message: message, timeout: 0, showEffects: false, hideEffects: false});
};
var ERROR_DELAY = 5000;
livesupport.ChatButton = nova.Widget.$extend({
im_common.ChatButton = openerp.Widget.extend({
className: "openerp_style oe_chat_button",
events: {
"click": "click",
"click": "click"
},
__init__: function(parent, channel, options) {
this.$super(parent);
init: function(parent, channel, options) {
this._super(parent);
this.channel = channel;
this.options = options;
this.text = options.buttonText;
},
render: function() {
this.$().append(templateEngine.chatButton({widget: this}));
start: function() {
this.$().append(openerp.qweb.render("chatButton", {widget: this}));
},
click: function() {
if (! this.manager) {
this.manager = new livesupport.ConversationManager(null);
this.manager = new im_common.ConversationManager(this, this.options);
this.manager.set("bottom_offset", 37);
this.activated_def = this.manager.start_polling();
}
var def = $.Deferred();
@ -92,362 +93,28 @@ define(["nova", "underscore", "oeclient", "require", "jquery",
def.reject();
}, 5000);
def.then(_.bind(this.chat, this), function() {
notification("It seems the connection to the server is encountering problems, please try again later.");
im_common.notification(_t("It seems the connection to the server is encountering problems, please try again later."));
});
},
chat: function() {
var self = this;
if (this.manager.conversations.length > 0)
return;
connection.getModel("im_livechat.channel").call("get_available_user", [this.channel]).then(function(user_id) {
im_common.connection.model("im_livechat.channel").call("get_available_user", [this.channel]).then(function(user_id) {
if (! user_id) {
notification("None of our collaborators seems to be available, please try again later.");
im_common.notification(_t("None of our collaborators seems to be available, please try again later."));
return;
}
self.manager.ensure_users([user_id]).then(function() {
var conv = self.manager.activate_user(self.manager.get_user(user_id), true);
if (self.options.defaultMessage) {
conv.received_message({message: self.options.defaultMessage,
date: oeclient.datetime_to_str(new Date())});
date: openerp.datetime_to_str(new Date())});
}
});
});
},
}
});
livesupport.ImUser = nova.Class.$extend({
__include__: [nova.DynamicProperties],
__init__: function(parent, user_rec) {
nova.DynamicProperties.__init__.call(this, parent);
user_rec.image_url = require.toUrl("../img/avatar/avatar.jpeg");
if (user_rec.image)
user_rec.image_url = "data:image/png;base64," + user_rec.image;
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");
nova.DynamicProperties.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);
},
});
livesupport.ConversationManager = nova.Class.$extend({
__include__: [nova.DynamicProperties],
__init__: function(parent) {
nova.DynamicProperties.__init__.call(this, 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;
var uuid = localStorage["oe_livesupport_uuid"];
var def = $.when(uuid);
if (! uuid) {
def = connection.connector.call("/longpolling/im/gen_uuid", {});
}
return def.then(function(uuid) {
localStorage["oe_livesupport_uuid"] = uuid;
return connection.getModel("im.user").call("get_by_user_id", [uuid]);
}).then(function(my_id) {
self.my_id = my_id["id"];
return connection.getModel("im.user").call("assign_name", [uuid, userName]);
}).then(function() {
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;
me.set("name", "You");
return connection.connector.call("/longpolling/im/activated", {});
}).then(function(activated) {
if (activated) {
self.activated = true;
$(window).on("unload", self.unload_event_handler);
self.poll();
} else {
return $.Deferred().reject();
}
});
},
unload: function() {
connection.getModel("im.user").call("im_disconnect", [], {uuid: this.me.get("uuid"), context: {}});
},
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 connection.getModel("im.user").call("read", [_.values(no_cache), []]).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 livesupport.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() {
console.debug("live support beggin polling");
var self = this;
var user_ids = _.map(this.users_cache, function(el) {
return el.get("id");
});
connection.connector.call("/longpolling/im/poll", {
last: this.last,
users_watch: user_ids,
db: connection.database,
uid: connection.userId,
password: connection.password,
uuid: self.me.get("uuid"),
}).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() {
setTimeout(_.bind(self.poll, self), ERROR_DELAY);
});
},
get_activated: function() {
return this.activated;
},
create_ting: function() {
if (typeof(Audio) === "undefined") {
this.ting = {play: function() {}};
return;
}
this.ting = new Audio(new Audio().canPlayType("audio/ogg; codecs=vorbis") ?
require.toUrl("../audio/Ting.ogg") :
require.toUrl("../audio/Ting.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("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 livesupport.Conversation(this, user, this.me);
conv.appendTo($("body"));
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].$().outerWidth(true);
}, this);
},
destroy: function() {
$(window).off("unload", this.unload_event_handler);
$(window).unbind("blur", this.blur_hdl);
$(window).unbind("focus", this.focus_hdl);
nova.DynamicProperties.destroy.call(this);
},
});
livesupport.Conversation = nova.Widget.$extend({
className: "openerp_style oe_im_chatview",
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);
this.inputPlaceholder = defaultInputPlaceholder;
},
render: function() {
this.$().append(templateEngine.conversation({widget: this}));
var change_status = function() {
this.$().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.$().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.$().animate({
height: this.$(".oe_im_chatview_header").outerHeight(),
});
} else {
this.$().animate({
height: this.full_height,
});
}
this.shown = ! this.shown;
if (this.shown) {
this.set("pending", 0);
}
},
calc_pos: function() {
this.$().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, oeclient.str_to_datetime(message.date));
},
send_message: function(e) {
if(e && e.which !== 13) {
return;
}
var mes = this.$("input").val();
if (! mes.trim()) {
return;
}
this.$("input").val("");
var send_it = _.bind(function() {
var model = connection.getModel("im.message");
return model.call("post", [mes, this.user.get('id')], {uuid: this.me.get("uuid"), context: {}});
}, this);
var tries = 0;
send_it().then(_.bind(function() {
this._add_bubble(this.me, mes, new Date());
}, this), function(error, e) {
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;
var zpad = function(str, size) {
str = "" + str;
return new Array(size - str.length + 1).join('0') + str;
};
date = "" + zpad(date.getHours(), 2) + ":" + zpad(date.getMinutes(), 2);
this.last_bubble = $(templateEngine.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();
},
destroy: function() {
this.user.remove_watcher();
this.trigger("destroyed");
return this.$super();
},
});
return livesupport;
});

View File

@ -1,36 +0,0 @@
<%def name="conversation">
<div class="oe_im_chatview_header">
<img src="${toUrl('../img/green.png')}" class="oe_im_chatview_online"/>
${widget.user.get('name') || 'You'}
<button class="oe_im_chatview_close">×</button>
</div>
<div class="oe_im_chatview_disconnected">
${widget.user.get("name") + " is offline. He/She will receive your messages on his/her next connection."}
</div>
<div class="oe_im_chatview_content">
<div></div>
</div>
<div class="oe_im_chatview_footer">
<input class="oe_im_chatview_input" placeholder="${widget.inputPlaceholder}" />
</div>
</%def>
<%def name="conversation_bubble">
<div class="oe_im_chatview_bubble">
<div class="oe_im_chatview_clip">
<img class="oe_im_chatview_avatar" src="${user.get('image_url')}"/>
</div>
<div class="oe_im_chatview_from">${user.get('name') || 'You'}</div>
<div class="oe_im_chatview_bubble_list">
% _.each(items, function(item) {
<div class="oe_im_chatview_bubble_item">${item}</div>
% });
</div>
<div class="oe_im_chatview_time">${time}</div>
</div>
</%def>
<%def name="chatButton">
${widget.text}
</%def>

View File

@ -1 +0,0 @@
window.oe_livesupport_templates_callback("\n<%def name=\"conversation\">\n <div class=\"oe_im_chatview_header\">\n <img src=\"${toUrl('../img/green.png')}\" class=\"oe_im_chatview_online\"/>\n ${widget.user.get('name') || 'You'}\n <button class=\"oe_im_chatview_close\">\u00d7</button>\n </div>\n <div class=\"oe_im_chatview_disconnected\">\n ${widget.user.get(\"name\") + \" is offline. He/She will receive your messages on his/her next connection.\"}\n </div>\n <div class=\"oe_im_chatview_content\">\n <div></div>\n </div>\n <div class=\"oe_im_chatview_footer\">\n <input class=\"oe_im_chatview_input\" placeholder=\"${widget.inputPlaceholder}\" />\n </div>\n</%def>\n\n<%def name=\"conversation_bubble\">\n <div class=\"oe_im_chatview_bubble\">\n <div class=\"oe_im_chatview_clip\">\n <img class=\"oe_im_chatview_avatar\" src=\"${user.get('image_url')}\"/>\n </div>\n <div class=\"oe_im_chatview_from\">${user.get('name') || 'You'}</div>\n <div class=\"oe_im_chatview_bubble_list\">\n % _.each(items, function(item) {\n <div class=\"oe_im_chatview_bubble_item\">${item}</div>\n % });\n </div>\n <div class=\"oe_im_chatview_time\">${time}</div>\n </div>\n</%def>\n\n<%def name=\"chatButton\">\n ${widget.text}\n</%def>");

View File

@ -1,988 +0,0 @@
/*
Copyright (c) 2012, Nicolas Vanhoren
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
(function() {
if (typeof(define) !== "undefined") { // requirejs
define(["jquery", "underscore"], nova_declare);
} else if (typeof(exports) !== "undefined") { // node
var _ = require("underscore")
_.extend(exports, nova_declare(null, _));
} else { // define global variable 'nova'
nova = nova_declare($, _);
}
function nova_declare($, _) {
var nova = {};
nova.internal = {};
/*
* Modified Armin Ronacher's Classy library.
*
* Defines The Class object. That object can be used to define and inherit classes using
* the $extend() method.
*
* Example:
*
* var Person = nova.Class.$extend({
* __init__: function(isDancing){
* this.dancing = isDancing;
* },
* dance: function(){
* return this.dancing;
* }
* });
*
* The __init__() method act as a constructor. This class can be instancied this way:
*
* var person = new Person(true);
* person.dance();
*
* The Person class can also be extended again:
*
* var Ninja = Person.$extend({
* __init__: function(){
* this.$super( false );
* },
* dance: function(){
* // Call the inherited version of dance()
* return this.$super();
* },
* swingSword: function(){
* return true;
* }
* });
*
* When extending a class, each re-defined method can use this.$super() to call the previous
* implementation of that method.
*/
/**
* Classy - classy classes for JavaScript
*
* :copyright: (c) 2011 by Armin Ronacher.
* :license: BSD.
*/
(function(){
var
context = this,
disable_constructor = false;
/* we check if $super is in use by a class if we can. But first we have to
check if the JavaScript interpreter supports that. This also matches
to false positives later, but that does not do any harm besides slightly
slowing calls down. */
var probe_super = (function(){this.$super();}).toString().indexOf('$super') > 0;
function usesSuper(obj) {
return !probe_super || /\B\$super\b/.test(obj.toString());
}
/* helper function to set the attribute of something to a value or
removes it if the value is undefined. */
function setOrUnset(obj, key, value) {
if (value === undefined)
delete obj[key];
else
obj[key] = value;
}
/* gets the own property of an object */
function getOwnProperty(obj, name) {
return Object.prototype.hasOwnProperty.call(obj, name)
? obj[name] : undefined;
}
/* instanciate a class without calling the constructor */
function cheapNew(cls) {
disable_constructor = true;
var rv = new cls;
disable_constructor = false;
return rv;
}
/* the base class we export */
var Class = function() {};
/* extend functionality */
Class.$extend = function(properties) {
var super_prototype = this.prototype;
/* disable constructors and instanciate prototype. Because the
prototype can't raise an exception when created, we are safe
without a try/finally here. */
var prototype = cheapNew(this);
/* copy all properties of the includes over if there are any */
prototype.__mixin_ids = _.clone(prototype.__mixin_ids || {});
if (properties.__include__)
for (var i = 0, n = properties.__include__.length; i != n; ++i) {
var mixin = properties.__include__[i];
if (mixin instanceof nova.Mixin) {
_.extend(prototype.__mixin_ids, mixin.__mixin_ids);
mixin = mixin.__mixin_properties;
}
for (var name in mixin) {
var value = getOwnProperty(mixin, name);
if (value !== undefined)
prototype[name] = mixin[name];
}
}
/* copy class vars from the superclass */
properties.__classvars__ = properties.__classvars__ || {};
if (prototype.__classvars__)
for (var key in prototype.__classvars__)
if (!properties.__classvars__[key]) {
var value = getOwnProperty(prototype.__classvars__, key);
properties.__classvars__[key] = value;
}
/* copy all properties over to the new prototype */
for (var name in properties) {
var value = getOwnProperty(properties, name);
if (name === '__include__' ||
value === undefined)
continue;
prototype[name] = typeof value === 'function' && usesSuper(value) ?
(function(meth, name) {
return function() {
var old_super = getOwnProperty(this, '$super');
this.$super = super_prototype[name];
try {
return meth.apply(this, arguments);
}
finally {
setOrUnset(this, '$super', old_super);
}
};
})(value, name) : value
}
var class_init = this.__class_init__ || function() {};
var p_class_init = prototype.__class_init__ || function() {};
delete prototype.__class_init__;
var n_class_init = function() {
class_init.apply(null, arguments);
p_class_init.apply(null, arguments);
}
n_class_init(prototype);
/* dummy constructor */
var instance = function() {
if (disable_constructor)
return;
var proper_this = context === this ? cheapNew(arguments.callee) : this;
if (proper_this.__init__)
proper_this.__init__.apply(proper_this, arguments);
proper_this.$class = instance;
return proper_this;
}
/* copy all class vars over of any */
for (var key in properties.__classvars__) {
var value = getOwnProperty(properties.__classvars__, key);
if (value !== undefined)
instance[key] = value;
}
/* copy prototype and constructor over, reattach $extend and
return the class */
instance.prototype = prototype;
instance.constructor = instance;
instance.$extend = this.$extend;
instance.$withData = this.$withData;
instance.__class_init__ = n_class_init;
return instance;
};
/* instanciate with data functionality */
Class.$withData = function(data) {
var rv = cheapNew(this);
for (var key in data) {
var value = getOwnProperty(data, key);
if (value !== undefined)
rv[key] = value;
}
return rv;
};
/* export the class */
this.Class = Class;
}).call(nova);
// end of Armin Ronacher's code
var mixinId = 1;
nova.Mixin = nova.Class.$extend({
__init__: function() {
this.__mixin_properties = {};
this.__mixin_id = mixinId;
mixinId++;
this.__mixin_ids = {};
this.__mixin_ids[this.__mixin_id] = true;
_.each(_.toArray(arguments), function(el) {
if (el instanceof nova.Mixin) {
_.extend(this.__mixin_properties, el.__mixin_properties);
_.extend(this.__mixin_ids, el.__mixin_ids);
} else { // object
_.extend(this.__mixin_properties, el)
}
}, this);
_.extend(this, this.__mixin_properties);
}
});
nova.Interface = nova.Mixin.$extend({
__init__: function() {
var lst = [];
_.each(_.toArray(arguments), function(el) {
if (el instanceof nova.Interface) {
lst.push(el);
} else if (el instanceof nova.Mixin) {
var tmp = new nova.Interface(el.__mixin_properties);
tmp.__mixin_ids = el.__mixin_ids;
lst.push(tmp);
} else { // object
var nprops = {};
_.each(el, function(v, k) {
nprops[k] = function() {
throw new nova.NotImplementedError();
};
});
lst.push(nprops);
}
});
this.$super.apply(this, lst);
}
});
nova.hasMixin = function(object, mixin) {
if (! object)
return false;
return (object.__mixin_ids || {})[mixin.__mixin_id] === true;
};
var ErrorBase = function() {
};
ErrorBase.prototype = new Error();
ErrorBase.$extend = nova.Class.$extend;
ErrorBase.$withData = nova.Class.$withData;
nova.Error = ErrorBase.$extend({
name: "nova.Error",
defaultMessage: "",
__init__: function(message) {
this.message = message || this.defaultMessage;
}
});
nova.NotImplementedError = nova.Error.$extend({
name: "nova.NotImplementedError",
defaultMessage: "This method is not implemented"
});
nova.InvalidArgumentError = nova.Error.$extend({
name: "nova.InvalidArgumentError"
});
/**
* Mixin to express the concept of destroying an object.
* When an object is destroyed, it should release any resource
* it could have reserved before.
*/
nova.Destroyable = new nova.Mixin({
__init__: function() {
this.__destroyableDestroyed = false;
},
/**
* Returns true if destroy() was called on the current object.
*/
isDestroyed : function() {
return this.__destroyableDestroyed;
},
/**
* Inform the object it should destroy itself, releasing any
* resource it could have reserved.
*/
destroy : function() {
this.__destroyableDestroyed = true;
}
});
/**
* Mixin to structure objects' life-cycles folowing a parent-children
* relationship. Each object can a have a parent and multiple children.
* When an object is destroyed, all its children are destroyed too.
*/
nova.Parented = new nova.Mixin(nova.Destroyable, {
__parentedMixin : true,
__init__: function() {
nova.Destroyable.__init__.apply(this);
this.__parentedChildren = [];
this.__parentedParent = null;
},
/**
* Set the parent of the current object. When calling this method, the
* parent will also be informed and will return the current object
* when its getChildren() method is called. If the current object did
* already have a parent, it is unregistered before, which means the
* previous parent will not return the current object anymore when its
* getChildren() method is called.
*/
setParent : function(parent) {
if (this.getParent()) {
if (this.getParent().__parentedMixin) {
this.getParent().__parentedChildren = _.without(this
.getParent().getChildren(), this);
}
}
this.__parentedParent = parent;
if (parent && parent.__parentedMixin) {
parent.__parentedChildren.push(this);
}
},
/**
* Return the current parent of the object (or null).
*/
getParent : function() {
return this.__parentedParent;
},
/**
* Return a list of the children of the current object.
*/
getChildren : function() {
return _.clone(this.__parentedChildren);
},
destroy : function() {
_.each(this.getChildren(), function(el) {
el.destroy();
});
this.setParent(undefined);
nova.Destroyable.destroy.apply(this);
}
});
/*
* Yes, we steal Backbone's events :)
*
* This class just handle the dispatching of events, it is not meant to be extended,
* nor used directly. All integration with parenting and automatic unregistration of
* events is done in the mixin EventDispatcher.
*/
// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
nova.internal.Events = nova.Class.$extend({
on : function(events, callback, context) {
var ev;
events = events.split(/\s+/);
var calls = this._callbacks || (this._callbacks = {});
while (ev = events.shift()) {
var list = calls[ev] || (calls[ev] = {});
var tail = list.tail || (list.tail = list.next = {});
tail.callback = callback;
tail.context = context;
list.tail = tail.next = {};
}
return this;
},
off : function(events, callback, context) {
var ev, calls, node;
if (!events) {
delete this._callbacks;
} else if (calls = this._callbacks) {
events = events.split(/\s+/);
while (ev = events.shift()) {
node = calls[ev];
delete calls[ev];
if (!callback || !node)
continue;
while ((node = node.next) && node.next) {
if (node.callback === callback
&& (!context || node.context === context))
continue;
this.on(ev, node.callback, node.context);
}
}
}
return this;
},
callbackList: function() {
var lst = [];
_.each(this._callbacks || {}, function(el, eventName) {
var node = el;
while ((node = node.next) && node.next) {
lst.push([eventName, node.callback, node.context]);
}
});
return lst;
},
trigger : function(events) {
var event, node, calls, tail, args, all, rest;
if (!(calls = this._callbacks))
return this;
all = calls['all'];
(events = events.split(/\s+/)).push(null);
// Save references to the current heads & tails.
while (event = events.shift()) {
if (all)
events.push({
next : all.next,
tail : all.tail,
event : event
});
if (!(node = calls[event]))
continue;
events.push({
next : node.next,
tail : node.tail
});
}
rest = Array.prototype.slice.call(arguments, 1);
while (node = events.pop()) {
tail = node.tail;
args = node.event ? [ node.event ].concat(rest) : rest;
while ((node = node.next) !== tail) {
node.callback.apply(node.context || this, args);
}
}
return this;
}
});
// end of Backbone's events class
nova.EventDispatcher = new nova.Mixin(nova.Parented, {
__eventDispatcherMixin: true,
__init__: function() {
nova.Parented.__init__.apply(this);
this.__edispatcherEvents = new nova.internal.Events();
this.__edispatcherRegisteredEvents = [];
},
on: function(events, dest, func) {
var self = this;
events = events.split(/\s+/);
_.each(events, function(eventName) {
self.__edispatcherEvents.on(eventName, func, dest);
if (dest && dest.__eventDispatcherMixin) {
dest.__edispatcherRegisteredEvents.push({name: eventName, func: func, source: self});
}
});
return this;
},
off: function(events, dest, func) {
var self = this;
events = events.split(/\s+/);
_.each(events, function(eventName) {
self.__edispatcherEvents.off(eventName, func, dest);
if (dest && dest.__eventDispatcherMixin) {
dest.__edispatcherRegisteredEvents = _.filter(dest.__edispatcherRegisteredEvents, function(el) {
return !(el.name === eventName && el.func === func && el.source === self);
});
}
});
return this;
},
trigger: function(events) {
this.__edispatcherEvents.trigger.apply(this.__edispatcherEvents, arguments);
return this;
},
destroy: function() {
var self = this;
_.each(this.__edispatcherRegisteredEvents, function(event) {
event.source.__edispatcherEvents.off(event.name, event.func, self);
});
this.__edispatcherRegisteredEvents = [];
_.each(this.__edispatcherEvents.callbackList(), function(cal) {
this.off(cal[0], cal[2], cal[1]);
}, this);
this.__edispatcherEvents.off();
nova.Parented.destroy.apply(this);
}
});
nova.Properties = new nova.Mixin(nova.EventDispatcher, {
__class_init__: function(proto) {
var props = {};
_.each(proto.__properties || {}, function(v, k) {
props[k] = _.clone(v);
});
_.each(proto, function(v, k) {
if (typeof v === "function") {
var res = /^((?:get)|(?:set))([A-Z]\w*)$/.exec(k);
if (! res)
return;
var name = res[2][0].toLowerCase() + res[2].slice(1);
var prop = props[name] || (props[name] = {});
prop[res[1]] = v;
}
});
proto.__properties = props;
},
__init__: function() {
nova.EventDispatcher.__init__.apply(this);
this.__dynamicProperties = {};
},
set: function(arg1, arg2) {
var self = this;
var map;
if (typeof arg1 === "string") {
map = {};
map[arg1] = arg2;
} else {
map = arg1;
}
var tmp_set = this.__props_setting;
this.__props_setting = false;
_.each(map, function(val, key) {
var prop = self.__properties[key];
if (prop) {
if (! prop.set)
throw new nova.InvalidArgumentError("Property " + key + " does not have a setter method.");
prop.set.call(self, val);
} else {
self.fallbackSet(key, val);
}
});
this.__props_setting = tmp_set;
if (! this.__props_setting && this.__props_setted) {
this.__props_setted = false;
self.trigger("change", self);
}
},
get: function(key) {
var prop = this.__properties[key];
if (prop) {
if (! prop.get)
throw new nova.InvalidArgumentError("Property " + key + " does not have a getter method.");
return prop.get.call(this);
} else {
return this.fallbackGet(key);
}
},
fallbackSet: function(key, val) {
throw new nova.InvalidArgumentError("Property " + key + " is not defined.");
},
fallbackGet: function(key) {
throw new nova.InvalidArgumentError("Property " + key + " is not defined.");
},
trigger: function(name) {
nova.EventDispatcher.trigger.apply(this, arguments);
if (/(\s|^)change\:.*/.exec(name)) {
if (! this.__props_setting)
this.trigger("change");
else
this.__props_setted = true;
}
}
});
nova.DynamicProperties = new nova.Mixin(nova.Properties, {
__init__: function() {
nova.Properties.__init__.apply(this);
this.__dynamicProperties = {};
},
fallbackSet: function(key, val) {
var tmp = this.__dynamicProperties[key];
if (tmp === val)
return;
this.__dynamicProperties[key] = val;
this.trigger("change:" + key, this, {
oldValue: tmp,
newValue: val
});
},
fallbackGet: function(key) {
return this.__dynamicProperties[key];
}
});
nova.Widget = nova.Class.$extend({
__include__ : [nova.DynamicProperties],
tagName: 'div',
className: '',
attributes: {},
events: {},
__init__: function(parent) {
nova.Properties.__init__.apply(this);
this.__widget_element = $(document.createElement(this.tagName));
this.$().addClass(this.className);
_.each(this.attributes, function(val, key) {
this.$().attr(key, val);
}, this);
_.each(this.events, function(val, key) {
key = key.split(" ");
val = _.bind(typeof val === "string" ? this[val] : val, this);
if (key.length > 1) {
this.$().on(key[0], key[1], val);
} else {
this.$().on(key[0], val);
}
}, this);
this.setParent(parent);
},
$: function(attr) {
if (attr)
return this.__widget_element.find.apply(this.__widget_element, arguments);
else
return this.__widget_element;
},
/**
* Destroys the current widget, also destroys all its children before destroying itself.
*/
destroy: function() {
_.each(this.getChildren(), function(el) {
el.destroy();
});
this.$().remove();
nova.Properties.destroy.apply(this);
},
/**
* Renders the current widget and appends it to the given jQuery object or Widget.
*
* @param target A jQuery object or a Widget instance.
*/
appendTo: function(target) {
this.$().appendTo(target);
return this.render();
},
/**
* Renders the current widget and prepends it to the given jQuery object or Widget.
*
* @param target A jQuery object or a Widget instance.
*/
prependTo: function(target) {
this.$().prependTo(target);
return this.render();
},
/**
* Renders the current widget and inserts it after to the given jQuery object or Widget.
*
* @param target A jQuery object or a Widget instance.
*/
insertAfter: function(target) {
this.$().insertAfter(target);
return this.render();
},
/**
* Renders the current widget and inserts it before to the given jQuery object or Widget.
*
* @param target A jQuery object or a Widget instance.
*/
insertBefore: function(target) {
this.$().insertBefore(target);
return this.render();
},
/**
* Renders the current widget and replaces the given jQuery object.
*
* @param target A jQuery object or a Widget instance.
*/
replace: function(target) {
this.$().replace(target);
return this.render();
},
/**
* This is the method to implement to render the Widget.
*/
render: function() {}
});
/*
Nova Template Engine
*/
var escape_ = function(text) {
return JSON.stringify(text);
}
var indent_ = function(txt) {
var tmp = _.map(txt.split("\n"), function(x) { return " " + x; });
tmp.pop();
tmp.push("");
return tmp.join("\n");
};
var tparams = {
def_begin: /<%\s*def\s+(?:name=(?:(?:"(.+?)")|(?:'(.+?)')))\s*>/g,
def_end: /<\/%\s*def\s*>/g,
comment_multi_begin: /<%\s*doc\s*>/g,
comment_multi_end: /<\/%\s*doc\s*>/g,
eval_long_begin: /<%/g,
eval_long_end: /%>/g,
eval_short_begin: /(?:^|\n)[[ \t]*%(?!{)/g,
eval_short_end: /\n|$/g,
escape_begin: /\${/g,
interpolate_begin: /%{/g,
comment_begin: /##/g,
comment_end: /\n|$/g
};
// /<%\s*def\s+(?:name=(?:"(.+?)"))\s*%>([\s\S]*?)<%\s*def\s*%>/g
var allbegin = new RegExp(
"((?:\\\\)*)(" +
"(" + tparams.def_begin.source + ")|" +
"(" + tparams.def_end.source + ")|" +
"(" + tparams.comment_multi_begin.source + ")|" +
"(" + tparams.eval_long_begin.source + ")|" +
"(" + tparams.interpolate_begin.source + ")|" +
"(" + tparams.eval_short_begin.source + ")|" +
"(" + tparams.escape_begin.source + ")|" +
"(" + tparams.comment_begin.source + ")" +
")"
, "g");
allbegin.global = true;
var regexes = {
slashes: 1,
match: 2,
def_begin: 3,
def_name1: 4,
def_name2: 5,
def_end: 6,
comment_multi_begin: 7,
eval_long: 8,
interpolate: 9,
eval_short: 10,
escape: 11,
comment: 12
};
var regex_count = 4;
var compileTemplate = function(text, options) {
options = _.extend({start: 0, indent: true}, options);
start = options.start;
var source = "";
var current = start;
allbegin.lastIndex = current;
var text_end = text.length;
var restart = end;
var found;
var functions = [];
var indent = options.indent ? indent_ : function (txt) { return txt; };
var rmWhite = options.removeWhitespaces ? function(txt) {
if (! txt)
return txt;
txt = _.map(txt.split("\n"), function(x) { return x.trim() });
var last = txt.pop();
txt = _.reject(txt, function(x) { return !x });
txt.push(last);
return txt.join("\n") || "\n";
} : function(x) { return x };
while (found = allbegin.exec(text)) {
var to_add = rmWhite(text.slice(current, found.index));
source += to_add ? "__p+=" + escape_(to_add) + ";\n" : '';
current = found.index;
// slash escaping handling
var slashes = found[regexes.slashes] || "";
var nbr = slashes.length;
var nslash = slashes.slice(0, Math.floor(nbr / 2));
source += nbr !== 0 ? "__p+=" + escape_(nslash) + ";\n" : "";
if (nbr % 2 !== 0) {
source += "__p+=" + escape_(found[regexes.match]) + ";\n";
current = found.index + found[0].length;
allbegin.lastIndex = current;
continue;
}
if (found[regexes.def_begin]) {
var sub_compile = compileTemplate(text, _.extend({}, options, {start: found.index + found[0].length}));
var name = (found[regexes.def_name1] || found[regexes.def_name2]);
source += "var " + name + " = function(context) {\n" + indent(sub_compile.header + sub_compile.source
+ sub_compile.footer) + "}\n";
functions.push(name);
current = sub_compile.end;
} else if (found[regexes.def_end]) {
text_end = found.index;
restart = found.index + found[0].length;
break;
} else if (found[regexes.comment_multi_begin]) {
tparams.comment_multi_end.lastIndex = found.index + found[0].length;
var end = tparams.comment_multi_end.exec(text);
if (!end)
throw new Error("<%doc> without corresponding </%doc>");
current = end.index + end[0].length;
} else if (found[regexes.eval_long]) {
tparams.eval_long_end.lastIndex = found.index + found[0].length;
var end = tparams.eval_long_end.exec(text);
if (!end)
throw new Error("<% without matching %>");
var code = text.slice(found.index + found[0].length, end.index);
code = _(code.split("\n")).chain().map(function(x) { return x.trim() })
.reject(function(x) { return !x }).value().join("\n");
source += code + "\n";
current = end.index + end[0].length;
} else if (found[regexes.interpolate]) {
var braces = /{|}/g;
braces.lastIndex = found.index + found[0].length;
var b_count = 1;
var brace;
while (brace = braces.exec(text)) {
if (brace[0] === "{")
b_count++;
else {
b_count--;
}
if (b_count === 0)
break;
}
if (b_count !== 0)
throw new Error("%{ without a matching }");
source += "__p+=" + text.slice(found.index + found[0].length, brace.index) + ";\n"
current = brace.index + brace[0].length;
} else if (found[regexes.eval_short]) {
tparams.eval_short_end.lastIndex = found.index + found[0].length;
var end = tparams.eval_short_end.exec(text);
if (!end)
throw new Error("impossible state!!");
source += text.slice(found.index + found[0].length, end.index).trim() + "\n";
current = end.index;
} else if (found[regexes.escape]) {
var braces = /{|}/g;
braces.lastIndex = found.index + found[0].length;
var b_count = 1;
var brace;
while (brace = braces.exec(text)) {
if (brace[0] === "{")
b_count++;
else {
b_count--;
}
if (b_count === 0)
break;
}
if (b_count !== 0)
throw new Error("${ without a matching }");
source += "__p+=_.escape(" + text.slice(found.index + found[0].length, brace.index) + ");\n"
current = brace.index + brace[0].length;
} else { // comment
tparams.comment_end.lastIndex = found.index + found[0].length;
var end = tparams.comment_end.exec(text);
if (!end)
throw new Error("impossible state!!");
current = end.index + end[0].length;
}
allbegin.lastIndex = current;
}
var to_add = rmWhite(text.slice(current, text_end));
source += to_add ? "__p+=" + escape_(to_add) + ";\n" : "";
var header = "var __p = ''; var print = function() { __p+=Array.prototype.join.call(arguments, '') };\n" +
"with (context || {}) {\n";
var footer = "}\nreturn __p;\n";
source = indent(source);
return {
header: header,
source: source,
footer: footer,
end: restart,
functions: functions,
};
};
nova.TemplateEngine = nova.Class.$extend({
__init__: function() {
this.resetEnvironment();
this.options = {
includeInDom: $ ? true : false,
indent: true,
removeWhitespaces: true,
};
},
loadFile: function(filename) {
var self = this;
return $.get(filename).pipe(function(content) {
return self.loadFileContent(content);
});
},
loadFileContent: function(file_content) {
var code = this.compileFile(file_content);
if (this.options.includeInDom) {
var varname = _.uniqueId("novajstemplate");
var previous = window[varname];
code = "window." + varname + " = " + code + ";";
var def = $.Deferred();
var script = document.createElement("script");
script.type = "text/javascript";
script.text = code;
$("head")[0].appendChild(script);
$(script).ready(function() {
def.resolve();
});
def.then(_.bind(function() {
var tmp = window[varname];
window[varname] = previous;
this.includeTemplates(tmp);
}, this));
return def;
} else {
console.log("return (" + code + ")(context);");
return this.includeTemplates(new Function('context', "return (" + code + ")(context);"));
}
},
compileFile: function(file_content) {
var result = compileTemplate(file_content, _.extend({}, this.options));
var to_append = "";
_.each(result.functions, function(name) {
to_append += name + ": " + name + ",\n";
}, this);
to_append = this.options.indent ? indent_(to_append) : to_append;
to_append = "return {\n" + to_append + "};\n";
to_append = this.options.indent ? indent_(to_append) : to_append;
var code = "function(context) {\n" + result.header +
result.source + to_append + result.footer + "}\n";
return code;
},
includeTemplates: function(fct) {
var add = _.extend({engine: this}, this._env);
var functions = fct(add);
_.each(functions, function(func, name) {
if (this[name])
throw new Error("The template '" + name + "' is already defined");
this[name] = func;
}, this);
},
buildTemplate: function(text) {
var comp = compileTemplate(text, _.extend({}, this.options));
var result = comp.header + comp.source + comp.footer;
var add = _.extend({engine: this}, this._env);
var func = new Function('context', result);
return function(data) {
return func.call(this, _.extend(add, data));
};
},
eval: function(text, context) {
return this.buildTemplate(text)(context);
},
resetEnvironment: function(nenv) {
this._env = {_: _};
this.extendEnvironment(nenv);
},
extendEnvironment: function(env) {
_.extend(this._env, env || {});
},
});
return nova;
};
})();

View File

@ -1,362 +0,0 @@
/*
Copyright (c) 2013, OpenERP
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
define(["underscore", "jquery", "nova"], function(_, $, nova) {
var oeclient = {};
var genericJsonRPC = function(fct_name, params, fct) {
var data = {
jsonrpc: "2.0",
method: fct_name,
params: params,
id: Math.floor(Math.random()* (1000*1000*1000)),
};
return fct(data).pipe(function(result) {
if (result.error !== undefined) {
console.error("Server application error", result.error);
return $.Deferred().reject("server", result.error);
} else {
return result.result;
}
}, function() {
console.error("JsonRPC communication error", _.toArray(arguments));
var def = $.Deferred();
return def.reject.apply(def, ["communication"].concat(_.toArray(arguments)));
});
};
oeclient.jsonRpc = function(url, fct_name, params, settings) {
return genericJsonRPC(fct_name, params, function(data) {
return $.ajax(url, _.extend({}, settings, {
url: url,
dataType: 'json',
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json',
}));
});
};
oeclient.jsonpRpc = function(url, fct_name, params, settings) {
return genericJsonRPC(fct_name, params, function(data) {
return $.ajax(url, _.extend({}, settings, {
url: url,
dataType: 'jsonp',
jsonp: 'jsonp',
type: 'GET',
cache: false,
data: {r: JSON.stringify(data)},
}));
});
};
oeclient.Connector = nova.Class.$extend({
getService: function(serviceName) {
return new oeclient.Service(this, serviceName);
},
});
oeclient.JsonRPCConnector = oeclient.Connector.$extend({
__init__: function(url) {
this.url = url;
},
call: function(sub_url, content) {
return oeclient.jsonRpc(this.url + sub_url, "call", content);
},
send: function(serviceName, method, args) {
return this.call("/jsonrpc", {"service": serviceName, "method": method, "args": args});
},
});
oeclient.JsonpRPCConnector = oeclient.JsonRPCConnector.$extend({
call: function(sub_url, content) {
return oeclient.jsonpRpc(this.url + sub_url, "call", content);
},
});
oeclient.Service = nova.Class.$extend({
__init__: function(connector, serviceName) {
this.connector = connector;
this.serviceName = serviceName;
},
call: function(method, args) {
return this.connector.send(this.serviceName, method, args);
},
});
oeclient.AuthenticationError = nova.Error.$extend({
name: "oeclient.AuthenticationError",
defaultMessage: "An error occured during authentication."
});
oeclient.Connection = nova.Class.$extend({
__init__: function(connector, database, login, password, userId) {
this.connector = connector;
this.setLoginInfo(database, login, password, userId);
this.userContext = null;
},
setLoginInfo: function(database, login, password, userId) {
this.database = database;
this.login = login;
this.password = password;
this.userId = userId;
},
checkLogin: function(force) {
force = force === undefined ? true: force;
if (this.userId && ! force)
return $.when();
if (! this.database || ! this.login || ! this.password)
throw new oeclient.AuthenticationError();
return this.getService("common").call("login", [this.database, this.login, this.password])
.then(_.bind(function(result) {
this.userId = result;
if (! this.userId) {
console.error("Authentication failure");
return $.Deferred().reject({message:"Authentication failure"});
}
}, this));
},
getUserContext: function() {
if (! this.userContext) {
return this.getModel("res.users").call("context_get").then(_.bind(function(result) {
this.userContext = result;
return this.userContext;
}, this));
}
return $.when(this.userContext);
},
getModel: function(modelName) {
return new oeclient.Model(this, modelName);
},
getService: function(serviceName) {
return this.connector.getService(serviceName);
},
});
oeclient.Model = nova.Class.$extend({
__init__: function(connection, modelName) {
this.connection = connection;
this.modelName = modelName;
},
call: function(method, args, kw) {
return this.connection.checkLogin().then(_.bind(function() {
return this.connection.getService("object").call("execute_kw", [
this.connection.database,
this.connection.userId,
this.connection.password,
this.modelName,
method,
args || [],
kw || {},
]);
}, this));
},
search_read: function(domain, fields, offset, limit, order, context) {
return this.call("search", [domain || [], offset || 0, limit || false, order || false, context || {}]).then(_.bind(function(record_ids) {
if (! record_ids) {
return [];
}
return this.call("read", [record_ids, fields || [], context || {}]).then(function(records) {
var index = {};
_.each(records, function(r) {
index[r.id] = r;
});
var res = [];
_.each(record_ids, function(id) {
if (index[id])
res.push(index[id]);
});
return res;
});
}, this));
},
});
/**
* Converts a string to a Date javascript object using OpenERP's
* datetime string format (exemple: '2011-12-01 15:12:35').
*
* The time zone is assumed to be UTC (standard for OpenERP 6.1)
* and will be converted to the browser's time zone.
*
* @param {String} str A string representing a datetime.
* @returns {Date}
*/
oeclient.str_to_datetime = function(str) {
if(!str) {
return str;
}
var regex = /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d(?:\.\d+)?)$/;
var res = regex.exec(str);
if ( !res ) {
throw new Error("'" + str + "' is not a valid datetime");
}
var tmp = new Date();
tmp.setUTCFullYear(parseFloat(res[1]));
tmp.setUTCMonth(parseFloat(res[2]) - 1);
tmp.setUTCDate(parseFloat(res[3]));
tmp.setUTCHours(parseFloat(res[4]));
tmp.setUTCMinutes(parseFloat(res[5]));
tmp.setUTCSeconds(parseFloat(res[6]));
return tmp;
};
/**
* Converts a string to a Date javascript object using OpenERP's
* date string format (exemple: '2011-12-01').
*
* As a date is not subject to time zones, we assume it should be
* represented as a Date javascript object at 00:00:00 in the
* time zone of the browser.
*
* @param {String} str A string representing a date.
* @returns {Date}
*/
oeclient.str_to_date = function(str) {
if(!str) {
return str;
}
var regex = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
var res = regex.exec(str);
if ( !res ) {
throw new Error("'" + str + "' is not a valid date");
}
var tmp = new Date();
tmp.setFullYear(parseFloat(res[1]));
tmp.setMonth(parseFloat(res[2]) - 1);
tmp.setDate(parseFloat(res[3]));
tmp.setHours(0);
tmp.setMinutes(0);
tmp.setSeconds(0);
return tmp;
};
/**
* Converts a string to a Date javascript object using OpenERP's
* time string format (exemple: '15:12:35').
*
* The OpenERP times are supposed to always be naive times. We assume it is
* represented using a javascript Date with a date 1 of January 1970 and a
* time corresponding to the meant time in the browser's time zone.
*
* @param {String} str A string representing a time.
* @returns {Date}
*/
oeclient.str_to_time = function(str) {
if(!str) {
return str;
}
var regex = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)$/;
var res = regex.exec(str);
if ( !res ) {
throw new Error("'" + str + "' is not a valid time");
}
debugger;
var tmp = new Date();
tmp.setFullYear(1970);
tmp.setMonth(0);
tmp.setDate(1);
tmp.setHours(parseFloat(res[1]));
tmp.setMinutes(parseFloat(res[2]));
tmp.setSeconds(parseFloat(res[3]));
return tmp;
};
/*
* Left-pad provided arg 1 with zeroes until reaching size provided by second
* argument.
*
* @param {Number|String} str value to pad
* @param {Number} size size to reach on the final padded value
* @returns {String} padded string
*/
var zpad = function(str, size) {
str = "" + str;
return new Array(size - str.length + 1).join('0') + str;
};
/**
* Converts a Date javascript object to a string using OpenERP's
* datetime string format (exemple: '2011-12-01 15:12:35').
*
* The time zone of the Date object is assumed to be the one of the
* browser and it will be converted to UTC (standard for OpenERP 6.1).
*
* @param {Date} obj
* @returns {String} A string representing a datetime.
*/
oeclient.datetime_to_str = function(obj) {
if (!obj) {
return false;
}
return zpad(obj.getUTCFullYear(),4) + "-" + zpad(obj.getUTCMonth() + 1,2) + "-"
+ zpad(obj.getUTCDate(),2) + " " + zpad(obj.getUTCHours(),2) + ":"
+ zpad(obj.getUTCMinutes(),2) + ":" + zpad(obj.getUTCSeconds(),2);
};
/**
* Converts a Date javascript object to a string using OpenERP's
* date string format (exemple: '2011-12-01').
*
* As a date is not subject to time zones, we assume it should be
* represented as a Date javascript object at 00:00:00 in the
* time zone of the browser.
*
* @param {Date} obj
* @returns {String} A string representing a date.
*/
oeclient.date_to_str = function(obj) {
if (!obj) {
return false;
}
return zpad(obj.getFullYear(),4) + "-" + zpad(obj.getMonth() + 1,2) + "-"
+ zpad(obj.getDate(),2);
};
/**
* Converts a Date javascript object to a string using OpenERP's
* time string format (exemple: '15:12:35').
*
* The OpenERP times are supposed to always be naive times. We assume it is
* represented using a javascript Date with a date 1 of January 1970 and a
* time corresponding to the meant time in the browser's time zone.
*
* @param {Date} obj
* @returns {String} A string representing a time.
*/
oeclient.time_to_str = function(obj) {
if (!obj) {
return false;
}
return zpad(obj.getHours(),2) + ":" + zpad(obj.getMinutes(),2) + ":"
+ zpad(obj.getSeconds(),2);
};
return oeclient;
});

View File

@ -1,12 +0,0 @@
import sys
import json
file_name = sys.argv[1]
function_name = sys.argv[2]
with open(file_name) as file_:
content = file_.read()
print "window.%s(%s);" % (function_name, json.dumps(content))

View File

@ -1,6 +1,6 @@
/**
* achtung 0.3.0
*
* achtung %%VERSION%%
*
* Growl-like notifications for jQuery
*
* Copyright (c) 2009 Josh Varner <josh@voxwerk.com>
@ -11,10 +11,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -29,43 +29,138 @@
* @author Josh Varner <josh@voxwerk.com>
*/
#achtung-overlay {
overflow: hidden;
position: fixed;
top: 0;
right: 0;
z-index: 50;
}
/* IE 6 doesn't support position: fixed */
* html #achtung-overlay {
position:absolute;
position: absolute;
}
/* IE6 includes padding in width */
* html .achtung {
width: 280px;
width: 260px;
}
#achtung-overlay {
#achtung-wrapper {
overflow: hidden;
position: fixed;
top: 15px;
right: 15px;
width: 280px;
z-index:50;
padding: 25px 30px 10px 10px;
}
.achtung {
display:none;
display: none;
float: right;
clear: right;
margin-bottom: 8px;
padding: 15px 15px;
background-color: #000;
color: white;
width: 250px;
font-weight: bold;
position:relative;
overflow: hidden;
-moz-box-shadow: #aaa 1px 1px 2px;
-webkit-box-shadow: #aaa 1px 1px 2px;
box-shadow: #aaa 1px 1px 2px;
-moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px;
padding: 15px;
background: #000;
background: rgba(0,0,0,.95);
color: white;
width: 230px;
font-weight: normal;
font-style: italic;
font-size: 1.05em;
position: relative;
overflow: hidden;
text-shadow: -1px -1px 0 rgba(0,0,0,.3);
box-shadow: rgba(0,0,0,.3) 0 1px 4px;
-moz-box-shadow: rgba(0,0,0,.3) 0 1px 4px;
-webkit-box-shadow: rgba(0,0,0,.3) 0 1px 4px;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
opacity: 1.0;
filter:Alpha(Opacity=100);
}
.achtung-default {
background: #000;
background: -moz-linear-gradient(top, rgba(150,150,150,.9), rgba(120,120,120,.9) 70%);
background: -webkit-gradient(linear, left top, left bottom,
from(rgba(150,150,150,.9)),
color-stop(70%, rgba(120,120,120,.9)),
to(rgba(120,120,120,.9))
) no-repeat;
color: white;
}
.achtung .achtung-message-icon {
float: left;
margin: 0 .8em 0 -.5em;
zoom: 1;
}
.achtung .ui-icon.achtung-close-button {
overflow: hidden;
float: right;
position: relative;
top: -8px;
right: -8px;
cursor: pointer;
background-image: url('images/ui-icons_cccccc_256x240.png');
}
.achtung .ui-icon.achtung-close-button:hover {
background-image: url('images/ui-icons_ffffff_256x240.png');
}
/* Slightly darker for these colors (readability) */
.achtungSuccess, .achtungFail, .achtungWait {
/* Note that if using show/hide animations, IE will lose
this setting */
opacity: .85;
filter:Alpha(Opacity=85);
opacity: 1.0;
filter:Alpha(Opacity=100);
}
.achtungSuccess {
background: #6a5;
background: #6a5 -moz-linear-gradient(top, #8c7, #6a5 70%);
background: #6a5 -webkit-gradient(linear, left top, left bottom,
from(#8c7),
color-stop(70%, #6a5),
to(#6a5)
) no-repeat;
}
.achtungFail {
background: #a55;
background: #a55 -moz-linear-gradient(top, #c66, #a44 70%);
background: #789 -webkit-gradient(linear, left top, left bottom,
from(#c66),
color-stop(70%, #a44),
to(#a44)
) no-repeat;
}
.achtungWait {
background: #789;
background: #789 -moz-linear-gradient(top, #89a, #678 70%);
background: #789 -webkit-gradient(linear, left top, left bottom,
from(#89a),
color-stop(70%, #678),
to(#678)
) no-repeat;
}
.achtungSuccess .ui-icon.achtung-close-button,
.achtungFail .ui-icon.achtung-close-button {
background-image: url('images/ui-icons_444444_256x240.png');
}
.achtungSuccess .ui-icon.achtung-close-button:hover,
.achtungFail .ui-icon.achtung-close-button:hover {
background-image: url('images/ui-icons_ffffff_256x240.png');
}
.achtung .wait-icon {
background-image: url('images/wait.gif');
}
.achtung .achtung-message {
display: inline;
}
/**
@ -74,8 +169,8 @@
* Can (and should) be removed if you are already loading the jQuery UI CSS
* to reduce payload size.
*/
.ui-icon { display: block; overflow: hidden; background-repeat: no-repeat; }
.ui-icon { width: 16px; height: 16px; }
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
.ui-icon { width: 16px; height: 16px; background-image: url('images/ui-icons_222222_256x240.png'); }
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
@ -249,58 +344,3 @@
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
.achtung .achtung-message-icon {
margin-top: 0px;
margin-left: -.5em;
margin-right: .5em;
float: left;
zoom: 1;
}
.achtung .ui-icon.achtung-close-button {
float: right;
margin-right: -8px;
margin-top: -12px;
cursor: pointer;
color: white;
text-align: right;
}
.achtung .ui-icon.achtung-close-button:after {
content: "x"
}
/* Slightly darker for these colors (readability) */
.achtungSuccess, .achtungFail, .achtungWait {
/* Note that if using show/hide animations, IE will lose
this setting */
opacity: .93; filter:Alpha(Opacity=93);
}
.achtungSuccess {
background-color: #4DB559;
}
.achtungFail {
background-color: #D64450;
}
.achtungWait {
background-color: #658093;
}
.achtungSuccess .ui-icon.achtung-close-button,
.achtungFail .ui-icon.achtung-close-button {
}
.achtungSuccess .ui-icon.achtung-close-button-hover,
.achtungFail .ui-icon.achtung-close-button-hover {
}
.achtung .wait-icon {
}
.achtung .achtung-message {
display: inline;
}

View File

@ -0,0 +1,282 @@
/**
* achtung %%VERSION%%
*
* Growl-like notifications for jQuery
*
* Copyright (c) 2009 Josh Varner <josh@voxwerk.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @license http://www.opensource.org/licenses/mit-license.php
* @author Josh Varner <josh@voxwerk.com>
*/
/*jslint browser:true, white:false, onevar:false, nomen:false, bitwise:false, plusplus:false, immed: false */
/*globals window, jQuery */
(function ($) {
var widgetName = 'achtung';
/**
* This is based on the jQuery UI $.widget code. I would have just made this
* a $.widget but I didn't want the jQuery UI dependency.
*/
$.fn.achtung = function (options) {
var isMethodCall = (typeof options === 'string'),
args = Array.prototype.slice.call(arguments, isMethodCall ? 1 : 0);
// handle initialization and non-getter methods
return this.each(function () {
// prevent calls to internal methods
if (isMethodCall && options.substring(0, 1) === '_') {
return;
}
var instance = $.data(this, widgetName);
// constructor
if (!instance && !isMethodCall) {
$.data(this, widgetName, new $.achtung(this))._init(args);
}
if (!!instance && isMethodCall && $.isFunction(instance[options])) {
instance[options].apply(instance, args);
}
});
};
$.achtung = function (element) {
if (!element || !element.nodeType) {
var el = $('<div>');
return el.achtung.apply(el, arguments);
}
this.container = $(element);
};
/**
* Static members
**/
$.extend($.achtung, {
version: '%%VERSION%%',
overlay: false,
wrapper: false,
defaults: {
timeout: 10,
disableClose: false,
icon: false,
className: 'achtung-default',
crossFadeMessage: 500, // 0 to disable
animateClassSwitch: 0, // 0 to disable (doesn't work with gradient backgrounds)
showEffects: {'opacity':'toggle'}, // ,'height':'toggle'},
hideEffects: {'opacity':'toggle'}, // ,'height':'toggle'},
showEffectDuration: 300,
hideEffectDuration: 500
}
});
/**
* Non-static members
**/
$.extend($.achtung.prototype, {
container: false,
icon: false,
message: false,
closeTimer: false,
options: {},
_init: function (args) {
var o, self = this;
o = this.options = $.extend.apply($, [{}, $.achtung.defaults].concat(args));
if ((o.animateClassSwitch > 0) && !('switchClass' in $.fn)) {
o.animateClassSwitch = this.options.animateClassSwitch = 0;
}
if (!o.disableClose) {
$('<span class="achtung-close-button ui-icon ui-icon-close" />')
.prependTo(this.container)
.bind({
click: function () { self.close(); }
});
}
this.changeIcon(o.icon, true);
if (o.message) {
this.message = $('<span>', {
'class': 'achtung-message',
html: o.message
}).appendTo(this.container);
}
if ('className' in o) {
this.container.addClass(o.className);
}
if ('css' in o) {
this.container.css(o.css);
}
if (!$.achtung.overlay) {
$.achtung.overlay = $('<div id="achtung-overlay"><div id="achtung-wrapper"></div></div>');
$.achtung.overlay.appendTo(document.body);
$.achtung.wrapper = $('#achtung-wrapper');
}
this.container.addClass('achtung').hide().appendTo($.achtung.wrapper);
if (o.showEffects) {
this.container.animate(o.showEffects, o.showEffectDuration);
} else {
this.container.show();
}
this.timeout(o.timeout);
},
timeout: function (timeout) {
var self = this;
if (this.closeTimer) {
clearTimeout(this.closeTimer);
}
if (timeout > 0) {
this.closeTimer = setTimeout(function () { self.close(); }, timeout * 1000);
this.options.timeout = timeout;
} else if (timeout < 0) {
this.close();
}
},
/**
* Change the CSS class associated with this message.
*
* @param newClass string Name of new class to associate
*/
changeClass: function (newClass) {
var oldClass = '' + this.options.className,
self = this;
if (oldClass === newClass) {
return;
}
this.container.queue(function (next) {
if (self.options.animateClassSwitch > 0) {
$(this).switchClass(oldClass, newClass, self.options.animateClassSwitch);
} else {
$(this).removeClass(oldClass).addClass(newClass);
}
next();
});
this.options.className = newClass;
},
changeIcon: function (newIcon, force) {
if (!force && this.options.icon === newIcon) {
return;
}
if (!!this.icon) {
if (newIcon) {
this.icon.removeClass(this.options.icon).addClass(newIcon);
} else {
this.icon.remove();
this.icon = false;
}
} else if (newIcon) {
this.icon = $('<span class="achtung-message-icon ui-icon ' + newIcon + '" />');
this.container.prepend(this.icon);
}
this.options.icon = newIcon;
},
changeMessage: function (newMessage) {
if (this.options.crossFadeMessage > 0) {
this.message.clone()
.css('position', 'absolute')
.insertBefore(this.message)
.fadeOut(this.options.crossFadeMessage, function () { $(this).remove(); });
this.message.hide().html(newMessage).fadeIn(this.options.crossFadeMessage);
} else {
this.message.html(newMessage);
}
this.options.message = newMessage;
},
update: function () {
var options = $.extend.apply($, [{}].concat(Array.prototype.slice.call(arguments, 0))),
map = {
className: 'changeClass',
css: 'css',
icon: 'changeIcon',
message: 'changeMessage',
timeout: 'timeout'
};
for (var prop in map) {
if (prop in options) {
this[map[prop]](options[prop]);
}
}
},
isVisible: function () {
return (true === this.container.is(':visible'));
},
_trigger: function (type, data) {
this.container.trigger(widgetName + type, data);
},
close: function () {
var o = this.options, self = this;
this._trigger('close');
if (o.hideEffects) {
this.container.animate(o.hideEffects, o.hideEffectDuration, function () {
self.remove();
});
} else {
this.container.hide();
this.remove();
}
},
remove: function () {
this.container.remove();
if ($.achtung.wrapper && !($.achtung.wrapper.contents().length)) {
$.achtung.wrapper = false;
$.achtung.overlay.remove();
$.achtung.overlay = false;
}
}
});
})(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,736 @@
/*
Copyright (c) 2013, Fabien Meghazi
Released under the MIT license
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// TODO: trim support
// TODO: line number -> https://bugzilla.mozilla.org/show_bug.cgi?id=618650
// TODO: templates orverwritten could be called by t-call="__super__" ?
// TODO: t-set + t-value + children node == scoped variable ?
(function() {
var QWeb2 = {
expressions_cache: {},
RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,this,typeof,eval,void,Math,RegExp,Array,Object,Date'.split(','),
ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,escf,raw,rawf,js,debug,log'.split(','),
WORD_REPLACEMENT: {
'and': '&&',
'or': '||',
'gt': '>',
'gte': '>=',
'lt': '<',
'lte': '<='
},
tools: {
exception: function(message, context) {
context = context || {};
var prefix = 'QWeb2';
if (context.template) {
prefix += " - template['" + context.template + "']";
}
throw new Error(prefix + ": " + message);
},
warning : function(message) {
if (typeof(window) !== 'undefined' && window.console) {
window.console.warn(message);
}
},
trim: function(s, mode) {
switch (mode) {
case "left":
return s.replace(/^\s*/, "");
case "right":
return s.replace(/\s*$/, "");
default:
return s.replace(/^\s*|\s*$/g, "");
}
},
js_escape: function(s, noquotes) {
return (noquotes ? '' : "'") + s.replace(/\r?\n/g, "\\n").replace(/'/g, "\\'") + (noquotes ? '' : "'");
},
html_escape: function(s, attribute) {
if (s == null) {
return '';
}
s = String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
if (attribute) {
s = s.replace(/"/g, '&quot;');
}
return s;
},
gen_attribute: function(o) {
if (o !== null && o !== undefined) {
if (o.constructor === Array) {
if (o[1] !== null && o[1] !== undefined) {
return this.format_attribute(o[0], o[1]);
}
} else if (typeof o === 'object') {
var r = '';
for (var k in o) {
if (o.hasOwnProperty(k)) {
r += this.gen_attribute([k, o[k]]);
}
}
return r;
}
}
return '';
},
format_attribute: function(name, value) {
return ' ' + name + '="' + this.html_escape(value, true) + '"';
},
extend: function(dst, src, exclude) {
for (var p in src) {
if (src.hasOwnProperty(p) && !(exclude && this.arrayIndexOf(exclude, p) !== -1)) {
dst[p] = src[p];
}
}
return dst;
},
arrayIndexOf : function(array, item) {
for (var i = 0, ilen = array.length; i < ilen; i++) {
if (array[i] === item) {
return i;
}
}
return -1;
},
xml_node_to_string : function(node, childs_only) {
if (childs_only) {
var childs = node.childNodes, r = [];
for (var i = 0, ilen = childs.length; i < ilen; i++) {
r.push(this.xml_node_to_string(childs[i]));
}
return r.join('');
} else {
if (typeof XMLSerializer !== 'undefined') {
return (new XMLSerializer()).serializeToString(node);
} else {
switch(node.nodeType) {
case 1: return node.outerHTML;
case 3: return node.data;
case 4: return '<![CDATA[' + node.data + ']]>';
case 8: return '<!-- ' + node.data + '-->';
}
throw new Error('Unknown node type ' + node.nodeType);
}
}
},
call: function(context, template, old_dict, _import, callback) {
var new_dict = this.extend({}, old_dict);
new_dict['__caller__'] = old_dict['__template__'];
if (callback) {
new_dict['__content__'] = callback(context, new_dict);
}
var r = context.engine._render(template, new_dict);
if (_import) {
if (_import === '*') {
this.extend(old_dict, new_dict, ['__caller__', '__template__']);
} else {
_import = _import.split(',');
for (var i = 0, ilen = _import.length; i < ilen; i++) {
var v = _import[i];
old_dict[v] = new_dict[v];
}
}
}
return r;
},
foreach: function(context, enu, as, old_dict, callback) {
if (enu != null) {
var size, new_dict = this.extend({}, old_dict);
new_dict[as + "_all"] = enu;
var as_value = as + "_value",
as_index = as + "_index",
as_first = as + "_first",
as_last = as + "_last",
as_parity = as + "_parity";
if (size = enu.length) {
new_dict[as + "_size"] = size;
for (var j = 0, jlen = enu.length; j < jlen; j++) {
var cur = enu[j];
new_dict[as_value] = cur;
new_dict[as_index] = j;
new_dict[as_first] = j === 0;
new_dict[as_last] = j + 1 === size;
new_dict[as_parity] = (j % 2 == 1 ? 'odd' : 'even');
if (cur.constructor === Object) {
this.extend(new_dict, cur);
}
new_dict[as] = cur;
callback(context, new_dict);
}
} else if (enu.constructor == Number) {
var _enu = [];
for (var i = 0; i < enu; i++) {
_enu.push(i);
}
this.foreach(context, _enu, as, old_dict, callback);
} else {
var index = 0;
for (var k in enu) {
if (enu.hasOwnProperty(k)) {
var v = enu[k];
new_dict[as_value] = v;
new_dict[as_index] = index;
new_dict[as_first] = index === 0;
new_dict[as_parity] = (j % 2 == 1 ? 'odd' : 'even');
new_dict[as] = k;
callback(context, new_dict);
index += 1;
}
}
}
} else {
this.exception("No enumerator given to foreach", context);
}
}
}
};
QWeb2.Engine = (function() {
function Engine() {
// TODO: handle prefix at template level : t-prefix="x", don't forget to lowercase it
this.prefix = 't';
this.debug = false;
this.templates_resources = []; // TODO: implement this.reload()
this.templates = {};
this.compiled_templates = {};
this.extend_templates = {};
this.default_dict = {};
this.tools = QWeb2.tools;
this.jQuery = window.jQuery;
this.reserved_words = QWeb2.RESERVED_WORDS.slice(0);
this.actions_precedence = QWeb2.ACTIONS_PRECEDENCE.slice(0);
this.word_replacement = QWeb2.tools.extend({}, QWeb2.WORD_REPLACEMENT);
this.preprocess_node = null;
for (var i = 0; i < arguments.length; i++) {
this.add_template(arguments[i]);
}
}
QWeb2.tools.extend(Engine.prototype, {
add_template : function(template) {
this.templates_resources.push(template);
if (template.constructor === String) {
template = this.load_xml(template);
}
var ec = (template.documentElement && template.documentElement.childNodes) || template.childNodes || [];
for (var i = 0; i < ec.length; i++) {
var node = ec[i];
if (node.nodeType === 1) {
if (node.nodeName == 'parsererror') {
return this.tools.exception(node.innerText);
}
var name = node.getAttribute(this.prefix + '-name');
var extend = node.getAttribute(this.prefix + '-extend');
if (name && extend) {
// Clone template and extend it
if (!this.templates[extend]) {
return this.tools.exception("Can't clone undefined template " + extend);
}
this.templates[name] = this.templates[extend].cloneNode(true);
extend = name;
name = undefined;
}
if (name) {
this.templates[name] = node;
this.compiled_templates[name] = null;
} else if (extend) {
delete(this.compiled_templates[extend]);
if (this.extend_templates[extend]) {
this.extend_templates[extend].push(node);
} else {
this.extend_templates[extend] = [node];
}
}
}
}
return true;
},
load_xml : function(s) {
s = this.tools.trim(s);
if (s.charAt(0) === '<') {
return this.load_xml_string(s);
} else {
var req = this.get_xhr();
if (req) {
// TODO: third parameter is async : https://developer.mozilla.org/en/XMLHttpRequest#open()
// do an on_ready in QWeb2{} that could be passed to add_template
if (this.debug) {
s += '?debug=' + (new Date()).getTime(); // TODO fme: do it properly in case there's already url parameters
}
req.open('GET', s, false);
req.send(null);
var xDoc = req.responseXML;
if (xDoc) {
if (!xDoc.documentElement) {
throw new Error("QWeb2: This xml document has no root document : " + xDoc.responseText);
}
if (xDoc.documentElement.nodeName == "parsererror") {
return this.tools.exception(xDoc.documentElement.childNodes[0].nodeValue);
}
return xDoc;
} else {
return this.load_xml_string(req.responseText);
}
}
}
},
load_xml_string : function(s) {
if (window.DOMParser) {
var dp = new DOMParser();
var r = dp.parseFromString(s, "text/xml");
if (r.body && r.body.firstChild && r.body.firstChild.nodeName == 'parsererror') {
return this.tools.exception(r.body.innerText);
}
return r;
}
var xDoc;
try {
// new ActiveXObject("Msxml2.DOMDocument.4.0");
xDoc = new ActiveXObject("MSXML2.DOMDocument");
} catch (e) {
return this.tools.exception(
"Could not find a DOM Parser: " + e.message);
}
xDoc.async = false;
xDoc.preserveWhiteSpace = true;
xDoc.loadXML(s);
return xDoc;
},
has_template : function(template) {
return !!this.templates[template];
},
get_xhr : function() {
if (window.XMLHttpRequest) {
return new window.XMLHttpRequest();
}
try {
return new ActiveXObject('MSXML2.XMLHTTP.3.0');
} catch (e) {
return null;
}
},
compile : function(node) {
var e = new QWeb2.Element(this, node);
var template = node.getAttribute(this.prefix + '-name');
return " /* 'this' refers to Qweb2.Engine instance */\n" +
" var context = { engine : this, template : " + (this.tools.js_escape(template)) + " };\n" +
" dict = dict || {};\n" +
" dict['__template__'] = '" + template + "';\n" +
" var r = [];\n" +
" /* START TEMPLATE */" +
(this.debug ? "" : " try {\n") +
(e.compile()) + "\n" +
" /* END OF TEMPLATE */" +
(this.debug ? "" : " } catch(error) {\n" +
" if (console && console.exception) console.exception(error);\n" +
" context.engine.tools.exception('Runtime Error: ' + error, context);\n") +
(this.debug ? "" : " }\n") +
" return r.join('');";
},
render : function(template, dict) {
dict = dict || {};
QWeb2.tools.extend(dict, this.default_dict);
/*if (this.debug && window['console'] !== undefined) {
console.time("QWeb render template " + template);
}*/
var r = this._render(template, dict);
/*if (this.debug && window['console'] !== undefined) {
console.timeEnd("QWeb render template " + template);
}*/
return r;
},
_render : function(template, dict) {
if (this.compiled_templates[template]) {
return this.compiled_templates[template].apply(this, [dict || {}]);
} else if (this.templates[template]) {
var ext;
if (ext = this.extend_templates[template]) {
var extend_node;
while (extend_node = ext.shift()) {
this.extend(template, extend_node);
}
}
var code = this.compile(this.templates[template]), tcompiled;
try {
tcompiled = new Function(['dict'], code);
} catch (error) {
if (this.debug && window.console) {
console.log(code);
}
this.tools.exception("Error evaluating template: " + error, { template: name });
}
if (!tcompiled) {
this.tools.exception("Error evaluating template: (IE?)" + error, { template: name });
}
this.compiled_templates[template] = tcompiled;
return this.render(template, dict);
} else {
return this.tools.exception("Template '" + template + "' not found");
}
},
extend : function(template, extend_node) {
if (!this.jQuery) {
return this.tools.exception("Can't extend template " + template + " without jQuery");
}
var template_dest = this.templates[template];
for (var i = 0, ilen = extend_node.childNodes.length; i < ilen; i++) {
var child = extend_node.childNodes[i];
if (child.nodeType === 1) {
var jquery = child.getAttribute(this.prefix + '-jquery'),
operation = child.getAttribute(this.prefix + '-operation'),
target,
error_msg = "Error while extending template '" + template;
if (jquery) {
target = this.jQuery(jquery, template_dest);
} else {
this.tools.exception(error_msg + "No expression given");
}
error_msg += "' (expression='" + jquery + "') : ";
if (operation) {
var allowed_operations = "append,prepend,before,after,replace,inner".split(',');
if (this.tools.arrayIndexOf(allowed_operations, operation) == -1) {
this.tools.exception(error_msg + "Invalid operation : '" + operation + "'");
}
operation = {'replace' : 'replaceWith', 'inner' : 'html'}[operation] || operation;
target[operation](child.cloneNode(true).childNodes);
} else {
try {
var f = new Function(['$', 'document'], this.tools.xml_node_to_string(child, true));
} catch(error) {
return this.tools.exception("Parse " + error_msg + error);
}
try {
f.apply(target, [this.jQuery, template_dest.ownerDocument]);
} catch(error) {
return this.tools.exception("Runtime " + error_msg + error);
}
}
}
}
}
});
return Engine;
})();
QWeb2.Element = (function() {
function Element(engine, node) {
this.engine = engine;
this.node = node;
this.tag = node.tagName;
this.actions = {};
this.actions_done = [];
this.attributes = {};
this.children = [];
this._top = [];
this._bottom = [];
this._indent = 1;
this.process_children = true;
var childs = this.node.childNodes;
if (childs) {
for (var i = 0, ilen = childs.length; i < ilen; i++) {
this.children.push(new QWeb2.Element(this.engine, childs[i]));
}
}
var attrs = this.node.attributes;
if (attrs) {
for (var j = 0, jlen = attrs.length; j < jlen; j++) {
var attr = attrs[j];
var name = attr.name;
var m = name.match(new RegExp("^" + this.engine.prefix + "-(.+)"));
if (m) {
name = m[1];
if (name === 'name') {
continue;
}
this.actions[name] = attr.value;
} else {
this.attributes[name] = attr.value;
}
}
}
if (this.engine.preprocess_node) {
this.engine.preprocess_node.call(this);
}
}
QWeb2.tools.extend(Element.prototype, {
compile : function() {
var r = [],
instring = false,
lines = this._compile().split('\n');
for (var i = 0, ilen = lines.length; i < ilen; i++) {
var m, line = lines[i];
if (m = line.match(/^(\s*)\/\/@string=(.*)/)) {
if (instring) {
if (this.engine.debug) {
// Split string lines in indented r.push arguments
r.push((m[2].indexOf("\\n") != -1 ? "',\n\t" + m[1] + "'" : '') + m[2]);
} else {
r.push(m[2]);
}
} else {
r.push(m[1] + "r.push('" + m[2]);
instring = true;
}
} else {
if (instring) {
r.push("');\n");
}
instring = false;
r.push(line + '\n');
}
}
return r.join('');
},
_compile : function() {
switch (this.node.nodeType) {
case 3:
case 4:
this.top_string(this.node.data);
break;
case 1:
this.compile_element();
}
var r = this._top.join('');
if (this.process_children) {
for (var i = 0, ilen = this.children.length; i < ilen; i++) {
var child = this.children[i];
child._indent = this._indent;
r += child._compile();
}
}
r += this._bottom.join('');
return r;
},
format_expression : function(e) {
/* Naive format expression builder. Replace reserved words and variables to dict[variable]
* Does not handle spaces before dot yet, and causes problems for anonymous functions. Use t-js="" for that */
if (QWeb2.expressions_cache[e]) {
return QWeb2.expressions_cache[e];
}
var chars = e.split(''),
instring = '',
invar = '',
invar_pos = 0,
r = '';
chars.push(' ');
for (var i = 0, ilen = chars.length; i < ilen; i++) {
var c = chars[i];
if (instring.length) {
if (c === instring && chars[i - 1] !== "\\") {
instring = '';
}
} else if (c === '"' || c === "'") {
instring = c;
} else if (c.match(/[a-zA-Z_\$]/) && !invar.length) {
invar = c;
invar_pos = i;
continue;
} else if (c.match(/\W/) && invar.length) {
// TODO: Should check for possible spaces before dot
if (chars[invar_pos - 1] !== '.' && QWeb2.tools.arrayIndexOf(this.engine.reserved_words, invar) < 0) {
invar = this.engine.word_replacement[invar] || ("dict['" + invar + "']");
}
r += invar;
invar = '';
} else if (invar.length) {
invar += c;
continue;
}
r += c;
}
r = r.slice(0, -1);
QWeb2.expressions_cache[e] = r;
return r;
},
string_interpolation : function(s) {
if (!s) {
return "''";
}
var regex = /^{(.*)}(.*)/,
src = s.split(/#/),
r = [];
for (var i = 0, ilen = src.length; i < ilen; i++) {
var val = src[i],
m = val.match(regex);
if (m) {
r.push("(" + this.format_expression(m[1]) + ")");
if (m[2]) {
r.push(this.engine.tools.js_escape(m[2]));
}
} else if (!(i === 0 && val === '')) {
r.push(this.engine.tools.js_escape((i === 0 ? '' : '#') + val));
}
}
return r.join(' + ');
},
indent : function() {
return this._indent++;
},
dedent : function() {
if (this._indent !== 0) {
return this._indent--;
}
},
get_indent : function() {
return new Array(this._indent + 1).join("\t");
},
top : function(s) {
return this._top.push(this.get_indent() + s + '\n');
},
top_string : function(s) {
return this._top.push(this.get_indent() + "//@string=" + this.engine.tools.js_escape(s, true) + '\n');
},
bottom : function(s) {
return this._bottom.unshift(this.get_indent() + s + '\n');
},
bottom_string : function(s) {
return this._bottom.unshift(this.get_indent() + "//@string=" + this.engine.tools.js_escape(s, true) + '\n');
},
compile_element : function() {
for (var i = 0, ilen = this.engine.actions_precedence.length; i < ilen; i++) {
var a = this.engine.actions_precedence[i];
if (a in this.actions) {
var value = this.actions[a];
var key = 'compile_action_' + a;
if (this[key]) {
this[key](value);
} else if (this.engine[key]) {
this.engine[key].call(this, value);
} else {
this.engine.tools.exception("No handler method for action '" + a + "'");
}
}
}
if (this.tag.toLowerCase() !== this.engine.prefix) {
var tag = "<" + this.tag;
for (var a in this.attributes) {
tag += this.engine.tools.gen_attribute([a, this.attributes[a]]);
}
this.top_string(tag);
if (this.actions.att) {
this.top("r.push(context.engine.tools.gen_attribute(" + (this.format_expression(this.actions.att)) + "));");
}
for (var a in this.actions) {
var v = this.actions[a];
var m = a.match(/att-(.+)/);
if (m) {
this.top("r.push(context.engine.tools.gen_attribute(['" + m[1] + "', (" + (this.format_expression(v)) + ")]));");
}
var m = a.match(/attf-(.+)/);
if (m) {
this.top("r.push(context.engine.tools.gen_attribute(['" + m[1] + "', (" + (this.string_interpolation(v)) + ")]));");
}
}
if (this.children.length || this.actions.opentag === 'true') {
this.top_string(">");
this.bottom_string("</" + this.tag + ">");
} else {
this.top_string("/>");
}
}
},
compile_action_if : function(value) {
this.top("if (" + (this.format_expression(value)) + ") {");
this.bottom("}");
this.indent();
},
compile_action_foreach : function(value) {
var as = this.actions['as'] || value.replace(/[^a-zA-Z0-9]/g, '_');
//TODO: exception if t-as not valid
this.top("context.engine.tools.foreach(context, " + (this.format_expression(value)) + ", " + (this.engine.tools.js_escape(as)) + ", dict, function(context, dict) {");
this.bottom("});");
this.indent();
},
compile_action_call : function(value) {
var _import = this.actions['import'] || '';
if (this.children.length === 0) {
return this.top("r.push(context.engine.tools.call(context, " + (this.engine.tools.js_escape(value)) + ", dict, " + (this.engine.tools.js_escape(_import)) + "));");
} else {
this.top("r.push(context.engine.tools.call(context, " + (this.engine.tools.js_escape(value)) + ", dict, " + (this.engine.tools.js_escape(_import)) + ", function(context, dict) {");
this.bottom("}));");
this.indent();
this.top("var r = [];");
return this.bottom("return r.join('');");
}
},
compile_action_set : function(value) {
var variable = this.format_expression(value);
if (this.actions['value']) {
if (this.children.length) {
this.engine.tools.warning("@set with @value plus node chidren found. Children are ignored.");
}
this.top(variable + " = (" + (this.format_expression(this.actions['value'])) + ");");
this.process_children = false;
} else {
if (this.children.length === 0) {
this.top(variable + " = '';");
} else if (this.children.length === 1 && this.children[0].node.nodeType === 3) {
this.top(variable + " = " + (this.engine.tools.js_escape(this.children[0].node.data)) + ";");
this.process_children = false;
} else {
this.top(variable + " = (function(dict) {");
this.bottom("})(dict);");
this.indent();
this.top("var r = [];");
this.bottom("return r.join('');");
}
}
},
compile_action_esc : function(value) {
this.top("r.push(context.engine.tools.html_escape(" + (this.format_expression(value)) + "));");
},
compile_action_escf : function(value) {
this.top("r.push(context.engine.tools.html_escape(" + (this.string_interpolation(value)) + "));");
},
compile_action_raw : function(value) {
this.top("r.push(" + (this.format_expression(value)) + ");");
},
compile_action_rawf : function(value) {
this.top("r.push(" + (this.string_interpolation(value)) + ");");
},
compile_action_js : function(value) {
this.top("(function(" + value + ") {");
this.bottom("})(dict);");
this.indent();
var lines = this.engine.tools.xml_node_to_string(this.node, true).split(/\r?\n/);
for (var i = 0, ilen = lines.length; i < ilen; i++) {
this.top(lines[i]);
}
this.process_children = false;
},
compile_action_debug : function(value) {
this.top("debugger;");
},
compile_action_log : function(value) {
this.top("console.log(" + this.format_expression(value) + ");");
}
});
return Element;
})();
window.QWeb2 = QWeb2;
})();

View File

@ -1,18 +1,18 @@
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* @license RequireJS 2.1.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
//Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict.
/*jslint regexp: true, nomen: true, sloppy: true */
/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */
/*global window, navigator, document, importScripts, setTimeout, opera */
var requirejs, require, define;
(function (global) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.1.2',
version = '2.1.8',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@ -21,9 +21,8 @@ var requirejs, require, define;
ostring = op.toString,
hasOwn = op.hasOwnProperty,
ap = Array.prototype,
aps = ap.slice,
apsp = ap.splice,
isBrowser = !!(typeof window !== 'undefined' && navigator && document),
isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
//PS3 indicates loaded and complete, but need to wait for complete
//specifically. Sequence is 'loading', 'loaded', execution,
@ -135,6 +134,10 @@ var requirejs, require, define;
return document.getElementsByTagName('script');
}
function defaultOnError(err) {
throw err;
}
//Allow getting a global that expressed in
//dot notation, like 'a.b.c'.
function getGlobal(value) {
@ -192,15 +195,21 @@ var requirejs, require, define;
var inCheckLoaded, Module, context, handlers,
checkLoadedTimeoutId,
config = {
//Defaults. Do not set a default for map
//config to speed up normalize(), which
//will run faster if there is no default.
waitSeconds: 7,
baseUrl: './',
paths: {},
pkgs: {},
shim: {},
map: {},
config: {}
},
registry = {},
//registry of just enabled modules, to speed
//cycle breaking code when lots of modules
//are registered, but not activated.
enabledRegistry = {},
undefEvents = {},
defQueue = [],
defined = {},
@ -296,7 +305,7 @@ var requirejs, require, define;
}
//Apply map config if available.
if (applyMap && (baseParts || starMap) && map) {
if (applyMap && map && (baseParts || starMap)) {
nameParts = name.split('/');
for (i = nameParts.length; i > 0; i -= 1) {
@ -495,7 +504,12 @@ var requirejs, require, define;
fn(defined[id]);
}
} else {
getModule(depMap).on(name, fn);
mod = getModule(depMap);
if (mod.error && name === 'error') {
fn(mod.error);
} else {
mod.on(name, fn);
}
}
}
@ -566,7 +580,13 @@ var requirejs, require, define;
id: mod.map.id,
uri: mod.map.url,
config: function () {
return (config.config && getOwn(config.config, mod.map.id)) || {};
var c,
pkg = getOwn(config.pkgs, mod.map.id);
// For packages, only support config targeted
// at the main module.
c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) :
getOwn(config.config, mod.map.id);
return c || {};
},
exports: defined[mod.map.id]
});
@ -577,6 +597,7 @@ var requirejs, require, define;
function cleanRegistry(id) {
//Clean up machinery used for waiting modules.
delete registry[id];
delete enabledRegistry[id];
}
function breakCycle(mod, traced, processed) {
@ -625,7 +646,7 @@ var requirejs, require, define;
inCheckLoaded = true;
//Figure out the state of all the modules.
eachProp(registry, function (mod) {
eachProp(enabledRegistry, function (mod) {
map = mod.map;
modId = map.id;
@ -806,7 +827,7 @@ var requirejs, require, define;
},
/**
* Checks is the module is ready to define itself, and if so,
* Checks if the module is ready to define itself, and if so,
* define it.
*/
check: function () {
@ -834,8 +855,13 @@ var requirejs, require, define;
if (this.depCount < 1 && !this.defined) {
if (isFunction(factory)) {
//If there is an error listener, favor passing
//to that instead of throwing an error.
if (this.events.error) {
//to that instead of throwing an error. However,
//only do it for define()'d modules. require
//errbacks should not be called for failures in
//their callbacks (#699). However if a global
//onError is set, use that.
if ((this.events.error && this.map.isDefine) ||
req.onError !== defaultOnError) {
try {
exports = context.execCb(id, factory, depExports, exports);
} catch (e) {
@ -863,8 +889,8 @@ var requirejs, require, define;
if (err) {
err.requireMap = this.map;
err.requireModules = [this.map.id];
err.requireType = 'define';
err.requireModules = this.map.isDefine ? [this.map.id] : null;
err.requireType = this.map.isDefine ? 'define' : 'require';
return onError((this.error = err));
}
@ -884,7 +910,7 @@ var requirejs, require, define;
}
//Clean up
delete registry[id];
cleanRegistry(id);
this.defined = true;
}
@ -918,8 +944,7 @@ var requirejs, require, define;
name = this.map.name,
parentName = this.map.parentMap ? this.map.parentMap.name : null,
localRequire = context.makeRequire(map.parentMap, {
enableBuildCallback: true,
skipMap: true
enableBuildCallback: true
});
//If current map is not normalized, wait for that
@ -1017,8 +1042,11 @@ var requirejs, require, define;
try {
req.exec(text);
} catch (e) {
throw new Error('fromText eval for ' + moduleName +
' failed: ' + e);
return onError(makeError('fromtexteval',
'fromText eval for ' + id +
' failed: ' + e,
e,
[id]));
}
if (hasInteractive) {
@ -1048,6 +1076,7 @@ var requirejs, require, define;
},
enable: function () {
enabledRegistry[this.map.id] = this;
this.enabled = true;
//Set flag mentioning that the module is enabling,
@ -1084,7 +1113,7 @@ var requirejs, require, define;
}));
if (this.errback) {
on(depMap, 'error', this.errback);
on(depMap, 'error', bind(this, this.errback));
}
}
@ -1207,6 +1236,7 @@ var requirejs, require, define;
Module: Module,
makeModuleMap: makeModuleMap,
nextTick: req.nextTick,
onError: onError,
/**
* Set a configuration for the context.
@ -1233,6 +1263,9 @@ var requirejs, require, define;
eachProp(cfg, function (value, prop) {
if (objs[prop]) {
if (prop === 'map') {
if (!config.map) {
config.map = {};
}
mixin(config[prop], value, true, true);
} else {
mixin(config[prop], value, true);
@ -1344,7 +1377,7 @@ var requirejs, require, define;
//Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that.
if (req.get) {
return req.get(context, deps, relMap);
return req.get(context, deps, relMap, localRequire);
}
//Normalize module name, if it contains . or ..
@ -1395,16 +1428,20 @@ var requirejs, require, define;
* plain URLs like nameToUrl.
*/
toUrl: function (moduleNamePlusExt) {
var index = moduleNamePlusExt.lastIndexOf('.'),
ext = null;
var ext,
index = moduleNamePlusExt.lastIndexOf('.'),
segment = moduleNamePlusExt.split('/')[0],
isRelative = segment === '.' || segment === '..';
if (index !== -1) {
//Have a file extension alias, and it is not the
//dots from a relative path.
if (index !== -1 && (!isRelative || index > 1)) {
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
}
return context.nameToUrl(normalize(moduleNamePlusExt,
relMap && relMap.id, true), ext);
relMap && relMap.id, true), ext, true);
},
defined: function (id) {
@ -1449,10 +1486,11 @@ var requirejs, require, define;
/**
* Called to enable a module if it is still in the registry
* awaiting enablement. parent module is passed in for context,
* used by the optimizer.
* awaiting enablement. A second arg, parent, the parent module,
* is passed in for context, when this method is overriden by
* the optimizer. Not shown here to keep code compact.
*/
enable: function (depMap, parent) {
enable: function (depMap) {
var mod = getOwn(registry, depMap.id);
if (mod) {
getModule(depMap).enable();
@ -1522,7 +1560,7 @@ var requirejs, require, define;
* it is assumed to have already been normalized. This is an
* internal API, not a public one. Use toUrl for the public API.
*/
nameToUrl: function (moduleName, ext) {
nameToUrl: function (moduleName, ext, skipExt) {
var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
parentPath;
@ -1571,7 +1609,7 @@ var requirejs, require, define;
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
url += (ext || (/\?/.test(url) ? '' : '.js'));
url += (ext || (/\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
}
@ -1587,7 +1625,7 @@ var requirejs, require, define;
},
/**
* Executes a module callack function. Broken out as a separate function
* Executes a module callback function. Broken out as a separate function
* solely to allow the build system to sequence the files in the built
* layer in the right sequence.
*
@ -1625,7 +1663,7 @@ var requirejs, require, define;
onScriptError: function (evt) {
var data = getScriptData(evt);
if (!hasPathFallback(data.id)) {
return onError(makeError('scripterror', 'Script error', evt, [data.id]));
return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
}
}
};
@ -1754,8 +1792,19 @@ var requirejs, require, define;
* function. Intercept/override it if you want custom error handling.
* @param {Error} err the error object.
*/
req.onError = function (err) {
throw err;
req.onError = defaultOnError;
/**
* Creates the node for the load command. Only used in browser envs.
*/
req.createNode = function (config, moduleName, url) {
var node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
return node;
};
/**
@ -1772,12 +1821,7 @@ var requirejs, require, define;
node;
if (isBrowser) {
//In the browser so use a script tag
node = config.xhtml ?
document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
document.createElement('script');
node.type = config.scriptType || 'text/javascript';
node.charset = 'utf-8';
node.async = true;
node = req.createNode(config, moduleName, url);
node.setAttribute('data-requirecontext', context.contextName);
node.setAttribute('data-requiremodule', moduleName);
@ -1810,7 +1854,7 @@ var requirejs, require, define;
node.attachEvent('onreadystatechange', context.onScriptLoad);
//It would be great to add an error handler here to catch
//404s in IE9+. However, onreadystatechange will fire before
//the error handler, so that does not help. If addEvenListener
//the error handler, so that does not help. If addEventListener
//is used, then IE will fire error before load, but we cannot
//use that pathway given the connect.microsoft.com issue
//mentioned above about not doing the 'script execute,
@ -1839,16 +1883,24 @@ var requirejs, require, define;
return node;
} else if (isWebWorker) {
//In a web worker, use importScripts. This is not a very
//efficient use of importScripts, importScripts will block until
//its script is downloaded and evaluated. However, if web workers
//are in play, the expectation that a build has been done so that
//only one script needs to be loaded anyway. This may need to be
//reevaluated if other use cases become common.
importScripts(url);
try {
//In a web worker, use importScripts. This is not a very
//efficient use of importScripts, importScripts will block until
//its script is downloaded and evaluated. However, if web workers
//are in play, the expectation that a build has been done so that
//only one script needs to be loaded anyway. This may need to be
//reevaluated if other use cases become common.
importScripts(url);
//Account for anonymous modules
context.completeLoad(moduleName);
//Account for anonymous modules
context.completeLoad(moduleName);
} catch (e) {
context.onError(makeError('importscripts',
'importScripts failed for ' +
moduleName + ' at ' + url,
e,
[moduleName]));
}
}
};
@ -1880,24 +1932,31 @@ var requirejs, require, define;
//baseUrl, if it is not already set.
dataMain = script.getAttribute('data-main');
if (dataMain) {
//Preserve dataMain in case it is a path (i.e. contains '?')
mainScript = dataMain;
//Set final baseUrl if there is not already an explicit one.
if (!cfg.baseUrl) {
//Pull off the directory of data-main for use as the
//baseUrl.
src = dataMain.split('/');
src = mainScript.split('/');
mainScript = src.pop();
subPath = src.length ? src.join('/') + '/' : './';
cfg.baseUrl = subPath;
dataMain = mainScript;
}
//Strip off any trailing .js since dataMain is now
//Strip off any trailing .js since mainScript is now
//like a module name.
dataMain = dataMain.replace(jsSuffixRegExp, '');
mainScript = mainScript.replace(jsSuffixRegExp, '');
//If mainScript is still a path, fall back to dataMain
if (req.jsExtRegExp.test(mainScript)) {
mainScript = dataMain;
}
//Put the data-main script in the files to load.
cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
return true;
}
@ -1925,12 +1984,13 @@ var requirejs, require, define;
//This module may not have dependencies
if (!isArray(deps)) {
callback = deps;
deps = [];
deps = null;
}
//If no name, and callback is a function, then figure out if it a
//CommonJS thing with dependencies.
if (!deps.length && isFunction(callback)) {
if (!deps && isFunction(callback)) {
deps = [];
//Remove comments from the callback string,
//look for require calls, and pull them into the dependencies,
//but only if there are function args.
@ -1990,4 +2050,4 @@ var requirejs, require, define;
//Set up with config info.
req(cfg);
}(this));
}(this));

View File

@ -1,8 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://localhost/im_livechat/static/ext/static/js/require.js"></script>
<script type="text/javascript" src='http://localhost/im_livechat/loader?p={"db":"test","channel":1}'></script>
<script type="text/javascript" src="http://localhost/im_livechat/static/ext/static/lib/requirejs/require.js"></script>
<script type="text/javascript" src='http://localhost/im_livechat/loader?p={"db":"testtrunk","channel":1}'></script>
</head>
<body style="height:100%; margin:0; padding:0;">
<iframe src="http://openerp.com" height="100%" width=100%"></iframe>

View File

@ -58,6 +58,7 @@ Wizards provided by this module:
'base_iban',
'account_chart',
'l10n_be_coda',
'l10n_multilang',
],
'data': [
'account_financial_report.xml',
@ -68,11 +69,11 @@ Wizards provided by this module:
'wizard/l10n_be_account_vat_declaration_view.xml',
'wizard/l10n_be_vat_intra_view.xml',
'wizard/l10n_be_partner_vat_listing.xml',
'wizard/account_wizard.xml',
'l10n_be_sequence.xml',
'fiscal_templates.xml',
'account_fiscal_position_tax_template.xml',
'security/ir.model.access.csv',
'l10n_be_wizard.yml'
],
'demo': [],
'installable': True,

View File

@ -12,6 +12,7 @@
<field name="property_account_payable" ref="a_pay"/>
<field name="property_account_expense_categ" ref="a_expense"/>
<field name="property_account_income_categ" ref="a_sale"/>
<field name="spoken_languages" eval="'nl_BE'"/>
</record>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
<openerp>
<data noupdate="1">
<record id="account.action_wizard_multi_chart_todo" model="ir.actions.todo">
<field name="state">open</field>
</record>
</data>
</openerp>

View File

@ -202,11 +202,11 @@ class partner_vat_intra(osv.osv_memory):
'vatnum': row['vat'][2:].replace(' ','').upper(),
'vat': row['vat'],
'country': row['vat'][:2],
'amount': amt,
'amount': round(amt,2),
'intra_code': row['intra_code'],
'code': intra_code})
xmldict.update({'dnum': dnum, 'clientnbr': str(seq), 'amountsum': amount_sum, 'partner_wo_vat': p_count})
xmldict.update({'dnum': dnum, 'clientnbr': str(seq), 'amountsum': round(amount_sum,2), 'partner_wo_vat': p_count})
return xmldict
def create_xml(self, cursor, user, ids, context=None):

View File

@ -32,6 +32,7 @@ Accounting Data for Belgian Payroll Rules.
'auto_install': True,
'demo': [],
'data':[
'l10n_be_wizard.yml',
'l10n_be_hr_payroll_account_data.xml',
'data/hr.salary.rule.csv',
],

View File

@ -207,6 +207,19 @@ class account_invoice(osv.osv):
'\nPlease create manually a unique BBA Structured Communication.'))
return super(account_invoice, self).write(cr, uid, ids, vals, context)
def copy(self, cr, uid, id, default=None, context=None):
default = default or {}
invoice = self.browse(cr, uid, id, context=context)
if invoice.type in ['out_invoice']:
reference_type = invoice.reference_type or 'none'
default['reference_type'] = reference_type
if reference_type == 'bba':
partner = invoice.partner_id
default['reference'] = self.generate_bbacomm(cr, uid, id,
invoice.type, reference_type,
partner.id, '', context=context)['value']['reference']
return super(account_invoice, self).copy(cr, uid, id, default, context=context)
_columns = {
'reference': fields.char('Communication', size=64, help="The partner reference of this invoice."),
'reference_type': fields.selection(_get_reference_type, 'Communication Type',

View File

@ -20,7 +20,7 @@
##############################################################################
{
'name': 'Canada - Accounting',
'version': '1.1',
'version': '1.2',
'author': 'Savoir-faire Linux',
'website': 'http://www.savoirfairelinux.com',
'category': 'Localization/Account Charts',
@ -29,6 +29,28 @@ This is the module to manage the English and French - Canadian accounting chart
===========================================================================================
Canadian accounting charts and localizations.
Fiscal positions
----------------
When considering taxes to be applied, it is the province where the delivery occurs that matters.
Therefore we decided to implement the most common case in the fiscal positions: delivery is the
responsibility of the supplier and done at the customer location.
Some examples:
1) You have a customer from another province and you deliver to his location.
On the customer, set the fiscal position to his province.
2) You have a customer from another province. However this customer comes to your location
with their truck to pick up products. On the customer, do not set any fiscal position.
3) An international supplier doesn't charge you any tax. Taxes are charged at customs
by the customs broker. On the supplier, set the fiscal position to International.
4) An international supplier charge you your provincial tax. They are registered with your
provincial government and remit taxes themselves. On the supplier, do not set any fiscal
position.
""",
'depends': [
'base',

View File

@ -131,7 +131,7 @@
<field name="parent_id" ref="chart118_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_receivable"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">GST receivable</field>
</record>
@ -140,17 +140,43 @@
<field name="parent_id" ref="chart118_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_receivable"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">PST/QST receivable</field>
</record>
<record id="chart1183_en" model="account.account.template">
<field name="code">1183</field>
<field name="parent_id" ref="chart118_en"/>
<field name="type">view</field>
<field name="user_type" ref="account.data_account_type_view"/>
<field name="name">HST receivable</field>
</record>
<record id="chart11831_en" model="account.account.template">
<field name="code">11831</field>
<field name="parent_id" ref="chart1183_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_receivable"/>
<field name="reconcile" eval="True"/>
<field name="name">HST receivable</field>
<field name="reconcile" eval="False"/>
<field name="name">HST receivable - 13%</field>
</record>
<record id="chart11832_en" model="account.account.template">
<field name="code">11832</field>
<field name="parent_id" ref="chart1183_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_receivable"/>
<field name="reconcile" eval="False"/>
<field name="name">HST receivable - 14%</field>
</record>
<record id="chart11833_en" model="account.account.template">
<field name="code">11833</field>
<field name="parent_id" ref="chart1183_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_receivable"/>
<field name="reconcile" eval="False"/>
<field name="name">HST receivable - 15%</field>
</record>
<record id="chart15_en" model="account.account.template">
@ -257,7 +283,7 @@
<field name="parent_id" ref="chart213_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">GST to pay</field>
</record>
@ -266,17 +292,43 @@
<field name="parent_id" ref="chart213_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">PST/QST to pay</field>
</record>
<record id="chart2133_en" model="account.account.template">
<field name="code">2133</field>
<field name="parent_id" ref="chart213_en"/>
<field name="type">view</field>
<field name="user_type" ref="account.data_account_type_view"/>
<field name="name">HST to pay</field>
</record>
<record id="chart21331_en" model="account.account.template">
<field name="code">21331</field>
<field name="parent_id" ref="chart2133_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field name="reconcile" eval="True"/>
<field name="name">HST to pay</field>
<field name="reconcile" eval="False"/>
<field name="name">HST to pay - 13%</field>
</record>
<record id="chart21332_en" model="account.account.template">
<field name="code">21332</field>
<field name="parent_id" ref="chart2133_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field name="reconcile" eval="False"/>
<field name="name">HST to pay - 14%</field>
</record>
<record id="chart21333_en" model="account.account.template">
<field name="code">21333</field>
<field name="parent_id" ref="chart2133_en"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_payable"/>
<field name="reconcile" eval="False"/>
<field name="name">HST to pay - 15%</field>
</record>
<record id="chart214_en" model="account.account.template">

View File

@ -130,7 +130,7 @@
<field name="parent_id" ref="chart118_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_asset"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">TPS à recevoir</field>
</record>
@ -139,17 +139,43 @@
<field name="parent_id" ref="chart118_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_asset"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">TVP/TVQ à recevoir</field>
</record>
<record id="chart1183_fr" model="account.account.template">
<field name="code">1183</field>
<field name="parent_id" ref="chart118_fr"/>
<field name="type">view</field>
<field name="user_type" ref="account.data_account_type_view"/>
<field name="name">TVH à recevoir</field>
</record>
<record id="chart11831_fr" model="account.account.template">
<field name="code">11831</field>
<field name="parent_id" ref="chart1183_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_asset"/>
<field name="reconcile" eval="True"/>
<field name="name">TVH à recevoir</field>
<field name="reconcile" eval="False"/>
<field name="name">TVH à recevoir - 13%</field>
</record>
<record id="chart11832_fr" model="account.account.template">
<field name="code">11832</field>
<field name="parent_id" ref="chart1183_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_asset"/>
<field name="reconcile" eval="False"/>
<field name="name">TVH à recevoir - 14%</field>
</record>
<record id="chart11833_fr" model="account.account.template">
<field name="code">11833</field>
<field name="parent_id" ref="chart1183_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_asset"/>
<field name="reconcile" eval="False"/>
<field name="name">TVH à recevoir - 15%</field>
</record>
<record id="chart15_fr" model="account.account.template">
@ -256,7 +282,7 @@
<field name="parent_id" ref="chart213_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_liability"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">TPS à payer</field>
</record>
@ -265,17 +291,43 @@
<field name="parent_id" ref="chart213_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_liability"/>
<field name="reconcile" eval="True"/>
<field name="reconcile" eval="False"/>
<field name="name">TVP/TVQ à payer</field>
</record>
<record id="chart2133_fr" model="account.account.template">
<field name="code">2133</field>
<field name="parent_id" ref="chart213_fr"/>
<field name="type">view</field>
<field name="user_type" ref="account.data_account_type_view"/>
<field name="name">TVH à payer</field>
</record>
<record id="chart21331_fr" model="account.account.template">
<field name="code">21331</field>
<field name="parent_id" ref="chart2133_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_liability"/>
<field name="reconcile" eval="True"/>
<field name="name">TVH à payer</field>
<field name="reconcile" eval="False"/>
<field name="name">TVH à payer - 13%</field>
</record>
<record id="chart21332_fr" model="account.account.template">
<field name="code">21332</field>
<field name="parent_id" ref="chart2133_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_liability"/>
<field name="reconcile" eval="False"/>
<field name="name">TVH à payer - 14%</field>
</record>
<record id="chart21333_fr" model="account.account.template">
<field name="code">21333</field>
<field name="parent_id" ref="chart2133_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_liability"/>
<field name="reconcile" eval="False"/>
<field name="name">TVH à payer - 15%</field>
</record>
<record id="chart214_fr" model="account.account.template">
@ -672,7 +724,7 @@
<field name="code">5112</field>
<field name="parent_id" ref="chart511_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_income"/>
<field name="user_type" ref="account.data_account_type_expense"/>
<field name="name">Achats dans des provinces harmonisées</field>
</record>
@ -680,7 +732,7 @@
<field name="code">5113</field>
<field name="parent_id" ref="chart511_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_income"/>
<field name="user_type" ref="account.data_account_type_expense"/>
<field name="name">Achats dans des provinces non-harmonisées</field>
</record>
@ -688,7 +740,7 @@
<field name="code">5114</field>
<field name="parent_id" ref="chart511_fr"/>
<field name="type">other</field>
<field name="user_type" ref="account.data_account_type_income"/>
<field name="user_type" ref="account.data_account_type_expense"/>
<field name="name">Achats à l'étranger</field>
</record>

View File

@ -31,6 +31,21 @@
<field name="parent_id" ref="vat_code_receivable_tva_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst13_en">
<field name="name">HST paid - 13%</field>
<field name="parent_id" ref="vat_code_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst14_en">
<field name="name">HST paid - 14%</field>
<field name="parent_id" ref="vat_code_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst15_en">
<field name="name">HST paid - 15%</field>
<field name="parent_id" ref="vat_code_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_en">
<field name="name">Taxes received</field>
<field name="parent_id" ref="vat_code_balance_net_en"/>
@ -51,6 +66,21 @@
<field name="parent_id" ref="vat_code_payable_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst13_en">
<field name="name">HST received - 13%</field>
<field name="parent_id" ref="vat_code_payable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst14_en">
<field name="name">HST received - 14%</field>
<field name="parent_id" ref="vat_code_payable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst15_en">
<field name="name">HST received - 15%</field>
<field name="parent_id" ref="vat_code_payable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_net_en">
<field name="name">Taxes Base</field>
<field name="parent_id" ref="vat_code_tax_en"/>
@ -76,6 +106,21 @@
<field name="parent_id" ref="vat_code_base_receivable_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst13_en">
<field name="name">Base of HST for Sales - 13%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst14_en">
<field name="name">Base of HST for Sales - 14%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst15_en">
<field name="name">Base of HST for Sales - 15%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_en">
<field name="name">Base of Purchases Tax</field>
<field name="parent_id" ref="vat_code_base_net_en"/>
@ -96,5 +141,20 @@
<field name="parent_id" ref="vat_code_base_payable_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst13_en">
<field name="name">Base of HST for Purchases - 13%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst14_en">
<field name="name">Base of HST for Purchases - 14%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_en"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst15_en">
<field name="name">Base of HST for Purchases - 15%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_en"/>
</record>
</data>
</openerp>

View File

@ -16,41 +16,71 @@
<field name="parent_id" ref="vat_code_balance_net_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_tps_fr">
<record model="account.tax.code.template" id="vat_code_receivable_gst_fr">
<field name="name">TPS payée</field>
<field name="parent_id" ref="vat_code_receivable_tva_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_tvp_fr">
<record model="account.tax.code.template" id="vat_code_receivable_pst_fr">
<field name="name">TVP/TVQ payée</field>
<field name="parent_id" ref="vat_code_receivable_tva_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_tvh_fr">
<record model="account.tax.code.template" id="vat_code_receivable_hst_fr">
<field name="name">TVH payée</field>
<field name="parent_id" ref="vat_code_receivable_tva_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst13_fr">
<field name="name">TVH payée - 13%</field>
<field name="parent_id" ref="vat_code_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst14_fr">
<field name="name">TVH payée - 14%</field>
<field name="parent_id" ref="vat_code_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_receivable_hst15_fr">
<field name="name">TVH payée - 15%</field>
<field name="parent_id" ref="vat_code_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_fr">
<field name="name">Taxes reçues</field>
<field name="parent_id" ref="vat_code_balance_net_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_tps_fr">
<record model="account.tax.code.template" id="vat_code_payable_gst_fr">
<field name="name">TPS reçue</field>
<field name="parent_id" ref="vat_code_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_tvp_fr">
<record model="account.tax.code.template" id="vat_code_payable_pst_fr">
<field name="name">TVP/TVQ reçue</field>
<field name="parent_id" ref="vat_code_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_tvh_fr">
<record model="account.tax.code.template" id="vat_code_payable_hst_fr">
<field name="name">TVH reçue</field>
<field name="parent_id" ref="vat_code_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst13_fr">
<field name="name">TVH reçue - 13%</field>
<field name="parent_id" ref="vat_code_payable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst14_fr">
<field name="name">TVH reçue - 14%</field>
<field name="parent_id" ref="vat_code_payable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_payable_hst15_fr">
<field name="name">TVH reçue - 15%</field>
<field name="parent_id" ref="vat_code_payable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_net_fr">
<field name="name">Base de taxes</field>
<field name="parent_id" ref="vat_code_tax_fr"/>
@ -61,40 +91,70 @@
<field name="parent_id" ref="vat_code_base_net_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_tps_fr">
<record model="account.tax.code.template" id="vat_code_base_receivable_gst_fr">
<field name="name">Base de la TPS pour les ventes</field>
<field name="parent_id" ref="vat_code_base_receivable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_tvp_fr">
<record model="account.tax.code.template" id="vat_code_base_receivable_pst_fr">
<field name="name">Base de la TVP/TVQ pour les ventes</field>
<field name="parent_id" ref="vat_code_base_receivable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_tvh_fr">
<record model="account.tax.code.template" id="vat_code_base_receivable_hst_fr">
<field name="name">Base de la TVH pour les ventes</field>
<field name="parent_id" ref="vat_code_base_receivable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst13_fr">
<field name="name">Base de la TVH pour les ventes - 13%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst14_fr">
<field name="name">Base de la TVH pour les ventes - 14%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_receivable_hst15_fr">
<field name="name">Base de la TVH pour les ventes - 15%</field>
<field name="parent_id" ref="vat_code_base_receivable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_fr">
<field name="name">Base des taxes d'achats</field>
<field name="parent_id" ref="vat_code_base_net_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_tps_fr">
<record model="account.tax.code.template" id="vat_code_base_payable_gst_fr">
<field name="name">Base de la TPS pour les achats</field>
<field name="parent_id" ref="vat_code_base_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_tvp_fr">
<record model="account.tax.code.template" id="vat_code_base_payable_pst_fr">
<field name="name">Base de la TVP/TVQ pour les achats</field>
<field name="parent_id" ref="vat_code_base_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_tvh_fr">
<record model="account.tax.code.template" id="vat_code_base_payable_hst_fr">
<field name="name">Base de la TVH pour les achats</field>
<field name="parent_id" ref="vat_code_base_payable_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst13_fr">
<field name="name">Base de la TVH pour les achats - 13%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst14_fr">
<field name="name">Base de la TVH pour les achats - 14%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_fr"/>
</record>
<record model="account.tax.code.template" id="vat_code_base_payable_hst15_fr">
<field name="name">Base de la TVH pour les achats - 15%</field>
<field name="parent_id" ref="vat_code_base_payable_hst_fr"/>
</record>
</data>
</openerp>

View File

@ -4,6 +4,53 @@
<!-- SALES TAXES -->
<!-- British Columbia PST -->
<record id="gstpst_bc_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + PST for sales (BC)</field>
<field name="description">GSTPST_BC_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend">1</field>
</record>
<record id="gstpst_sale_bc_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for sales - 5% (BC)</field>
<field name="description">GST</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_en"/>
<field name="account_paid_id" ref="chart2131_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_en"/>
<field name="tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="parent_id" ref="gstpst_bc_sale_en"/>
</record>
<record id="pst_bc_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for sales - 7% (BC)</field>
<field name="description">PST</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.070000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_en"/>
<field name="account_paid_id" ref="chart2132_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_en"/>
<field name="tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="parent_id" ref="gstpst_bc_sale_en"/>
</record>
<!-- Manitoba PST -->
<record id="gstpst_mb_sale_en" model="account.tax.template">
@ -13,6 +60,7 @@
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gstpst_sale_mb_gst_en" model="account.tax.template">
@ -35,10 +83,10 @@
<record id="pst_mb_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for sales - 7%</field>
<field name="name">PST for sales - 8% (MB)</field>
<field name="description">PST</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.070000</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_en"/>
@ -50,65 +98,19 @@
<field name="parent_id" ref="gstpst_mb_sale_en"/>
</record>
<!-- Prince Edward Island PST -->
<record id="gstpst_pe_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + PST for sales (PE)</field>
<field name="description">GSTPST_PE_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="child_depend">1</field>
<field name="type">percent</field>
</record>
<record id="gstpst_sale_pe_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for sales - 5% (PE)</field>
<field name="description">GST</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_en"/>
<field name="account_paid_id" ref="chart2131_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_en"/>
<field name="tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="parent_id" ref="gstpst_pe_sale_en"/>
</record>
<record id="pst_pe_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for sale - 10%</field>
<field name="description">PST</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.100000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_en"/>
<field name="account_paid_id" ref="chart2132_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_en"/>
<field name="tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="parent_id" ref="gstpst_pe_sale_en"/>
</record>
<!-- Quebec PST -->
<record id="gsttvq_sale_en" model="account.tax.template">
<record id="gstqst_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + QST for sales</field>
<field name="description">GSTQST_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gsttvq_sale_gst_en" model="account.tax.template">
<record id="gstqst_sale_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for sales - 5% (QC)</field>
<field name="description">GST</field>
@ -122,10 +124,10 @@
<field name="tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_en"/>
<field name="parent_id" ref="gsttvq_sale_en"/>
<field name="parent_id" ref="gstqst_sale_en"/>
</record>
<record id="tvq_sale_en" model="account.tax.template">
<record id="qst_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">QST for sales - 9.975%</field>
<field name="description">QST</field>
@ -139,7 +141,7 @@
<field name="tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_en"/>
<field name="parent_id" ref="gsttvq_sale_en"/>
<field name="parent_id" ref="gstqst_sale_en"/>
</record>
<!-- Saskatchewan PST -->
@ -151,6 +153,7 @@
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gstpst_sale_sk_gst_en" model="account.tax.template">
@ -190,21 +193,6 @@
<!-- HST -->
<record id="hst12_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for sales - 12%</field>
<field name="description">HST12_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.120000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_en"/>
<field name="account_paid_id" ref="chart2133_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst_en"/>
</record>
<record id="hst13_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for sales - 13%</field>
@ -212,27 +200,27 @@
<field name="type_tax_use">sale</field>
<field name="amount">0.130000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_en"/>
<field name="account_paid_id" ref="chart2133_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="account_collected_id" ref="chart21331_en"/>
<field name="account_paid_id" ref="chart21331_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst13_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst13_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst13_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst13_en"/>
</record>
<record id="hst135_sale_en" model="account.tax.template">
<record id="hst14_sale_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for sales - 13.5%</field>
<field name="description">HST135_SALE</field>
<field name="name">HST for sales - 14%</field>
<field name="description">HST14_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.135000</field>
<field name="amount">0.14000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_en"/>
<field name="account_paid_id" ref="chart2133_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="account_collected_id" ref="chart21332_en"/>
<field name="account_paid_id" ref="chart21332_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst14_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst14_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst14_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst14_en"/>
</record>
<record id="hst15_sale_en" model="account.tax.template">
@ -242,12 +230,12 @@
<field name="type_tax_use">sale</field>
<field name="amount">0.150000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_en"/>
<field name="account_paid_id" ref="chart2133_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst_en"/>
<field name="account_collected_id" ref="chart21333_en"/>
<field name="account_paid_id" ref="chart21333_en"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst15_en"/>
<field name="tax_code_id" ref="vat_code_payable_hst15_en"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst15_en"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst15_en"/>
</record>
<!-- GST -->
@ -267,9 +255,55 @@
<field name="ref_tax_code_id" ref="vat_code_payable_gst_en"/>
</record>
<!-- PURCHASE TAXES -->
<!-- British Columbia PST -->
<record id="gstpst_bc_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + PST for purchases (BC)</field>
<field name="description">GSTPST_BC_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend">1</field>
</record>
<record id="gstpst_purc_bc_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for purchases - 5% (BC)</field>
<field name="description">GST</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_en"/>
<field name="account_paid_id" ref="chart1181_en"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="parent_id" ref="gstpst_bc_purc_en"/>
</record>
<record id="pst_bc_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for purchases - 7% (BC)</field>
<field name="description">PST</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.070000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_en"/>
<field name="account_paid_id" ref="chart1182_en"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="parent_id" ref="gstpst_bc_purc_en"/>
</record>
<!-- Manitoba PST -->
<record id="gstpst_mb_purc_en" model="account.tax.template">
@ -279,6 +313,7 @@
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gstpst_purc_mb_gst_en" model="account.tax.template">
@ -301,10 +336,10 @@
<record id="pst_mb_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for purchases - 7%</field>
<field name="name">PST for purchases - 8% (MB)</field>
<field name="description">PST</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.070000</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_en"/>
@ -316,65 +351,19 @@
<field name="parent_id" ref="gstpst_mb_purc_en"/>
</record>
<!-- Prince Edward Island PST -->
<record id="gstpst_pe_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + PST for purchases (PE)</field>
<field name="description">GSTPST_PE_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="child_depend">1</field>
<field name="type">percent</field>
</record>
<record id="gstpst_purc_pe_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for purchases - 5% (PE)</field>
<field name="description">GST</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_en"/>
<field name="account_paid_id" ref="chart1181_en"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="parent_id" ref="gstpst_pe_purc_en"/>
</record>
<record id="pst_pe_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">PST for purchases - 10%</field>
<field name="description">PST</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.100000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_en"/>
<field name="account_paid_id" ref="chart1182_en"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="parent_id" ref="gstpst_pe_purc_en"/>
</record>
<!-- Quebec PST -->
<record id="gsttvq_purc_en" model="account.tax.template">
<record id="gstqst_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST + QST for purchases</field>
<field name="description">GSTQST_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gsttvq_purc_gst_en" model="account.tax.template">
<record id="gstqst_purc_gst_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">GST for purchases - 5% (QC)</field>
<field name="description">GST</field>
@ -388,10 +377,10 @@
<field name="tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_en"/>
<field name="parent_id" ref="gsttvq_purc_en"/>
<field name="parent_id" ref="gstqst_purc_en"/>
</record>
<record id="tvq_purc_en" model="account.tax.template">
<record id="qst_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">QST for purchases - 9.975%</field>
<field name="description">QST</field>
@ -405,7 +394,7 @@
<field name="tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_en"/>
<field name="parent_id" ref="gsttvq_purc_en"/>
<field name="parent_id" ref="gstqst_purc_en"/>
</record>
<!-- Saskatchewan PST -->
@ -417,6 +406,7 @@
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="gstpst_purc_sk_gst_en" model="account.tax.template">
@ -456,21 +446,6 @@
<!-- HST -->
<record id="hst12_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for purchases - 12%</field>
<field name="description">HST12_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.120000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_en"/>
<field name="account_paid_id" ref="chart1183_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst_en"/>
</record>
<record id="hst13_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for purchases - 13%</field>
@ -478,27 +453,27 @@
<field name="type_tax_use">purchase</field>
<field name="amount">0.130000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_en"/>
<field name="account_paid_id" ref="chart1183_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="account_collected_id" ref="chart11831_en"/>
<field name="account_paid_id" ref="chart11831_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst13_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst13_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst13_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst13_en"/>
</record>
<record id="hst135_purc_en" model="account.tax.template">
<record id="hst14_purc_en" model="account.tax.template">
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
<field name="name">HST for purchases - 13.5%</field>
<field name="description">HST135_PURC</field>
<field name="name">HST for purchases - 14%</field>
<field name="description">HST14_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.135000</field>
<field name="amount">0.140000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_en"/>
<field name="account_paid_id" ref="chart1183_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="account_collected_id" ref="chart11832_en"/>
<field name="account_paid_id" ref="chart11832_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst14_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst14_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst14_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst14_en"/>
</record>
<record id="hst15_purc_en" model="account.tax.template">
@ -508,12 +483,12 @@
<field name="type_tax_use">purchase</field>
<field name="amount">0.150000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_en"/>
<field name="account_paid_id" ref="chart1183_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst_en"/>
<field name="account_collected_id" ref="chart11833_en"/>
<field name="account_paid_id" ref="chart11833_en"/>
<field name="base_code_id" ref="vat_code_base_payable_hst15_en"/>
<field name="tax_code_id" ref="vat_code_receivable_hst15_en"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst15_en"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst15_en"/>
</record>
<!-- GST -->

View File

@ -4,18 +4,66 @@
<!-- SALES TAXES -->
<!-- British Columbia PST -->
<record id="gstpst_bc_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les ventes (BC)</field>
<field name="description">TPSTVP_BC_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="child_depend">1</field>
<field name="type">percent</field>
</record>
<record id="gstpst_sale_bc_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5% (BC)</field>
<field name="description">TPS</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="parent_id" ref="gstpst_bc_sale_fr"/>
</record>
<record id="pst_bc_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les ventes - 7% (BC)</field>
<field name="description">TVP</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.070000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_fr"/>
<field name="account_paid_id" ref="chart2132_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="parent_id" ref="gstpst_bc_sale_fr"/>
</record>
<!-- Manitoba PST -->
<record id="tpstvp_mb_sale_fr" model="account.tax.template">
<record id="gstpst_mb_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les ventes (MB)</field>
<field name="description">TPSTVP_MB_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvp_sale_mb_tps_fr" model="account.tax.template">
<record id="gstpst_sale_mb_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5% (MB)</field>
<field name="description">TPS</field>
@ -26,89 +74,43 @@
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="parent_id" ref="tpstvp_mb_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="parent_id" ref="gstpst_mb_sale_fr"/>
</record>
<record id="tvp_mb_sale_fr" model="account.tax.template">
<record id="pst_mb_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les ventes - 7%</field>
<field name="name">TVP sur les ventes - 8% (MB)</field>
<field name="description">TVP</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.070000</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_fr"/>
<field name="account_paid_id" ref="chart2132_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_mb_sale_fr"/>
</record>
<!-- Prince Edward Island PST -->
<record id="tpstvp_pe_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les ventes (PE)</field>
<field name="description">TPSTVP_PE_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="child_depend">1</field>
<field name="type">percent</field>
</record>
<record id="tpstvp_sale_pe_tps_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5% (PE)</field>
<field name="description">TPS</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="parent_id" ref="tpstvp_pe_sale_fr"/>
</record>
<record id="tvp_pe_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP for sale - 10%</field>
<field name="description">TVP</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.100000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_fr"/>
<field name="account_paid_id" ref="chart2132_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_pe_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="parent_id" ref="gstpst_mb_sale_fr"/>
</record>
<!-- Quebec PST -->
<record id="tpstvq_sale_fr" model="account.tax.template">
<record id="gstqst_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVQ sur les ventes</field>
<field name="description">TPSTVQ_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvq_sale_tps_fr" model="account.tax.template">
<record id="gstqst_sale_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5% (QC)</field>
<field name="description">TPS</field>
@ -118,11 +120,11 @@
<field name="sequence">1</field>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="parent_id" ref="tpstvq_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="parent_id" ref="gstqst_sale_fr"/>
</record>
<record id="tvq_sale_fr" model="account.tax.template">
@ -135,25 +137,26 @@
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_fr"/>
<field name="account_paid_id" ref="chart2132_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="parent_id" ref="tpstvq_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="parent_id" ref="gstqst_sale_fr"/>
</record>
<!-- Saskatchewan PST -->
<record id="tpstvp_sk_sale_fr" model="account.tax.template">
<record id="gstpst_sk_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les ventes (SK)</field>
<field name="description">TPSTVP_SK_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvp_sale_sk_tps_fr" model="account.tax.template">
<record id="gstpst_sale_sk_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5% (SK)</field>
<field name="description">TPS</field>
@ -164,14 +167,14 @@
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="parent_id" ref="tpstvp_sk_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="parent_id" ref="gstpst_sk_sale_fr"/>
</record>
<record id="tvp_sk_sale_fr" model="account.tax.template">
<record id="pst_sk_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les ventes - 5% (SK)</field>
<field name="description">TVP</field>
@ -181,78 +184,63 @@
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart2132_fr"/>
<field name="account_paid_id" ref="chart2132_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_sk_sale_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_pst_fr"/>
<field name="parent_id" ref="gstpst_sk_sale_fr"/>
</record>
<!-- HST -->
<record id="tvh12_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les ventes - 12%</field>
<field name="description">TVH12_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.120000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_fr"/>
<field name="account_paid_id" ref="chart2133_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvh_fr"/>
</record>
<record id="tvh13_sale_fr" model="account.tax.template">
<record id="hst13_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les ventes - 13%</field>
<field name="description">TVH13_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.130000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_fr"/>
<field name="account_paid_id" ref="chart2133_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="account_collected_id" ref="chart21331_fr"/>
<field name="account_paid_id" ref="chart21331_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst13_fr"/>
<field name="tax_code_id" ref="vat_code_payable_hst13_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst13_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst13_fr"/>
</record>
<record id="tvh135_sale_fr" model="account.tax.template">
<record id="hst14_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les ventes - 13.5%</field>
<field name="description">TVH135_SALE</field>
<field name="name">TVH sur les ventes - 14%</field>
<field name="description">TVH14_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.135000</field>
<field name="amount">0.140000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_fr"/>
<field name="account_paid_id" ref="chart2133_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="account_collected_id" ref="chart21332_fr"/>
<field name="account_paid_id" ref="chart21332_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst14_fr"/>
<field name="tax_code_id" ref="vat_code_payable_hst14_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst14_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst14_fr"/>
</record>
<record id="tvh15_sale_fr" model="account.tax.template">
<record id="hst15_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les ventes - 15%</field>
<field name="description">TVH15_SALE</field>
<field name="type_tax_use">sale</field>
<field name="amount">0.150000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2133_fr"/>
<field name="account_paid_id" ref="chart2133_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tvh_fr"/>
<field name="account_collected_id" ref="chart21333_fr"/>
<field name="account_paid_id" ref="chart21333_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_hst15_fr"/>
<field name="tax_code_id" ref="vat_code_payable_hst15_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_hst15_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_hst15_fr"/>
</record>
<!-- GST -->
<record id="tps_sale_fr" model="account.tax.template">
<record id="gst_sale_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les ventes - 5%</field>
<field name="description">TPS_SALE</field>
@ -261,27 +249,75 @@
<field name="type">percent</field>
<field name="account_collected_id" ref="chart2131_fr"/>
<field name="account_paid_id" ref="chart2131_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_tps_fr"/>
<field name="base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_payable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_receivable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_payable_gst_fr"/>
</record>
<!-- PURCHASE TAXES -->
<!-- British Columbia PST -->
<record id="gstpst_bc_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les achats (BC)</field>
<field name="description">TPSTVP_BC_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend">1</field>
</record>
<record id="gstpst_purc_bc_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5% (BC)</field>
<field name="description">TPS</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="parent_id" ref="gstpst_bc_purc_fr"/>
</record>
<record id="pst_bc_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les achats - 7% (BC)</field>
<field name="description">TVP</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.070000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_fr"/>
<field name="account_paid_id" ref="chart1182_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="parent_id" ref="gstpst_bc_purc_fr"/>
</record>
<!-- Manitoba PST -->
<record id="tpstvp_mb_purc_fr" model="account.tax.template">
<record id="gstpst_mb_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les achats (MB)</field>
<field name="description">TPSTVP_MB_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvp_purc_mb_tps_fr" model="account.tax.template">
<record id="gstpst_purc_mb_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5% (MB)</field>
<field name="description">TPS</field>
@ -292,89 +328,43 @@
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="parent_id" ref="tpstvp_mb_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="parent_id" ref="gstpst_mb_purc_fr"/>
</record>
<record id="tvp_mb_purc_fr" model="account.tax.template">
<record id="pst_mb_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les achats - 7%</field>
<field name="name">TVP sur les achats - 8% (MB)</field>
<field name="description">TVP</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.070000</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_fr"/>
<field name="account_paid_id" ref="chart1182_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_mb_purc_fr"/>
</record>
<!-- Prince Edward Island PST -->
<record id="tpstvp_pe_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les achats (PE)</field>
<field name="description">TPSTVP_PE_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="child_depend">1</field>
<field name="type">percent</field>
</record>
<record id="tpstvp_purc_pe_tps_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5% (PE)</field>
<field name="description">TPS</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="sequence">1</field>
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="parent_id" ref="tpstvp_pe_purc_fr"/>
</record>
<record id="tvp_pe_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les achats - 10%</field>
<field name="description">TVP</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.100000</field>
<field name="type">percent</field>
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_fr"/>
<field name="account_paid_id" ref="chart1182_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_pe_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="parent_id" ref="gstpst_mb_purc_fr"/>
</record>
<!-- Quebec PST -->
<record id="tpstvq_purc_fr" model="account.tax.template">
<record id="gstqst_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVQ sur les achats</field>
<field name="description">TPSTVQ_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvq_purc_tps_fr" model="account.tax.template">
<record id="gstqst_purc_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5% (QC)</field>
<field name="description">TPS</field>
@ -384,11 +374,11 @@
<field name="sequence">1</field>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="parent_id" ref="tpstvq_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="parent_id" ref="gstqst_purc_fr"/>
</record>
<record id="tvq_purc_fr" model="account.tax.template">
@ -401,25 +391,26 @@
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_fr"/>
<field name="account_paid_id" ref="chart1182_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="parent_id" ref="tpstvq_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="parent_id" ref="gstqst_purc_fr"/>
</record>
<!-- Saskatchewan PST -->
<record id="tpstvp_sk_purc_fr" model="account.tax.template">
<record id="gstpst_sk_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS + TVP sur les achats (SK)</field>
<field name="description">TPSTVP_SK_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">1</field>
<field name="type">percent</field>
<field name="child_depend" eval="True"/>
</record>
<record id="tpstvp_purc_sk_tps_fr" model="account.tax.template">
<record id="gstpst_purc_sk_gst_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5% (SK)</field>
<field name="description">TPS</field>
@ -430,14 +421,14 @@
<field name="include_base_amount" eval="True"/>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="parent_id" ref="tpstvp_sk_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="parent_id" ref="gstpst_sk_purc_fr"/>
</record>
<record id="tvp_sk_purc_fr" model="account.tax.template">
<record id="pst_sk_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVP sur les achats - 5% (SK)</field>
<field name="description">TVP</field>
@ -447,78 +438,63 @@
<field name="sequence">2</field>
<field name="account_collected_id" ref="chart1182_fr"/>
<field name="account_paid_id" ref="chart1182_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvp_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvp_fr"/>
<field name="parent_id" ref="tpstvp_sk_purc_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_pst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_pst_fr"/>
<field name="parent_id" ref="gstpst_sk_purc_fr"/>
</record>
<!-- HST -->
<record id="tvh12_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les achats - 12%</field>
<field name="description">TVH12_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.120000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_fr"/>
<field name="account_paid_id" ref="chart1183_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvh_fr"/>
</record>
<record id="tvh13_purc_fr" model="account.tax.template">
<record id="hst13_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les achats - 13%</field>
<field name="description">TVH13_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.130000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_fr"/>
<field name="account_paid_id" ref="chart1183_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="account_collected_id" ref="chart11831_fr"/>
<field name="account_paid_id" ref="chart11831_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_hst13_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_hst13_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst13_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst13_fr"/>
</record>
<record id="tvh135_purc_fr" model="account.tax.template">
<record id="hst14_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les achats - 13.5%</field>
<field name="description">TVH135_PURC</field>
<field name="name">TVH sur les achats - 14%</field>
<field name="description">TVH14_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.135000</field>
<field name="amount">0.140000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_fr"/>
<field name="account_paid_id" ref="chart1183_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="account_collected_id" ref="chart11832_fr"/>
<field name="account_paid_id" ref="chart11832_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_hst14_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_hst14_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst14_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst14_fr"/>
</record>
<record id="tvh15_purc_fr" model="account.tax.template">
<record id="hst15_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TVH sur les achats - 15%</field>
<field name="description">TVH15_PURC</field>
<field name="type_tax_use">purchase</field>
<field name="amount">0.150000</field>
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1183_fr"/>
<field name="account_paid_id" ref="chart1183_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tvh_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tvh_fr"/>
<field name="account_collected_id" ref="chart11833_fr"/>
<field name="account_paid_id" ref="chart11833_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_hst15_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_hst15_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_hst15_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_hst15_fr"/>
</record>
<!-- GST -->
<record id="tps_purc_fr" model="account.tax.template">
<record id="gst_purc_fr" model="account.tax.template">
<field name="chart_template_id" ref="ca_fr_chart_template_fr"/>
<field name="name">TPS sur les achats - 5%</field>
<field name="description">TPS_PURC</field>
@ -527,10 +503,10 @@
<field name="type">percent</field>
<field name="account_collected_id" ref="chart1181_fr"/>
<field name="account_paid_id" ref="chart1181_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_tps_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_tps_fr"/>
<field name="base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="tax_code_id" ref="vat_code_receivable_gst_fr"/>
<field name="ref_base_code_id" ref="vat_code_base_payable_gst_fr"/>
<field name="ref_tax_code_id" ref="vat_code_receivable_gst_fr"/>
</record>
</data>

View File

@ -0,0 +1,23 @@
;Product/Service is delivered in;;;;;;;;;;;;;
Supplier is in ;Alberta;British Columbia;Manitoba;New Brunswick;"Newfoundland
And Labrador";Nova Scotia;"Northwest
Territories";Nunavut;Ontario;"Prince Edward
Islands";Quebec;Saskatchewan;Yukon;International
Alberta;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
British Columbia;GST 5%;"GST 5%
PST 7%";GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Manitoba;GST 5%;GST 5%;"GST 5%
PST 8%";HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
New Brunswick;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Newfoundland and Labrador;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Nova Scotia;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Northwest Territories;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Nunavut;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Ontario;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Prince Edward Islands;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
Quebec;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;"GST 5%
QST 9,975%";GST 5%;GST 5%;
Saskatchewan;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;"GST 5%
PST 5%";GST 5%;
Yukon;GST 5%;GST 5%;GST 5%;HST 13%;HST 13%;HST 15%;GST 5%;GST 5%;HST 13%;HST 14%;GST 5%;GST 5%;GST 5%;
International;;;;;;;;;;;;;;
1 Product/Service is delivered in
2 Supplier is in Alberta British Columbia Manitoba New Brunswick Newfoundland And Labrador Nova Scotia Northwest Territories Nunavut Ontario Prince Edward Islands Quebec Saskatchewan Yukon International
3 Alberta GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
4 British Columbia GST – 5% GST – 5% PST – 7% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
5 Manitoba GST – 5% GST – 5% GST – 5% PST – 8% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
6 New Brunswick GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
7 Newfoundland and Labrador GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
8 Nova Scotia GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
9 Northwest Territories GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
10 Nunavut GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
11 Ontario GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
12 Prince Edward Islands GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
13 Quebec GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% QST – 9,975% GST – 5% GST – 5%
14 Saskatchewan GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% PST – 5% GST – 5%
15 Yukon GST – 5% GST – 5% GST – 5% HST – 13% HST – 13% HST – 15% GST – 5% GST – 5% HST – 13% HST – 14% GST – 5% GST – 5% GST – 5%
16 International

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -978,7 +978,7 @@
<field name="parent_id" ref="chart222020000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie naliczonego VAT-22%</field>
<field name="name">Rozliczenie naliczonego VAT-23%</field>
</record>
<record id="chart222020200" model="account.account.template">
@ -987,7 +987,16 @@
<field name="parent_id" ref="chart222020000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie naliczonego VAT-7%</field>
<field name="name">Rozliczenie naliczonego VAT-8%</field>
</record>
<record id="chart222020400" model="account.account.template">
<field name="code">222020400</field>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="chart222020000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie naliczonego VAT-5%</field>
</record>
<record id="chart222020300" model="account.account.template">
@ -1014,7 +1023,7 @@
<field name="parent_id" ref="chart222030000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie należnego VAT-22%</field>
<field name="name">Rozliczenie należnego VAT-23%</field>
</record>
<record id="chart222030200" model="account.account.template">
@ -1023,7 +1032,16 @@
<field name="parent_id" ref="chart222030000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie należnego VAT-7%</field>
<field name="name">Rozliczenie należnego VAT-8%</field>
</record>
<record id="chart222030400" model="account.account.template">
<field name="code">222030400</field>
<field name="reconcile" eval="False"/>
<field name="parent_id" ref="chart222030000"/>
<field name="type">other</field>
<field name="user_type" ref="account_type_cash"/>
<field name="name">Rozliczenie należnego VAT-5%</field>
</record>
<record id="chart222030300" model="account.account.template">
@ -3176,15 +3194,15 @@
<!-- Chart template -->
<record id="pl_chart_template" model="account.chart.template">
<field name="name">Polska - Plan kont</field>
<field name="account_root_id" ref="chart0"/>
<field name="tax_code_root_id" ref="vat_code_tax"/>
<field name="bank_account_view_id" ref="chart113010000"/>
<field name="property_account_receivable" ref="chart220000000"/>
<field name="name">Polska - Plan kont</field>
<field name="account_root_id" ref="chart0"/>
<field name="tax_code_root_id" ref="vat_code_tax"/>
<field name="bank_account_view_id" ref="chart113010000"/>
<field name="property_account_receivable" ref="chart220000000"/>
<field name="property_account_payable" ref="chart221000000"/>
<field name="property_account_expense_categ" ref="chart330020000"/>
<field name="property_account_income_categ" ref="chart773010000"/>
</record>
</data>
</openerp>
</openerp>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="tax1" model="account.tax.template">
<record id="tax_vat_23_due" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT-22%(22.0%)</field>
<field name="amount">0.220000</field>
<field name="name">VAT-23%(23.0%)</field>
<field name="amount">0.230000</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="account_collected_id" ref="chart222030100"/>
@ -16,10 +16,10 @@
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax2" model="account.tax.template">
<record id="tax_vat_8_due" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT-7%(7.0%)</field>
<field name="amount">0.070000</field>
<field name="name">VAT-8%(8.0%)</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="account_collected_id" ref="chart222030200"/>
@ -31,7 +31,22 @@
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax3" model="account.tax.template">
<record id="tax_vat_5_due" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT-5%(5.0%)</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="account_collected_id" ref="chart222030400"/>
<field name="account_paid_id" ref="chart222030400"/>
<field name="base_code_id" ref="vat_code_base_due"/>
<field name="tax_code_id" ref="vat_code_due_tva"/>
<field name="ref_base_code_id" ref="vat_code_base_due"/>
<field name="ref_tax_code_id" ref="vat_code_due_tva"/>
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax_vat_0_due" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT-0%(0.0%)</field>
<field name="amount">0.000000</field>
@ -46,10 +61,11 @@
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax4" model="account.tax.template">
<record id="tax_vat_23_recivable" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT naliczony-22%(22.0%)</field>
<field name="amount">0.220000</field>
<field name="name">VAT naliczony-23%(23.0%)</field>
<field name="amount">0.230000</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="chart222020100"/>
@ -61,10 +77,10 @@
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax5" model="account.tax.template">
<record id="tax_vat_8_recivable" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT naliczony-7%(7.0%)</field>
<field name="amount">0.070000</field>
<field name="name">VAT naliczony-8%(8.0%)</field>
<field name="amount">0.080000</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="chart222020200"/>
@ -76,7 +92,22 @@
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax6" model="account.tax.template">
<record id="tax_vat_5_recivable" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT naliczony-5%(5.0%)</field>
<field name="amount">0.050000</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_collected_id" ref="chart222020400"/>
<field name="account_paid_id" ref="chart222020200"/>
<field name="base_code_id" ref="vat_code_receivable_net"/>
<field name="tax_code_id" ref="vat_code_payable"/>
<field name="ref_base_code_id" ref="vat_code_receivable_net"/>
<field name="ref_tax_code_id" ref="vat_code_payable"/>
<field name="ref_base_sign" eval="-1"/>
<field name="ref_tax_sign" eval="-1"/>
</record>
<record id="tax_vat_0_recivable" model="account.tax.template">
<field name="chart_template_id" ref="pl_chart_template"/>
<field name="name">VAT naliczony-0%(0.0%)</field>
<field name="amount">0.000000</field>
@ -92,4 +123,4 @@
<field name="ref_tax_sign" eval="-1"/>
</record>
</data>
</openerp>
</openerp>

View File

@ -327,6 +327,7 @@ class mail_mail(osv.Model):
email_list.append(self.send_get_email_dict(cr, uid, mail, partner=partner, context=context))
# build an RFC2822 email.message.Message object and send it without queuing
res = None
for email in email_list:
msg = ir_mail_server.build_email(
email_from = mail.email_from,

View File

@ -77,9 +77,9 @@ Dashboard / Reports for MRP will include:
#TODO: This yml tests are needed to be completely reviewed again because the product wood panel is removed in product demo as it does not suit for new demo context of computer and consultant company
# so the ymls are too complex to change at this stage
'test': [
# 'test/order_demo.yml',
# 'test/order_process.yml',
# 'test/cancel_order.yml',
'test/order_demo.yml',
'test/order_process.yml',
'test/cancel_order.yml',
],
'installable': True,
'application': True,

View File

@ -23,11 +23,12 @@ import time
from datetime import datetime
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv
from openerp.osv import fields, osv, orm
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP
from openerp.tools import float_compare
from openerp.tools.translate import _
from openerp import tools
from openerp import SUPERUSER_ID
#----------------------------------------------------------
# Work Centers
@ -405,12 +406,20 @@ class mrp_production(osv.osv):
return result
def _src_id_default(self, cr, uid, ids, context=None):
src_location_id = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock', context=context)
return src_location_id.id
try:
location_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock')
self.pool.get('stock.location').check_access_rule(cr, uid, [location_id], 'read', context=context)
except (orm.except_orm, ValueError):
location_id = False
return location_id
def _dest_id_default(self, cr, uid, ids, context=None):
dest_location_id = self.pool.get('ir.model.data').get_object(cr, uid, 'stock', 'stock_location_stock', context=context)
return dest_location_id.id
try:
location_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock')
self.pool.get('stock.location').check_access_rule(cr, uid, [location_id], 'read', context=context)
except (orm.except_orm, ValueError):
location_id = False
return location_id
def _get_progress(self, cr, uid, ids, name, arg, context=None):
""" Return product quantity percentage """
@ -605,8 +614,12 @@ class mrp_production(osv.osv):
prod_line_obj = self.pool.get('mrp.production.product.line')
workcenter_line_obj = self.pool.get('mrp.production.workcenter.line')
for production in self.browse(cr, uid, ids):
cr.execute('delete from mrp_production_product_line where production_id=%s', (production.id,))
cr.execute('delete from mrp_production_workcenter_line where production_id=%s', (production.id,))
p_ids = prod_line_obj.search(cr, SUPERUSER_ID, [('production_id', '=', production.id)], context=context)
prod_line_obj.unlink(cr, SUPERUSER_ID, p_ids, context=context)
w_ids = workcenter_line_obj.search(cr, SUPERUSER_ID, [('production_id', '=', production.id)], context=context)
workcenter_line_obj.unlink(cr, SUPERUSER_ID, w_ids, context=context)
bom_point = production.bom_id
bom_id = production.bom_id.id
if not bom_point:
@ -872,7 +885,7 @@ class mrp_production(osv.osv):
'move_id': shipment_move_id,
'company_id': production.company_id.id,
})
self.signal_button_confirm(cr, uid, [procurement_id])
procurement_order.signal_button_confirm(cr, uid, [procurement_id])
return procurement_id
def _make_production_internal_shipment_line(self, cr, uid, production_line, shipment_id, parent_move_id, destination_location_id=False, context=None):

View File

@ -619,8 +619,8 @@
<form string="Manufacturing Orders" version="7.0">
<header>
<button name="button_confirm" states="draft" string="Confirm Production" class="oe_highlight"/>
<button name="%(act_mrp_product_produce)d" states="confirmed,ready,in_production" string="Produce" type="action" class="oe_highlight"/>
<button name="force_production" states="confirmed" string="Force Reservation" type="object"/>
<button name="%(act_mrp_product_produce)d" states="ready,in_production" string="Produce" type="action" class="oe_highlight"/>
<button name="force_production" states="confirmed" string="Force Reservation" type="object" class="oe_highlight"/>
<button name="force_production" states="picking_except" string="Force Reservation" type="object"/>
<button name="button_produce" states="ready" string="Mark as Started"/>
<button name="button_recreate" states="picking_except" string="Recreate Picking"/>

View File

@ -94,6 +94,11 @@
procurement_ids = procurement.search(cr, uid, [('move_id','=',move_line.id)])
assert procurement_ids, "Procurement should be created for shipment line of raw materials."
shipment_procurement = procurement.browse(cr, uid, procurement_ids[0], context=context)
# procurement state should be `confirmed` at this stage, except if mrp_jit is installed, in which
# case it could already be in `running` or `exception` state (not enough stock)
expected_states = ('confirmed', 'running', 'exception')
assert shipment_procurement.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % \
(shipment_procurement.state, shipment_procurement.product_id.name, expected_states)
assert shipment_procurement.date_planned == date_planned, "Planned date is not correspond in procurement."
assert shipment_procurement.product_id.id == order_line.product_id.id, "Product is not correspond in procurement."
assert shipment_procurement.product_qty == order_line.product_qty, "Qty is not correspond in procurement."
@ -157,9 +162,9 @@
scrap_location_id = scrap_location_ids[0]
order = self.browse(cr, uid, ref("mrp_production_test1"))
for move in order.move_lines:
move.action_consume(move.product_qty)
if move.product_id.id == ref("product.product_product_6"):
move.action_scrap(5.0, scrap_location_id)
move.action_consume(move.product_qty)
-
I produce product.
-

View File

@ -111,7 +111,8 @@ class pos_config(osv.osv):
return result
def _default_sale_journal(self, cr, uid, context=None):
res = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale')], limit=1)
company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
res = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', company_id)], limit=1, context=context)
return res and res[0] or False
def _default_warehouse(self, cr, uid, context=None):

View File

@ -290,7 +290,7 @@
<record id="peche" model="product.product">
<field name="available_in_pos">True</field>
<field name="list_price">5.10</field>
<field name="name">Fishing</field>
<field name="name">Peaches</field>
<field name="to_weight">True</field>
<field name="ean13">2300001000008</field>
<field name="pos_categ_id" ref="rouges_noyau_fruits"/>

View File

@ -12,6 +12,8 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
this.weight = 0;
this.weighting = false;
this.debug_weight = 0;
this.use_debug_weight = false;
this.paying = false;
this.default_payment_status = {
@ -92,38 +94,36 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
// and a weighting_end()
weighting_read_kg: function(){
var self = this;
if(this.bypass_proxy){
return this.weight;
}else{
this.message('weighting_read_kg',{})
.done(function(weight){
if(self.weighting && !self.bypass_proxy){
this.message('weighting_read_kg',{})
.done(function(weight){
if(self.weighting){
if(self.use_debug_weight){
self.weight = self.debug_weight;
}else{
self.weight = weight;
}
});
return this.weight;
}
}
});
return this.weight;
},
// sets a custom weight, ignoring the proxy returned value.
debug_set_weight: function(kg){
this.bypass_proxy = true;
this.weight = kg;
this.use_debug_weight = true;
this.debug_weight = kg;
},
// resets the custom weight and re-enable listening to the proxy for weight values
debug_reset_weight: function(){
this.bypass_proxy = false;
this.weight = 0;
this.use_debug_weight = false;
this.debug_weight = 0;
},
// the client has finished weighting products
weighting_end: function(){
if(!this.bypass_proxy){
this.weight = 0;
this.weighting = false;
this.message('weighting_end');
}
this.weight = 0;
this.weighting = false;
this.message('weighting_end');
},
// the pos asks the client to pay 'price' units

View File

@ -234,8 +234,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
on_removed_order: function(removed_order){
if( this.get('orders').isEmpty()){
this.add_new_order();
}
if( this.get('selectedOrder') === removed_order){
}else{
this.set({ selectedOrder: this.get('orders').last() });
}
},

View File

@ -467,7 +467,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
click: function(){
clearInterval(this.intervalID);
self.pos.proxy.weighting_end();
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
}
});
@ -828,7 +827,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
click: function() { self.finishOrder(); },
});
window.print();
this.print();
// THIS IS THE HACK OF THE CENTURY
//

View File

@ -752,6 +752,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
}
});
this.$('.button.reset_weight').click(function(){
self.$('input.weight').val('');
self.pos.proxy.debug_reset_weight();
});
this.$('.button.custom_ean').click(function(){

View File

@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-08-13 05:00+0000\n"
"X-Launchpad-Export-Date: 2013-08-14 04:54+0000\n"
"X-Generator: Launchpad (build 16723)\n"
#. module: project

View File

@ -742,7 +742,8 @@ class task(osv.osv):
" * Blocked indicates something is preventing the progress of this task\n"
" * Ready for next stage indicates the task is ready to be pulled to the next stage",
readonly=True, required=False),
'create_date': fields.datetime('Create Date', readonly=True,select=True),
'create_date': fields.datetime('Create Date', readonly=True, select=True),
'write_date': fields.datetime('Last Modification Date', readonly=True, select=True), #not displayed in the view but it might be useful with base_action_rule module (and it needs to be defined first for that)
'date_start': fields.datetime('Starting Date',select=True),
'date_end': fields.datetime('Ending Date',select=True),
'date_deadline': fields.date('Deadline',select=True),

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