[MERGE] from saas-3
bzr revid: chm@openerp.com-20140212095425-ew77la0i2wzfzlno
This commit is contained in:
@@ -25,7 +25,7 @@ def fragment_to_query_string(func):
|
||||
return """<html><head><script>
|
||||
var l = window.location;
|
||||
var q = l.hash.substring(1);
|
||||
var r = '/' + l.search;
|
||||
var r = l.pathname + l.search;
|
||||
if(q.length !== 0) {
|
||||
var s = l.search ? (l.search === '?' ? '' : '&') : '?';
|
||||
r = l.pathname + l.search + s + q;
|
||||
|
||||
@@ -62,7 +62,7 @@ class AuthSignup(openerp.addons.web.controllers.main.Home):
|
||||
}
|
||||
qcontext.update(config)
|
||||
|
||||
if 'error' in qcontext or mode not in ('reset', 'signup') or (not token and not config[mode]):
|
||||
if 'error' in request.params or mode not in ('reset', 'signup') or (not token and not config[mode]):
|
||||
if isinstance(super_response, LazyResponse):
|
||||
super_response.params['values'].update(config)
|
||||
return super_response
|
||||
@@ -85,15 +85,20 @@ class AuthSignup(openerp.addons.web.controllers.main.Home):
|
||||
values = dict((key, qcontext.get(key)) for key in ('login', 'name', 'password'))
|
||||
try:
|
||||
self._signup_with_values(token, values)
|
||||
request.cr.commit()
|
||||
redirect = request.params.get('redirect')
|
||||
if not redirect:
|
||||
redirect = '/web?' + request.httprequest.query_string
|
||||
return http.redirect_with_hash(redirect)
|
||||
except SignupError, e:
|
||||
qcontext['error'] = exception_to_unicode(e)
|
||||
return super(AuthSignup, self).web_login(*args, **kw)
|
||||
|
||||
return response
|
||||
|
||||
def _signup_with_values(self, token, values):
|
||||
request.registry['res.users'].signup(request.cr, openerp.SUPERUSER_ID, values, token)
|
||||
db, login, password = request.registry['res.users'].signup(request.cr, openerp.SUPERUSER_ID, values, token)
|
||||
uid = request.session.authenticate(db, login, password)
|
||||
if uid is not False:
|
||||
raise SignupError(_('Authentification Failed.'))
|
||||
|
||||
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<div class="form-group field-login">
|
||||
<label for="login" class="control-label">Your Email</label>
|
||||
<input type="text" name="login" t-att-value="login" id="login" class="form-control"
|
||||
<input type="email" name="login" t-att-value="login" id="login" class="form-control"
|
||||
t-att-autofocus="'autofocus' if reset_without_token else None"
|
||||
required="required" t-att-disabled="'disabled' if mode == 'reset' and token else None"/>
|
||||
<input type="hidden" name="login" t-att-value="login" t-if="mode == 'reset' and token"/>
|
||||
|
||||
+11
-6
@@ -120,14 +120,14 @@ class crm_case_section(osv.osv):
|
||||
month_begin = date.today().replace(day=1)
|
||||
section_result = [{
|
||||
'value': 0,
|
||||
'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B'),
|
||||
'tooltip': (month_begin + relativedelta.relativedelta(months=-i)).strftime('%B %Y'),
|
||||
} for i in range(self._period_number - 1, -1, -1)]
|
||||
group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context)
|
||||
pattern = tools.DEFAULT_SERVER_DATE_FORMAT if obj.fields_get(cr, uid, groupby_field)[groupby_field]['type'] == 'date' else tools.DEFAULT_SERVER_DATETIME_FORMAT
|
||||
for group in group_obj:
|
||||
group_begin_date = datetime.strptime(group['__domain'][0][2], pattern)
|
||||
month_delta = relativedelta.relativedelta(month_begin, group_begin_date)
|
||||
section_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group_begin_date.strftime('%B')}
|
||||
section_result[self._period_number - (month_delta.months + 1)] = {'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field, 0)}
|
||||
return section_result
|
||||
|
||||
def _get_opportunities_data(self, cr, uid, ids, field_name, arg, context=None):
|
||||
@@ -140,13 +140,18 @@ class crm_case_section(osv.osv):
|
||||
month_begin = date.today().replace(day=1)
|
||||
date_begin = month_begin - relativedelta.relativedelta(months=self._period_number - 1)
|
||||
date_end = month_begin.replace(day=calendar.monthrange(month_begin.year, month_begin.month)[1])
|
||||
date_domain = [('create_date', '>=', date_begin.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)), ('create_date', '<=', date_end.strftime(tools.DEFAULT_SERVER_DATE_FORMAT))]
|
||||
lead_pre_domain = [('create_date', '>=', date_begin.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)),
|
||||
('create_date', '<=', date_end.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)),
|
||||
('type', '=', 'lead')]
|
||||
opp_pre_domain = [('date_deadline', '>=', date_begin.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
('date_deadline', '<=', date_end.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)),
|
||||
('type', '=', 'opportunity')]
|
||||
for id in ids:
|
||||
res[id] = dict()
|
||||
lead_domain = date_domain + [('type', '=', 'lead'), ('section_id', '=', id)]
|
||||
lead_domain = lead_pre_domain + [('section_id', '=', id)]
|
||||
opp_domain = opp_pre_domain + [('section_id', '=', id)]
|
||||
res[id]['monthly_open_leads'] = self.__get_bar_values(cr, uid, obj, lead_domain, ['create_date'], 'create_date_count', 'create_date', context=context)
|
||||
opp_domain = date_domain + [('type', '=', 'opportunity'), ('section_id', '=', id)]
|
||||
res[id]['monthly_planned_revenue'] = self.__get_bar_values(cr, uid, obj, opp_domain, ['planned_revenue', 'create_date'], 'planned_revenue', 'create_date', context=context)
|
||||
res[id]['monthly_planned_revenue'] = self.__get_bar_values(cr, uid, obj, opp_domain, ['planned_revenue', 'date_deadline'], 'planned_revenue', 'date_deadline', context=context)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
|
||||
@@ -65,9 +65,9 @@
|
||||
<record id="action_report_crm_lead_salesteam" model="ir.actions.act_window">
|
||||
<field name="name">Leads Analysis</field>
|
||||
<field name="res_model">crm.lead.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{"search_default_month":1}</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="crm.view_report_crm_lead_graph_two"/>
|
||||
<field name="domain">[('type','=', 'lead'),('section_id', '=', active_id)]</field>
|
||||
<field name="help">Leads Analysis allows you to check different CRM related information like the treatment delays or number of leads per state. You can sort out your leads analysis by different groups to get accurate grained analysis.</field>
|
||||
</record>
|
||||
@@ -75,9 +75,8 @@
|
||||
<record id="action_report_crm_opportunity_salesteam" model="ir.actions.act_window">
|
||||
<field name="name">Opportunities Analysis</field>
|
||||
<field name="res_model">crm.lead.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{"search_default_month":1}</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="crm.view_report_crm_opportunity_graph"/>
|
||||
<field name="domain">[('type','=', 'opportunity'), ('section_id', '=', active_id)]</field>
|
||||
<field name="help">Opportunities Analysis gives you an instant access to your opportunities with information such as the expected revenue, planned cost, missed deadlines or the number of interactions per opportunity. This report is mainly used by the sales manager in order to do the periodic review with the teams of the sales pipeline.</field>
|
||||
</record>
|
||||
@@ -119,14 +118,14 @@
|
||||
<a name="%(crm_case_form_view_salesteams_lead)d" type="action">Leads</a>
|
||||
<a name="%(action_report_crm_lead_salesteam)d" type="action" class="oe_sparkline_bar_link">
|
||||
<field name="monthly_open_leads" widget="sparkline_bar"
|
||||
options="{'height': '20px', 'barWidth': 4, 'barSpacing': 1, 'delayIn': '3000', 'tooltip_suffix': 'Leads'}">Open Leads per Month<br/>Click to see a detailed analysis of leads.</field>
|
||||
options="{'height': '20px', 'barWidth': 4, 'barSpacing': 1, 'delayIn': '3000', 'tooltip_suffix': ' Leads'}">Open Leads per Month<br/>Click to see a detailed analysis of leads.</field>
|
||||
</a>
|
||||
</div>
|
||||
<div class="oe_salesteams_opportunities">
|
||||
<a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">Opportunities</a>
|
||||
<a name="%(action_report_crm_opportunity_salesteam)d" type="action">
|
||||
<field name="monthly_planned_revenue" widget="sparkline_bar"
|
||||
options="{'height': '20px', 'barWidth': '4', 'barSpacing': '1', 'delayIn': '3000', 'tooltip_suffix': 'Opportunities'}">Planned Revenue per Month<br/>Click to see a detailed analysis of opportunities.</field>
|
||||
options="{'height': '20px', 'barWidth': '4', 'barSpacing': '1', 'delayIn': '3000', 'tooltip_suffix': ' (Planned Revenue)'}">Planned Revenue per Month<br/>Click to see a detailed analysis of opportunities.</field>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -89,10 +89,6 @@ class crm_lead_report(osv.osv):
|
||||
id,
|
||||
c.date_deadline,
|
||||
|
||||
to_char(c.create_date, 'YYYY') as creation_year,
|
||||
to_char(c.create_date, 'MM') as creation_month,
|
||||
to_char(c.create_date, 'YYYY-MM-DD') as creation_day,
|
||||
|
||||
to_char(c.date_open, 'YYYY-MM-DD') as opening_date,
|
||||
to_char(c.date_closed, 'YYYY-mm-dd') as date_closed,
|
||||
|
||||
|
||||
@@ -15,6 +15,17 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_crm_lead_graph_two" model="ir.ui.view">
|
||||
<field name="name">crm.lead.report.graph.two</field>
|
||||
<field name="model">crm.lead.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Leads Analysis" type="pivot" stacked="True">
|
||||
<field name="create_date" type="row"/>
|
||||
<field name="user_id" type="col"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_report_crm_opportunity_graph" model="ir.ui.view">
|
||||
<field name="name">crm.opportunity.report.graph</field>
|
||||
<field name="model">crm.lead.report</field>
|
||||
@@ -23,7 +34,7 @@
|
||||
<field name="date_deadline" type="row"/>
|
||||
<field name="user_id" type="col"/>
|
||||
<field name="stage_id" type="col"/>
|
||||
<field name="probable_revenue" type="measure"/>
|
||||
<field name="planned_revenue" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -84,7 +95,7 @@
|
||||
<filter string="Creation date (week)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:week'}"/>
|
||||
<filter string="Creation date (month)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:month'}"/>
|
||||
domain="[]" context="{'group_by':'create_date:month'}" name="month"/>
|
||||
<filter string="Creation date (year)" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'create_date:year'}"/>
|
||||
<separator orientation="vertical" />
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
<label for="number_of_days_temp" string="Duration"/>
|
||||
<div>
|
||||
<group col="3" attrs="{'invisible': [('type', '=', 'add')]}">
|
||||
<field name="date_from" nolabel="1" on_change="onchange_date_from(date_to, date_from)" required="1" class="oe_inline"/><label string="-" class="oe_inline"/>
|
||||
<field name="date_to" nolabel="1" on_change="onchange_date_to(date_to, date_from)" required="1" class="oe_inline"/>
|
||||
<field name="date_from" nolabel="1" on_change="onchange_date_from(date_to, date_from)" attrs="{'required':[('type', '=', 'remove')]}" class="oe_inline"/><label string="-" class="oe_inline"/>
|
||||
<field name="date_to" nolabel="1" on_change="onchange_date_to(date_to, date_from)" attrs="{'required':[('type', '=', 'remove')]}" class="oe_inline"/>
|
||||
</group>
|
||||
<div>
|
||||
<field name="number_of_days_temp" class="oe_inline"/> days
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import commands
|
||||
import logging
|
||||
import simplejson
|
||||
import os
|
||||
@@ -11,7 +12,7 @@ import math
|
||||
import md5
|
||||
import openerp.addons.hw_proxy.controllers.main as hw_proxy
|
||||
import subprocess
|
||||
from threading import Thread
|
||||
from threading import Thread, Lock
|
||||
from Queue import Queue, Empty
|
||||
|
||||
try:
|
||||
@@ -39,6 +40,7 @@ class EscposDriver(Thread):
|
||||
def __init__(self):
|
||||
Thread.__init__(self)
|
||||
self.queue = Queue()
|
||||
self.lock = Lock()
|
||||
self.status = {'status':'connecting', 'messages':[]}
|
||||
|
||||
def connected_usb_devices(self):
|
||||
@@ -47,6 +49,13 @@ class EscposDriver(Thread):
|
||||
if usb.core.find(idVendor=device['vendor'], idProduct=device['product']) != None:
|
||||
connected.append(device)
|
||||
return connected
|
||||
|
||||
def lockedstart(self):
|
||||
self.lock.acquire()
|
||||
if not self.isAlive():
|
||||
self.daemon = True
|
||||
self.start()
|
||||
self.lock.release()
|
||||
|
||||
def get_escpos_printer(self):
|
||||
try:
|
||||
@@ -105,6 +114,8 @@ class EscposDriver(Thread):
|
||||
elif task == 'cashbox':
|
||||
if timestamp >= time.time() - 12:
|
||||
self.open_cashbox(printer)
|
||||
elif task == 'printstatus':
|
||||
self.print_status(printer)
|
||||
elif task == 'status':
|
||||
pass
|
||||
|
||||
@@ -113,10 +124,31 @@ class EscposDriver(Thread):
|
||||
_logger.error(e);
|
||||
|
||||
def push_task(self,task, data = None):
|
||||
if not self.isAlive():
|
||||
self.start()
|
||||
self.lockedstart()
|
||||
self.queue.put((time.time(),task,data))
|
||||
|
||||
def print_status(self,eprint):
|
||||
localips = ['0.0.0.0','127.0.0.1','127.0.1.1']
|
||||
ips = [ c.split(':')[1].split(' ')[0] for c in commands.getoutput("/sbin/ifconfig").split('\n') if 'inet addr' in c ]
|
||||
ips = [ ip for ip in ips if ip not in localips ]
|
||||
eprint.text('\n\n')
|
||||
eprint.set(align='center',type='b',height=2,width=2)
|
||||
eprint.text('PosBox Status\n')
|
||||
eprint.text('\n')
|
||||
eprint.set(align='center')
|
||||
|
||||
if len(ips) == 0:
|
||||
eprint.text('ERROR: Could not connect to LAN\n\nPlease check that the PosBox is correc-\ntly connected with a network cable,\n that the LAN is setup with DHCP, and\nthat network addresses are available')
|
||||
elif len(ips) == 1:
|
||||
eprint.text('IP Address\n'+ips[0]+'\n')
|
||||
else:
|
||||
eprint.text('IP Addresses\n')
|
||||
for ip in ips:
|
||||
eprint.text(ip+'\n')
|
||||
|
||||
eprint.text('\n\n')
|
||||
eprint.cut()
|
||||
|
||||
def print_receipt_body(self,eprint,receipt):
|
||||
|
||||
def check(string):
|
||||
@@ -134,7 +166,6 @@ class EscposDriver(Thread):
|
||||
else:
|
||||
return str(amount)
|
||||
|
||||
|
||||
def printline(left, right='', width=40, ratio=0.5, indent=0):
|
||||
lwidth = int(width * ratio)
|
||||
rwidth = width - lwidth
|
||||
@@ -157,6 +188,7 @@ class EscposDriver(Thread):
|
||||
|
||||
# Receipt Header
|
||||
if receipt['company']['logo']:
|
||||
eprint.set(align='center')
|
||||
eprint.print_base64_image(receipt['company']['logo'])
|
||||
eprint.text('\n')
|
||||
else:
|
||||
@@ -245,6 +277,8 @@ class EscposDriver(Thread):
|
||||
driver = EscposDriver()
|
||||
|
||||
hw_proxy.drivers['escpos'] = driver
|
||||
|
||||
driver.push_task('printstatus')
|
||||
|
||||
class EscposProxy(hw_proxy.Proxy):
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
import time
|
||||
from os import listdir
|
||||
from os.path import join
|
||||
from threading import Thread
|
||||
from threading import Thread, Lock
|
||||
from select import select
|
||||
from Queue import Queue, Empty
|
||||
|
||||
@@ -26,6 +26,7 @@ except ImportError:
|
||||
class Scanner(Thread):
|
||||
def __init__(self):
|
||||
Thread.__init__(self)
|
||||
self.lock = Lock()
|
||||
self.status = {'status':'connecting', 'messages':[]}
|
||||
self.input_dir = '/dev/input/by-id/'
|
||||
self.barcodes = Queue()
|
||||
@@ -86,6 +87,12 @@ class Scanner(Thread):
|
||||
57:(" "," "),
|
||||
}
|
||||
|
||||
def lockedstart(self):
|
||||
self.lock.acquire()
|
||||
if not self.isAlive():
|
||||
self.start()
|
||||
self.lock.release()
|
||||
|
||||
def set_status(self, status, message = None):
|
||||
if status == self.status['status']:
|
||||
if message != None and message != self.status['messages'][-1]:
|
||||
@@ -102,8 +109,6 @@ class Scanner(Thread):
|
||||
elif status == 'disconnected' and message:
|
||||
_logger.warning('Disconnected Barcode Scanner: '+message)
|
||||
|
||||
|
||||
|
||||
def get_device(self):
|
||||
try:
|
||||
if not evdev:
|
||||
@@ -135,6 +140,8 @@ class Scanner(Thread):
|
||||
busy reading another barcode
|
||||
"""
|
||||
|
||||
self.lockedstart()
|
||||
|
||||
while True:
|
||||
try:
|
||||
timestamp, barcode = self.barcodes.get(True, 5)
|
||||
@@ -144,8 +151,7 @@ class Scanner(Thread):
|
||||
return ''
|
||||
|
||||
def get_status(self):
|
||||
if not s.isAlive():
|
||||
s.start()
|
||||
self.lockedstart()
|
||||
return self.status
|
||||
|
||||
def run(self):
|
||||
@@ -209,7 +215,6 @@ hw_proxy.drivers['scanner'] = s
|
||||
class ScannerDriver(hw_proxy.Proxy):
|
||||
@http.route('/hw_proxy/scanner', type='json', auth='none', cors='*')
|
||||
def scanner(self):
|
||||
if not s.isAlive():
|
||||
s.start()
|
||||
return s.get_barcode()
|
||||
|
||||
|
||||
|
||||
@@ -162,25 +162,37 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
},
|
||||
|
||||
// find a proxy and connects to it. for options see find_proxy
|
||||
// - force_ip : only try to connect to the specified ip.
|
||||
// - port: what port to listen to (default 8069)
|
||||
// - progress(fac) : callback for search progress ( fac in [0,1] )
|
||||
autoconnect: function(options){
|
||||
var self = this;
|
||||
this.set_connection_status('connecting',{});
|
||||
var found_url = new $.Deferred();
|
||||
var success = new $.Deferred();
|
||||
this.find_proxy(options)
|
||||
.then(function(proxies){
|
||||
if(proxies.length > 0){
|
||||
self.connect(proxies[0])
|
||||
.then(function(){
|
||||
success.resolve();
|
||||
},function(){
|
||||
self.set_connection_status('disconnected');
|
||||
success.reject();
|
||||
});
|
||||
}else{
|
||||
self.set_connection_status('disconnected');
|
||||
success.reject();
|
||||
}
|
||||
|
||||
if ( options.force_ip ){
|
||||
// if the ip is forced by server config, bailout on fail
|
||||
found_url = this.try_hard_to_connect(options.force_ip, options)
|
||||
}else if( localStorage['hw_proxy_url'] ){
|
||||
// try harder when we remember a good proxy url
|
||||
found_url = this.try_hard_to_connect(localStorage['hw_proxy_url'], options)
|
||||
.then(null,function(){
|
||||
return self.find_proxy(options);
|
||||
});
|
||||
}else{
|
||||
// just find something quick
|
||||
found_url = this.find_proxy(options);
|
||||
}
|
||||
|
||||
success = found_url.then(function(url){
|
||||
return self.connect(url);
|
||||
});
|
||||
|
||||
success.fail(function(){
|
||||
self.set_connection_status('disconnected');
|
||||
});
|
||||
|
||||
return success;
|
||||
},
|
||||
|
||||
@@ -217,10 +229,50 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
}
|
||||
},
|
||||
|
||||
// returns as a deferred a list of valid hosts urls that can be used as proxy.
|
||||
// try several time to connect to a known proxy url
|
||||
try_hard_to_connect: function(url,options){
|
||||
options = options || {};
|
||||
var port = ':' + (options.port || '8069');
|
||||
|
||||
this.set_connection_status('connecting');
|
||||
|
||||
if(url.indexOf('//') < 0){
|
||||
url = 'http://'+url;
|
||||
}
|
||||
|
||||
if(url.indexOf(':',5) < 0){
|
||||
url = url+port;
|
||||
}
|
||||
|
||||
// try real hard to connect to url, with a 1sec timeout and up to 'retries' retries
|
||||
function try_real_hard_to_connect(url, retries, done){
|
||||
|
||||
done = done || new $.Deferred();
|
||||
|
||||
var c = $.ajax({
|
||||
url: url + '/hw_proxy/hello',
|
||||
method: 'GET',
|
||||
timeout: 1000,
|
||||
})
|
||||
.done(function(){
|
||||
done.resolve(url);
|
||||
})
|
||||
.fail(function(){
|
||||
if(retries > 0){
|
||||
try_real_hard_to_connect(url,retries-1,done);
|
||||
}else{
|
||||
done.reject();
|
||||
}
|
||||
});
|
||||
return done;
|
||||
}
|
||||
|
||||
return try_real_hard_to_connect(url,3);
|
||||
},
|
||||
|
||||
// returns as a deferred a valid host url that can be used as proxy.
|
||||
// options:
|
||||
// - port: what port to listen to (default 8069)
|
||||
// - force_ip : limit the search to the specified ip
|
||||
// - progress(fac) : callback for search progress ( fac in [0,1] )
|
||||
find_proxy: function(options){
|
||||
options = options || {};
|
||||
@@ -228,36 +280,17 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
var port = ':' + (options.port || '8069');
|
||||
var urls = [];
|
||||
var found = false;
|
||||
var proxies = [];
|
||||
var done = new $.Deferred();
|
||||
var parallel = 8;
|
||||
var done = new $.Deferred(); // will be resolved with the proxies valid urls
|
||||
var threads = [];
|
||||
var progress = 0;
|
||||
|
||||
this.set_connection_status('connecting');
|
||||
|
||||
if(options.force_ip){
|
||||
var url = options.force_ip;
|
||||
if(url.indexOf('//') < 0){
|
||||
url = 'http://'+url;
|
||||
}
|
||||
if(url.indexOf(':',5) < 0){
|
||||
url = url+port;
|
||||
}
|
||||
urls.push(url);
|
||||
}else{
|
||||
if(localStorage['hw_proxy_url']){
|
||||
urls.push(localStorage['hw_proxy_url']);
|
||||
}
|
||||
|
||||
urls.push('http://localhost'+port);
|
||||
|
||||
for(var i = 0; i < 256; i++){
|
||||
urls.push('http://192.168.0.'+i+port);
|
||||
urls.push('http://192.168.1.'+i+port);
|
||||
urls.push('http://192.168.2.'+i+port);
|
||||
urls.push('http://10.0.0.'+i+port);
|
||||
}
|
||||
urls.push('http://localhost'+port);
|
||||
for(var i = 0; i < 256; i++){
|
||||
urls.push('http://192.168.0.'+i+port);
|
||||
urls.push('http://192.168.1.'+i+port);
|
||||
urls.push('http://10.0.0.'+i+port);
|
||||
}
|
||||
|
||||
var prog_inc = 1/urls.length;
|
||||
@@ -269,40 +302,39 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
}
|
||||
}
|
||||
|
||||
function thread(url,done){
|
||||
if(!url){
|
||||
function thread(done){
|
||||
var url = urls.shift();
|
||||
|
||||
done = done || new $.Deferred();
|
||||
|
||||
if( !url || found || !self.searching_for_proxy ){
|
||||
done.resolve();
|
||||
return done;
|
||||
}
|
||||
|
||||
var c = $.ajax({
|
||||
url: url + '/hw_proxy/hello',
|
||||
method: 'GET',
|
||||
timeout: 300,
|
||||
timeout: 400,
|
||||
}).done(function(){
|
||||
found = true;
|
||||
update_progress();
|
||||
proxies.push(url);
|
||||
done.resolve(url);
|
||||
})
|
||||
.fail(function(){
|
||||
update_progress();
|
||||
var next_url = urls.shift();
|
||||
if(found ||! self.searching_for_proxy || !next_url){
|
||||
done.resolve();
|
||||
}else{
|
||||
thread(next_url,done);
|
||||
}
|
||||
thread(done);
|
||||
});
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
this.searching_for_proxy = true;
|
||||
|
||||
for(var i = 0; i < Math.min(parallel,urls.length); i++){
|
||||
threads.push(thread(urls.shift(),new $.Deferred()));
|
||||
for(var i = 0, len = Math.min(parallel,urls.length); i < len; i++){
|
||||
threads.push(thread());
|
||||
}
|
||||
|
||||
var done = new $.Deferred();
|
||||
|
||||
$.when.apply($,threads).then(function(){
|
||||
var urls = [];
|
||||
for(var i = 0; i < arguments.length; i++){
|
||||
@@ -310,7 +342,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
urls.push(arguments[i]);
|
||||
}
|
||||
}
|
||||
done.resolve(urls);
|
||||
done.resolve(urls[0]);
|
||||
});
|
||||
|
||||
return done;
|
||||
|
||||
@@ -258,8 +258,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||
var total = order ? order.getTotalTaxIncluded() : 0;
|
||||
var taxes = order ? total - order.getTotalTaxExcluded() : 0;
|
||||
|
||||
this.el.querySelector('.summary .total > .value').innerText = this.format_currency(total);
|
||||
this.el.querySelector('.summary .total .subentry .value').innerText = this.format_currency(taxes);
|
||||
this.el.querySelector('.summary .total > .value').textContent = this.format_currency(total);
|
||||
this.el.querySelector('.summary .total .subentry .value').textContent = this.format_currency(taxes);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -635,9 +635,9 @@
|
||||
Shop: <t t-esc="widget.pos.shop.name"/><br />
|
||||
<br />
|
||||
<t t-if="widget.pos.config.receipt_header">
|
||||
<pre>
|
||||
<div style='text-align:center'>
|
||||
<t t-esc="widget.pos.config.receipt_header" />
|
||||
</pre>
|
||||
</div>
|
||||
<br />
|
||||
</t>
|
||||
<table>
|
||||
@@ -711,9 +711,9 @@
|
||||
</table>
|
||||
<t t-if="widget.pos.config.receipt_footer">
|
||||
<br />
|
||||
<pre>
|
||||
<div style='text-align:center'>
|
||||
<t t-esc="widget.pos.config.receipt_footer" />
|
||||
</pre>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -214,8 +214,7 @@
|
||||
<record id="action_order_report_quotation_salesteam" model="ir.actions.act_window">
|
||||
<field name="name">Quotations Analysis</field>
|
||||
<field name="res_model">sale.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="domain">[('state','=','draft'),('section_id', '=', active_id)]</field>
|
||||
<field name="context">{'search_default_order_month':1}</field>
|
||||
<field name="help">This report performs analysis on your quotations. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.</field>
|
||||
@@ -224,8 +223,7 @@
|
||||
<record id="action_order_report_so_salesteam" model="ir.actions.act_window">
|
||||
<field name="name">Sales Analysis</field>
|
||||
<field name="res_model">sale.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="domain">[('state','not in',('draft','sent','cancel')),('section_id', '=', active_id)]</field>
|
||||
<field name="context">{'search_default_order_month':1}</field>
|
||||
<field name="help">This report performs analysis on your sales orders. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.</field>
|
||||
@@ -234,8 +232,7 @@
|
||||
<record id="action_account_invoice_report_salesteam" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Analysis</field>
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,graph</field>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="domain">[('section_id', '=', active_id),('state', 'not in', ['draft', 'cancel'])]</field>
|
||||
<field name="context">{'search_default_month':1}</field>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced to your customer. The tool search can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
|
||||
@@ -304,20 +304,23 @@ ul.nav-stacked > li > a {
|
||||
}
|
||||
|
||||
.carousel .carousel-caption {
|
||||
left: auto;
|
||||
right: auto;
|
||||
bottom: 10%;
|
||||
position: absolute;
|
||||
right: 50%;
|
||||
left: 50%;
|
||||
bottom: 20px;
|
||||
}
|
||||
.carousel .carousel-caption > div {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
padding: 20px;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
bottom: 20px;
|
||||
}
|
||||
.carousel .carousel-caption h1, .carousel .carousel-caption h2, .carousel .carousel-caption h3 {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.carousel .carousel-image {
|
||||
right: 50%;
|
||||
left: 50%;
|
||||
top: 5%;
|
||||
bottom: 5%;
|
||||
position: absolute;
|
||||
@@ -332,13 +335,35 @@ ul.nav-stacked > li > a {
|
||||
right: 10%;
|
||||
top: 10%;
|
||||
bottom: auto;
|
||||
}
|
||||
.carousel .item.text_only .carousel-caption > div {
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
bottom: auto;
|
||||
width: 100%;
|
||||
}
|
||||
.carousel .item.text_image .carousel-caption {
|
||||
left: 10%;
|
||||
}
|
||||
.carousel .item.text_image .carousel-caption > div {
|
||||
right: 50%;
|
||||
margin-right: -20%;
|
||||
max-width: 550px;
|
||||
}
|
||||
.carousel .item.text_image .carousel-image {
|
||||
right: 10%;
|
||||
left: 50%;
|
||||
}
|
||||
.carousel .item.image_text .carousel-caption {
|
||||
right: 10%;
|
||||
}
|
||||
.carousel .item.image_text .carousel-caption > div {
|
||||
left: 50%;
|
||||
margin-left: -20%;
|
||||
max-width: 550px;
|
||||
}
|
||||
.carousel .item.image_text .carousel-image {
|
||||
right: 50%;
|
||||
left: 10%;
|
||||
}
|
||||
.carousel .carousel-control {
|
||||
|
||||
@@ -248,18 +248,20 @@ ul.nav-stacked > li > a
|
||||
background-size: cover
|
||||
.carousel
|
||||
.carousel-caption
|
||||
left: auto
|
||||
right: auto
|
||||
bottom: 10%
|
||||
text-align: left
|
||||
padding: 20px
|
||||
background: rgba(0, 0, 0, 0.4)
|
||||
position: absolute
|
||||
right: 50%
|
||||
left: 50%
|
||||
bottom: 20px
|
||||
> div
|
||||
position: absolute
|
||||
text-align: left
|
||||
padding: 20px
|
||||
background: rgba(0, 0, 0, 0.4)
|
||||
bottom: 20px
|
||||
h1, h2, h3
|
||||
margin-top: 10px
|
||||
margin-bottom: 10px
|
||||
.carousel-image
|
||||
right: 50%
|
||||
left: 50%
|
||||
top: 5%
|
||||
bottom: 5%
|
||||
position: absolute
|
||||
@@ -273,12 +275,30 @@ ul.nav-stacked > li > a
|
||||
right: 10%
|
||||
top: 10%
|
||||
bottom: auto
|
||||
text-align: center
|
||||
background: transparent
|
||||
> div
|
||||
text-align: center
|
||||
background: transparent
|
||||
bottom: auto
|
||||
width: 100%
|
||||
.item.text_image
|
||||
.carousel-caption
|
||||
left: 10%
|
||||
> div
|
||||
right: 50%
|
||||
margin-right: -20%
|
||||
max-width: 550px
|
||||
.carousel-image
|
||||
right: 10%
|
||||
left: 50%
|
||||
.item.image_text
|
||||
.carousel-caption
|
||||
right: 10%
|
||||
> div
|
||||
left: 50%
|
||||
margin-left: -20%
|
||||
max-width: 550px
|
||||
.carousel-image
|
||||
right: 50%
|
||||
left: 10%
|
||||
.carousel-control
|
||||
cursor: pointer
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
<div class="item image_text active" style="background-image: url('/website/static/src/img/banner/color_splash.jpg')">
|
||||
<div class="container">
|
||||
<div class="carousel-caption content">
|
||||
<h2>Your Banner Title</h2>
|
||||
<h3>Click to customize this text</h3>
|
||||
<p>
|
||||
<a href="/page/website.contactus" class="btn btn-success btn-large">Contact us</a>
|
||||
</p>
|
||||
<div>
|
||||
<h2>Your Banner Title</h2>
|
||||
<h3>Click to customize this text</h3>
|
||||
<p>
|
||||
<a href="/page/website.contactus" class="btn btn-success btn-large">Contact us</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<img class="carousel-image hidden-xs" src="/website/static/src/img/banner/banner_picture.png" alt="Banner OpenERP Image"/>
|
||||
</div>
|
||||
@@ -182,15 +184,6 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="hr" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_separator.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Separator</span>
|
||||
</div>
|
||||
<hr class="oe_snippet_body"/>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="big-picture" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_big_picture.png"/>
|
||||
@@ -372,6 +365,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-snippet-id="hr" data-selector-children=".oe_structure, [data-oe-type=html]">
|
||||
<div class="oe_snippet_thumbnail">
|
||||
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_separator.png"/>
|
||||
<span class="oe_snippet_thumbnail_title">Separator</span>
|
||||
</div>
|
||||
<hr class="oe_snippet_body"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="snippet_feature" class="tab-pane fade">
|
||||
|
||||
@@ -673,10 +673,9 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
|
||||
<template id="company_description" name="Company Description">
|
||||
<address>
|
||||
<div t-field="res_company.name">Name</div>
|
||||
<br />
|
||||
<div><i class="fa fa-phone"/> <span t-field="res_company.phone"/></div>
|
||||
<div><i class="fa fa-envelope"/> <span t-field="res_company.email"/></div>
|
||||
<div t-field="res_company.partner_id" t-field-options='{
|
||||
"widget": "contact",
|
||||
"fields": ["name", "address", "phone", "mobile", "fax", "email"]}'/>
|
||||
</address>
|
||||
<a t-att-href="res_company.google_map_link()" target="_BLANK">
|
||||
<img class="thumbnail img-responsive" t-att-src="res_company.google_map_img()" />
|
||||
@@ -703,7 +702,7 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
|
||||
</div>
|
||||
<div class="col-md-4 mb32">
|
||||
<div groups="base.group_website_publisher" t-ignore="true" class="pull-right css_editable_mode_hidden" t-att-style="style or ''">
|
||||
<a class="btn btn-primary" t-att-href="'/web#return_label=Website&model=%s&id=%s' % (res_company._name, res_company.id)" title='Edit in backend'>Edit</a>
|
||||
<a class="btn btm-sm btn-default" t-att-href="'/web#return_label=Website&model=%s&id=%s' % (res_company._name, res_company.id)">Change address</a>
|
||||
</div>
|
||||
<t t-call="website.company_description"/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user