[MRG] merge with lp:openobject-addons
bzr revid: tpa@tinyerp.com-20130821054505-l3e9h86gsqa60jp9
|
@ -1 +1,2 @@
|
|||
.*
|
||||
**/node_modules
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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([]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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']);
|
||||
|
||||
};
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"grunt": "*",
|
||||
"grunt-contrib-jshint": "*"
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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();
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
})();
|
|
@ -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);
|
||||
}
|
||||
|
||||
})();
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory": "static/lib/"
|
||||
}
|
|
@ -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']);
|
||||
|
||||
};
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"grunt": "*",
|
||||
"grunt-contrib-jshint": "*"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 74 B |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 830 B |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 100 KiB |
|
@ -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);
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<templates>
|
||||
<t t-name="chatButton">
|
||||
<t t-esc="widget.text"/>
|
||||
</t>
|
||||
</templates>
|
|
@ -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;
|
||||
});
|
||||
|
|
|
@ -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>
|
|
@ -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>");
|
|
@ -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;
|
||||
};
|
||||
})();
|
|
@ -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;
|
||||
|
||||
});
|
|
@ -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))
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
if (attribute) {
|
||||
s = s.replace(/"/g, '"');
|
||||
}
|
||||
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;
|
||||
|
||||
})();
|
|
@ -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));
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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):
|
||||
|
|
|
@ -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',
|
||||
],
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;;;;;;;;;;;;;;
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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.
|
||||
-
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() });
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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(){
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|