diff options
| author | Christophe Simonis <chs@odoo.com> | 2015-08-11 16:56:47 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2015-08-11 16:56:47 +0200 |
| commit | 171d001985eab6ac1c06339117e8b22b96d5d689 (patch) | |
| tree | 468e6d87e3e68dab775b364f27a7ff29f72816c4 /addons | |
| parent | 71d51bb05fc8df01613e8c2da55b16da6bb553cd (diff) | |
| parent | 02954bad2b390024bf60d209e4ce181c04eb865d (diff) | |
[MERGE] forward port of branch 8.0 up to 02954ba
Diffstat (limited to 'addons')
42 files changed, 506 insertions, 89 deletions
diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 266112d7cb8..4eca707b863 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -399,7 +399,7 @@ <field name="reconciled" invisible="1"/> </group> <group> - <field name="payment_term" class="oe_inline" on_change="onchange_payment_term_date_invoice(payment_term,date_invoice)"/> + <field name="payment_term" class="oe_inline" on_change="onchange_payment_term_date_invoice(payment_term, date_invoice)"/> </group> <field name="comment" class="oe_inline" placeholder="Additional notes..."/> </page> diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 51e005a45fb..e03285dacd3 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -885,6 +885,7 @@ <field name="priority">100</field> <field name="arch" type="xml"> <tree string="Account Tax Code" toolbar="1"> + <field name="sequence" widget="handle"/> <field name="name"/> <field name="code"/> <field name="sum_period"/> @@ -904,6 +905,7 @@ <field name="code"/> <field name="parent_id"/> <field name="company_id" groups="base.group_multi_company"/> + <field name="sequence"/> </group> <group string="Reporting Configuration"> <field name="notprintable"/> @@ -2154,6 +2156,7 @@ <field name="field_parent">child_ids</field> <field name="arch" type="xml"> <tree string="Account Tax Code Template" toolbar="1"> + <field name="sequence" widget="handle"/> <field name="name"/> <field name="code"/> <field name="parent_id" invisible="1"/> @@ -2183,6 +2186,7 @@ <field name="code"/> <field name="parent_id"/> <field name="sign"/> + <field name="sequence"/> </group> <separator string="Description"/> <field name="info"/> diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 8d8be98e38f..313dd54f4db 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -375,7 +375,7 @@ class account_analytic_account(osv.osv): inv_ids = [] for account in self.browse(cr, uid, ids, context=context): res[account.id] = 0.0 - line_ids = lines_obj.search(cr, uid, [('account_id','=', account.id), ('invoice_id','!=',False), ('to_invoice','!=', False), ('journal_id.type', '=', 'general'), ('invoice_id.type', 'in', ['out_invoice', 'out_refund'])], context=context) + line_ids = lines_obj.search(cr, uid, [('account_id','=', account.id), ('invoice_id','!=',False), ('invoice_id.state', 'not in', ['draft', 'cancel']), ('to_invoice','!=', False), ('journal_id.type', '=', 'general'), ('invoice_id.type', 'in', ['out_invoice', 'out_refund'])], context=context) for line in lines_obj.browse(cr, uid, line_ids, context=context): if line.invoice_id not in inv_ids: inv_ids.append(line.invoice_id) diff --git a/addons/auth_oauth/auth_oauth_data.xml b/addons/auth_oauth/auth_oauth_data.xml index fe64f42b2f6..b389386f1c1 100644 --- a/addons/auth_oauth/auth_oauth_data.xml +++ b/addons/auth_oauth/auth_oauth_data.xml @@ -14,8 +14,8 @@ <record id="provider_facebook" model="auth.oauth.provider"> <field name="name">Facebook Graph</field> <field name="auth_endpoint">https://www.facebook.com/dialog/oauth</field> - <field name="scope"></field> - <field name="validation_endpoint">https://graph.facebook.com/me/permissions</field> + <field name="scope">public_profile,email</field> + <field name="validation_endpoint">https://graph.facebook.com/me</field> <field name="data_endpoint"></field> <field name="css_class">fa fa-facebook-square</field> <field name="body">Log in with facebook</field> diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index f2c6be389f1..cada7d51a26 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -101,7 +101,12 @@ class res_users(osv.Model): validation = self._auth_oauth_validate(cr, uid, provider, access_token) # required check if not validation.get('user_id'): - raise openerp.exceptions.AccessDenied() + # Workaround: facebook does not send 'user_id' in Open Graph Api + if validation.get('id'): + validation['user_id'] = validation['id'] + else: + raise openerp.exceptions.AccessDenied() + # retrieve and sign in user login = self._auth_oauth_signin(cr, uid, provider, validation, params, context=context) if not login: diff --git a/addons/auth_openid/res_users.py b/addons/auth_openid/res_users.py index 35f70438d80..f8367073f62 100644 --- a/addons/auth_openid/res_users.py +++ b/addons/auth_openid/res_users.py @@ -63,19 +63,15 @@ class res_users(osv.osv): cr.commit() return res[0] if res else False - def check(self, db, uid, passwd): + def check_credentials(self, cr, uid, password): try: - return super(res_users, self).check(db, uid, passwd) + return super(res_users, self).check_credentials(cr, uid, password) except openerp.exceptions.AccessDenied: - if not passwd: + cr.execute('''SELECT COUNT(1) + FROM res_users + WHERE id=%s + AND openid_key=%s + AND active=%s''', + (int(uid), password, True)) + if not cr.fetchone()[0]: raise - with RegistryManager.get(db).cursor() as cr: - cr.execute('''SELECT COUNT(1) - FROM res_users - WHERE id=%s - AND openid_key=%s - AND active=%s''', - (int(uid), passwd, True)) - if not cr.fetchone()[0]: - raise - self._uid_cache.setdefault(db, {})[uid] = passwd diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml index fdbce2b0310..6ee9c2cd931 100644 --- a/addons/hr_holidays/hr_holidays_view.xml +++ b/addons/hr_holidays/hr_holidays_view.xml @@ -1,3 +1,4 @@ +<?xml version='1.0' encoding='UTF-8' ?> <openerp> <data> @@ -25,17 +26,27 @@ <filter domain="[('state','in',('confirm','validate1'))]" string="To Approve" name="approve"/> <filter domain="[('state','=','validate')]" string="Validated" name="validated"/> <separator/> + <filter name="active_types" string="Active Types" domain="[('holiday_status_id.active', '=', True)]" help="Filters only on allocations and requests that belong to an holiday type that is 'active' (active field is True)"/> + <separator/> <filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/> <separator/> <filter string="Approved Leaves" name="validated" domain="[('state','=','validate')]"/> <separator/> <filter string="To Report in Payslip" name="gray" domain="[('payslip_status', '=', False)]" groups="base.group_hr_manager"/> <separator/> - <filter name="year" string="Year" domain="[('holiday_status_id.active','=',True)]" help="Filters only on allocations and requests that belong to an holiday type that is 'active' (active field is True)"/> <separator/> <filter string="To Do" name="todo" domain="[('payslip_status', '=', False), ('holiday_status_id.active', '=', True)]"/> <separator/> - <filter string="My Department Leaves" help="My Department Leaves" domain="[('department_id.manager_id','=',uid)]"/> + <filter name="year" string="Year" + domain="['|','&',('date_to', '<=', time.strftime('%%Y-12-31')), + ('date_to', '>=', time.strftime('%%Y-01-01')), + '&',('date_from', '<=', time.strftime('%%Y-12-31')), + ('date_from', '>=', time.strftime('%%Y-01-01'))]" + help="Current Year Leaves"/> + <separator/> + <filter string="My Requests" name="my_leaves" domain="[('user_id', '=', uid)]" help="My Leave Requests"/> + <separator/> + <filter string="My Department Leaves" name="my_department_leaves" domain="[('department_id.manager_id.user_id', '=', uid)]"/> <field name="employee_id"/> <field name="department_id"/> <field name="holiday_status_id"/> diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py index d475a10f6a6..a1dffb15a00 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py @@ -255,6 +255,7 @@ class account_analytic_line(osv.osv): def invoice_cost_create(self, cr, uid, ids, data=None, context=None): invoice_obj = self.pool.get('account.invoice') invoice_line_obj = self.pool.get('account.invoice.line') + analytic_line_obj = self.pool.get('account.analytic.line') invoices = [] if context is None: context = {} @@ -303,13 +304,15 @@ class account_analytic_line(osv.osv): analytic_line.to_invoice.id, analytic_line.account_id, analytic_line.journal_id.type) + # We want to retrieve the data in the partner language for the invoice creation + analytic_line = analytic_line_obj.browse(cr, uid , [line.id for line in analytic_line], context=invoice_context) invoice_lines_grouping.setdefault(key, []).append(analytic_line) # finally creates the invoice line for (product_id, uom, user_id, factor_id, account, journal_type), lines_to_invoice in invoice_lines_grouping.items(): curr_invoice_line = self._prepare_cost_invoice_line(cr, uid, last_invoice, product_id, uom, user_id, factor_id, account, lines_to_invoice, - journal_type, data, context=context) + journal_type, data, context=invoice_context) invoice_line_obj.create(cr, uid, curr_invoice_line, context=context) self.write(cr, uid, [l.id for l in analytic_lines], {'invoice_id': last_invoice}, context=context) diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py index c57238bd659..083e5cd5557 100644 --- a/addons/hw_escpos/controllers/main.py +++ b/addons/hw_escpos/controllers/main.py @@ -40,6 +40,10 @@ from openerp.tools.translate import _ _logger = logging.getLogger(__name__) +# workaround https://bugs.launchpad.net/openobject-server/+bug/947231 +# related to http://bugs.python.org/issue7980 +from datetime import datetime +datetime.strptime('2012-01-01', '%Y-%m-%d') class EscposDriver(Thread): def __init__(self): @@ -146,7 +150,7 @@ class EscposDriver(Thread): _logger.warning('ESC/POS Device Disconnected: '+message) def run(self): - + printer = None if not escpos: _logger.error('ESC/POS cannot initialize, please verify system dependencies.') return @@ -192,7 +196,7 @@ class EscposDriver(Thread): errmsg = str(e) + '\n' + '-'*60+'\n' + traceback.format_exc() + '-'*60 + '\n' _logger.error(errmsg); finally: - if error: + if error: self.queue.put((timestamp, task, data)) if printer: printer.close() diff --git a/addons/hw_posbox_homepage/controllers/main.py b/addons/hw_posbox_homepage/controllers/main.py index 25e33c409fa..a021986bee7 100644 --- a/addons/hw_posbox_homepage/controllers/main.py +++ b/addons/hw_posbox_homepage/controllers/main.py @@ -36,16 +36,16 @@ index_template = """ </p> <p> For more information on how to setup the Point of Sale with - the PosBox, please refer to <a href='/hw_proxy/static/doc/manual.pdf'>the manual</a> + the PosBox, please refer to <a href='/hw_proxy/static/doc/manual.pdf'>the manual</a>. </p> <p> To see the status of the connected hardware, please refer - to the <a href='/hw_proxy/status'>hardware status page</a> + to the <a href='/hw_proxy/status'>hardware status page</a>. </p> <p> - The PosBox software installed on this posbox is <b>version 6</b>, + The PosBox software installed on this posbox is <b>version 13</b>, the posbox version number is independent from Odoo. You can upgrade - the software on the <a href='/hw_proxy/upgrade/'>upgrade page</a> + the software on the <a href='/hw_proxy/upgrade/'>upgrade page</a>. </p> <p>For any other question, please contact the Odoo support at <a href='mailto:support@odoo.com'>support@odoo.com</a> </p> diff --git a/addons/hw_posbox_upgrade/controllers/main.py b/addons/hw_posbox_upgrade/controllers/main.py index 0947fbc8564..5ed958d020e 100644 --- a/addons/hw_posbox_upgrade/controllers/main.py +++ b/addons/hw_posbox_upgrade/controllers/main.py @@ -29,17 +29,8 @@ upgrade_template = """ $.ajax({ url:'/hw_proxy/perform_upgrade/' }).then(function(status){ - $('#upgrade').html('Upgrade Successful<br \\>Click to Restart the PosBox'); + $('#upgrade').html('Upgrade successful, restarting the posbox...'); $('#upgrade').off('click'); - $('#upgrade').click(function(){ - $.ajax({ url:'/hw_proxy/perform_restart' }) - $('#upgrade').text('Restarting'); - $('#upgrade').off('click'); - setTimeout(function(){ - window.location = '/' - },30*1000); - }); - },function(){ $('#upgrade').text('Upgrade Failed'); }); @@ -73,9 +64,11 @@ upgrade_template = """ <body> <h1>PosBox Software Upgrade</h1> <p> - This tool will help you perform an upgrade of the PosBox's software. + This tool will help you perform an upgrade of the PosBox's software over the + internet. + <p></p> However the preferred method to upgrade the posbox is to flash the sd-card with - the <a href='http://nightly.openerp.com/trunk/posbox/'>latest image</a>. The upgrade + the <a href='http://nightly.odoo.com/trunk/posbox/'>latest image</a>. The upgrade procedure is explained into to the <a href='/hw_proxy/static/doc/manual.pdf'>PosBox manual</a> </p> <p> @@ -93,7 +86,6 @@ class PosboxUpgrader(hw_proxy.Proxy): def __init__(self): super(PosboxUpgrader,self).__init__() self.upgrading = threading.Lock() - self.last_upgrade = 0 @http.route('/hw_proxy/upgrade', type='http', auth='none', ) def upgrade(self): @@ -102,25 +94,8 @@ class PosboxUpgrader(hw_proxy.Proxy): @http.route('/hw_proxy/perform_upgrade', type='http', auth='none') def perform_upgrade(self): self.upgrading.acquire() - if time.time() - self.last_upgrade < 30: - self.upgrading.release() - return 'UPTODATE' - else: - os.system('/bin/bash /home/pi/openerp/update.sh') - self.last_upgrade = time.time() - self.upgrading.release() - return 'SUCCESS' - - @http.route('/hw_proxy/perform_restart', type='http', auth='none') - def perform_restart(self): - self.upgrading.acquire() - if time.time() - self.last_upgrade < 30: - self.upgrading.release() - return 'RESTARTED' - else: - os.system('/bin/bash /home/pi/openerp/restart.sh') - self.last_upgrade = time.time() - self.upgrading.release() - return 'SUCCESS' + os.system('/home/pi/posbox_update.sh') + self.upgrading.release() + return 'SUCCESS' diff --git a/addons/hw_proxy/controllers/main.py b/addons/hw_proxy/controllers/main.py index 337874cf67a..eb95527efcd 100644 --- a/addons/hw_proxy/controllers/main.py +++ b/addons/hw_proxy/controllers/main.py @@ -17,6 +17,14 @@ _logger = logging.getLogger(__name__) from openerp import http from openerp.http import request +# Those are the builtin raspberry pi USB modules, they should +# not appear in the list of connected devices. +BANNED_DEVICES = set([ + "0424:9514", # Standard Microsystem Corp. Builtin Ethernet module + "1d6b:0002", # Linux Foundation 2.0 root hub + "0424:ec00", # Standard Microsystem Corp. Other Builtin Ethernet module +]) + # drivers modules must add to drivers an object with a get_status() method # so that 'status' can return the status of all active drivers @@ -88,10 +96,18 @@ class Proxy(http.Controller): <p>The list of connected USB devices as seen by the posbox</p> """ devices = commands.getoutput("lsusb").split('\n') + count = 0 resp += "<div class='devices'>\n" for device in devices: device_name = device[device.find('ID')+2:] - resp+= "<div class='device' data-device='"+device+"'>"+device_name+"</div>\n" + device_id = device_name.split()[0] + if not (device_id in BANNED_DEVICES): + resp+= "<div class='device' data-device='"+device+"'>"+device_name+"</div>\n" + count += 1 + + if count == 0: + resp += "<div class='device'>No USB Device Found</div>" + resp += "</div>\n" resp += """ <h2>Add New Printer</h2> diff --git a/addons/hw_scale/controllers/main.py b/addons/hw_scale/controllers/main.py index 44a031f5566..2f9e0271dd5 100644 --- a/addons/hw_scale/controllers/main.py +++ b/addons/hw_scale/controllers/main.py @@ -44,6 +44,11 @@ class Scale(Thread): if status == self.status['status']: if message != None and message != self.status['messages'][-1]: self.status['messages'].append(message) + + if status == 'error' and message: + _logger.error('Scale Error: '+message) + elif status == 'disconnected' and message: + _logger.warning('Disconnected Scale: '+message) else: self.status['status'] = status if message: @@ -51,13 +56,16 @@ class Scale(Thread): else: self.status['messages'] = [] - if status == 'error' and message: - _logger.error('Scale Error: '+message) - elif status == 'disconnected' and message: - _logger.info('Disconnected Scale: %s', message) + if status == 'error' and message: + _logger.error('Scale Error: '+message) + elif status == 'disconnected' and message: + _logger.info('Disconnected Scale: %s', message) def get_device(self): try: + if not os.path.exists(self.input_dir): + self.set_status('disconnected','Scale Not Found') + return None devices = [ device for device in listdir(self.input_dir)] scales = [ device for device in devices if ('mettler' in device.lower()) or ('toledo' in device.lower()) ] if len(scales) > 0: @@ -69,8 +77,8 @@ class Scale(Thread): stopbits = serial.STOPBITS_ONE, parity = serial.PARITY_EVEN, #xonxoff = serial.XON, - timeout = 0.01, - writeTimeout= 0.01) + timeout = 0.02, + writeTimeout= 0.02) else: self.set_status('disconnected','Scale Not Found') return None @@ -95,7 +103,7 @@ class Scale(Thread): if self.device: try: self.device.write('W') - time.sleep(0.1) + time.sleep(0.2) answer = [] while True: @@ -171,7 +179,7 @@ class Scale(Thread): while True: if self.device: self.read_weight() - time.sleep(0.05) + time.sleep(0.15) else: with self.scalelock: self.device = self.get_device() diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py index 6e53c37006f..8e5e8f6af18 100644 --- a/addons/hw_scanner/controllers/main.py +++ b/addons/hw_scanner/controllers/main.py @@ -111,6 +111,8 @@ class Scanner(Thread): def get_device(self): try: + if not evdev: + return None devices = [ device for device in listdir(self.input_dir)] keyboards = [ device for device in devices if ('kbd' in device) and ('keyboard' not in device.lower())] scanners = [ device for device in devices if ('barcode' in device.lower()) or ('scanner' in device.lower())] @@ -133,6 +135,7 @@ class Scanner(Thread): been returned before. This is necessary to catch barcodes scanned while the POS is busy reading another barcode """ + self.lockedstart() while True: @@ -164,10 +167,13 @@ class Scanner(Thread): try: device.ungrab() except Exception as e: + device = None self.set_status('error',str(e)) else: time.sleep(5) # wait until a suitable device is plugged device = self.get_device() + if not device: + continue try: device.grab() diff --git a/addons/mass_mailing/models/mail_mail.py b/addons/mass_mailing/models/mail_mail.py index 7a9128189e6..94cb8b0794b 100644 --- a/addons/mass_mailing/models/mail_mail.py +++ b/addons/mass_mailing/models/mail_mail.py @@ -19,8 +19,8 @@ # ############################################################################## -import urllib import urlparse +import werkzeug.urls from openerp import tools from openerp import SUPERUSER_ID @@ -55,7 +55,7 @@ class MailMail(osv.Model): track_url = urlparse.urljoin( base_url, 'mail/track/%(mail_id)s/blank.gif?%(params)s' % { 'mail_id': mail.id, - 'params': urllib.urlencode({'db': cr.dbname}) + 'params': werkzeug.url_encode({'db': cr.dbname}) } ) return '<img src="%s" alt=""/>' % track_url @@ -65,7 +65,7 @@ class MailMail(osv.Model): url = urlparse.urljoin( base_url, 'mail/mailing/%(mailing_id)s/unsubscribe?%(params)s' % { 'mailing_id': mail.mailing_id.id, - 'params': urllib.urlencode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to}) + 'params': werkzeug.url_encode({'db': cr.dbname, 'res_id': mail.res_id, 'email': email_to}) } ) return url diff --git a/addons/point_of_sale/tools/posbox/.gitignore b/addons/point_of_sale/tools/posbox/.gitignore new file mode 100644 index 00000000000..b26eafa34d1 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/.gitignore @@ -0,0 +1,3 @@ +kernel-qemu +posbox.img +raspbian.img
\ No newline at end of file diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/fstab b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/fstab new file mode 100644 index 00000000000..28898fc8ea4 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/fstab @@ -0,0 +1,4 @@ +proc /proc proc defaults 0 0 +/dev/mmcblk0p1 /boot vfat defaults 0 2 +/dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1 +# a swapfile is not a swap partition, so no using swapon|off from here on, use dphys-swapfile swap[on|off] for that diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/init.d/rcS b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/init.d/rcS new file mode 100755 index 00000000000..6380e949834 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/init.d/rcS @@ -0,0 +1,10 @@ +#! /bin/sh +# +# rcS +# +# Call all S??* scripts in /etc/rcS.d/ in numerical/alphabetical order +# + +/etc/setup_ramdisks.sh + +exec /etc/init.d/rc S diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/network/interfaces b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/network/interfaces new file mode 100644 index 00000000000..95b6f07524a --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/network/interfaces @@ -0,0 +1,3 @@ +# needed for postgresql +auto lo +iface lo inet loopback
\ No newline at end of file diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/rc.local b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/rc.local new file mode 100755 index 00000000000..065b6a05f77 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/rc.local @@ -0,0 +1,25 @@ +#!/bin/sh -e +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +# Print the IP address +_IP=$(hostname -I) || true +if [ "$_IP" ]; then + printf "My IP address is %s\n" "$_IP" +fi + +mkdir -p /var/run/odoo +chown pi:pi /var/run/odoo + +/home/pi/led_status.sh & + +exit 0 diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/setup_ramdisks.sh b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/setup_ramdisks.sh new file mode 100755 index 00000000000..47e11d1bdd3 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/setup_ramdisks.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail +# set -o xtrace + +create_ramdisk () { + ORIGINAL="${1}" + RAMDISK="${ORIGINAL}_ram" + SIZE="${2}" + echo "Creating ramdisk for ${1} of size ${SIZE}..." + + mount -t tmpfs -o size="${SIZE}" tmpfs "${RAMDISK}" + rsync -a --exclude="swap" --exclude="apt" --exclude="dpkg" "${ORIGINAL}/" "${RAMDISK}/" + mount --bind "${RAMDISK}" "${ORIGINAL}" +} + +# check /proc/cmdline + +# bind mount / so that we can get to the real /var and /etc +mount --bind / /root_bypass_ramdisks + +echo "Creating ramdisks..." +create_ramdisk "/var" "128M" +create_ramdisk "/etc" "16M" diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo new file mode 100755 index 00000000000..9bdaa86c584 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init.d/odoo @@ -0,0 +1,72 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: odoo.py +# Required-Start: $remote_fs $syslog postgresql +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start odoo daemon at boot time +# Description: Enable service provided by daemon. +# X-Interactive: true +### END INIT INFO +## more info: http://wiki.debian.org/LSBInitScripts + +. /lib/lsb/init-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin +DAEMON=/home/pi/odoo/odoo.py +NAME=odoo +DESC=odoo +CONFIG=/home/pi/odoo.conf +LOGFILE=/var/log/odoo/odoo-server.log +PIDFILE=/var/run/${NAME}.pid +USER=pi + +test -x $DAEMON || exit 0 +set -e + +function _start() { + start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$USER --background --make-pidfile --exec $DAEMON -- --config $CONFIG --logfile $LOGFILE --load=web,hw_proxy,hw_posbox_homepage,hw_posbox_upgrade,hw_scale,hw_scanner,hw_escpos +} + +function _stop() { + start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo --retry 3 + rm -f $PIDFILE +} + +function _status() { + start-stop-daemon --status --quiet --pidfile $PIDFILE + return $? +} + + +case "$1" in + start) + echo -n "Starting $DESC: " + _start + echo "ok" + ;; + stop) + echo -n "Stopping $DESC: " + _stop + echo "ok" + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + _stop + sleep 1 + _start + echo "ok" + ;; + status) + echo -n "Status of $DESC: " + _status && echo "running" || echo "stopped" + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh new file mode 100755 index 00000000000..68b64fb94ca --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail +# set -o xtrace + +__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +__file="${__dir}/$(basename "${BASH_SOURCE[0]}")" +__base="$(basename ${__file} .sh)" + +# Recommends: antiword, graphviz, ghostscript, postgresql, python-gevent, poppler-utils +export DEBIAN_FRONTEND=noninteractive + +# GUI-related packages +PKGS_TO_DELETE="xserver-xorg-video-fbdev xserver-xorg xinit gstreamer1.0-x gstreamer1.0-omx gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-alsa gstreamer1.0-libav epiphany-browser lxde lxtask menu-xdg gksu xserver-xorg-video-fbturbo xpdf gtk2-engines alsa-utils netsurf-gtk zenity desktop-base lxpolkit weston omxplayer raspberrypi-artwork lightdm gnome-themes-standard-data gnome-icon-theme qt50-snapshot qt50-quick-particle-examples idle python-pygame python-tk idle3 python-serial python-picamera debian-reference-en dillo x2x scratch nuscratch raspberrypi-ui-mods timidity smartsim penguinspuzzle pistore sonic-pi python-pifacecommon python-pifacedigitalio oracle-java8-jdk minecraft-pi python-minecraftpi wolfram-engine raspi-config libgl1-mesa-dri libicu48 pypy-upstream lxde-icon-theme python3" +INSTALLED_PKGS_TO_DELETE="" +set +o errexit +for CURRENT_PKG in $(echo $PKGS_TO_DELETE); do + $(dpkg --status $CURRENT_PKG &> /dev/null) + if [[ $? -eq 0 ]]; then + INSTALLED_PKGS_TO_DELETE="$INSTALLED_PKGS_TO_DELETE $CURRENT_PKG" + fi +done +set -o errexit + +apt-get -y remove --purge ${INSTALLED_PKGS_TO_DELETE} + +# Remove automatically installed dependency packages +apt-get -y autoremove + +apt-get update +apt-get -y dist-upgrade + +PKGS_TO_INSTALL="adduser postgresql-client python python-dateutil python-decorator python-docutils python-feedparser python-imaging python-jinja2 python-ldap python-libxslt1 python-lxml python-mako python-mock python-openid python-passlib python-psutil python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-pypdf python-reportlab python-requests python-simplejson python-tz python-unittest2 python-vatnumber python-vobject python-werkzeug python-xlwt python-yaml postgresql python-gevent python-serial python-pip python-dev localepurge vim mc mg" + +apt-get -y install ${PKGS_TO_INSTALL} + +apt-get clean +localepurge +rm -rf /usr/share/doc || true +rm -rf /home/pi/python_games || true + +# python-usb in wheezy is too old +# the latest pyusb from pip does not work either, usb.core.find() never returns +# this may be fixed with libusb>2:1.0.11-1, but that's the most recent one in raspbian +# so we install the latest pyusb that works with this libusb +pip install pyusb==1.0.0b1 +pip install qrcode +pip install evdev + +usermod -a -G lp pi + +sudo -u postgres createuser -s pi +mkdir /var/log/odoo +chown pi:pi /var/log/odoo + +update-rc.d odoo defaults + +# create dirs for ramdisks +create_ramdisk_dir () { + mkdir "${1}_ram" +} + +create_ramdisk_dir "/var" +create_ramdisk_dir "/etc" +mkdir /root_bypass_ramdisks + +reboot diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload new file mode 100644 index 00000000000..5e9332843b5 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload @@ -0,0 +1,2 @@ +# the used qemu-kernel doesn't work well with this library, so get rid of it +#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.conf b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.conf new file mode 100644 index 00000000000..1ac409b252e --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.conf @@ -0,0 +1,32 @@ +# see "man logrotate" for details +# rotate log files daily +daily + +# keep 2 days worth of backlogs +rotate 2 + +# create new (empty) log files after rotating old ones +create + +# uncomment this if you want your log files compressed +#compress + +# packages drop log rotation information into this directory +include /etc/logrotate.d + +# no packages own wtmp, or btmp -- we'll rotate them here +/var/log/wtmp { + missingok + monthly + create 0664 root utmp + rotate 1 +} + +/var/log/btmp { + missingok + monthly + create 0660 root utmp + rotate 1 +} + +# system-specific logs may be configured here diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.d/odoo b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.d/odoo new file mode 100644 index 00000000000..060ec54d012 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/logrotate.d/odoo @@ -0,0 +1,5 @@ +/var/log/odoo/*.log { + copytruncate + missingok + notifempty +} diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/rc.local b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/rc.local new file mode 100755 index 00000000000..c55290c3978 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/rc.local @@ -0,0 +1,22 @@ +#!/bin/sh -e +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +# Print the IP address +_IP=$(hostname -I) || true +if [ "$_IP" ]; then + printf "My IP address is %s\n" "$_IP" +fi + +/etc/init_posbox_image.sh + +exit 0 diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/90-qemu.rules b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/90-qemu.rules new file mode 100644 index 00000000000..fadedd206fe --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/udev/rules.d/90-qemu.rules @@ -0,0 +1,3 @@ +KERNEL=="sda", SYMLINK+="mmcblk0" +KERNEL=="sda?", SYMLINK+="mmcblk0p%n" +KERNEL=="sda2", SYMLINK+="root"
\ No newline at end of file diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/led_status.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/led_status.sh new file mode 100755 index 00000000000..8d272d7de2b --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/led_status.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set_brightness() { + echo "${1}" > /sys/class/leds/led0/brightness +} + +check_status_loop() { + while true ; do + if wget --quiet localhost:8069/hw_proxy/hello -O /dev/null ; then + set_brightness 255 + else + set_brightness 0 + fi + sleep 5 + done +} + +echo none > /sys/class/leds/led0/trigger +check_status_loop diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/odoo.conf b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/odoo.conf new file mode 100644 index 00000000000..1bc0a0d3ba5 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/odoo.conf @@ -0,0 +1,6 @@ +[options] +data_dir = /var/run/odoo +log_level = error +logfile = /var/log/odoo/odoo-server.log +pidfile = /var/run/odoo/odoo.pid +server_wide_modules = web,hw_proxy,hw_posbox_homepage,hw_posbox_upgrade,hw_scale,hw_scanner,hw_escpos
\ No newline at end of file diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/posbox_update.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/posbox_update.sh new file mode 100755 index 00000000000..e994a60461f --- /dev/null +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/home/pi/posbox_update.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +sudo mount -o remount,rw / +sudo git --work-tree=/home/pi/odoo/ --git-dir=/home/pi/odoo/.git pull +sudo mount -o remount,ro / +(sleep 5 && sudo reboot) & diff --git a/addons/point_of_sale/tools/posbox/posbox_create_image.sh b/addons/point_of_sale/tools/posbox/posbox_create_image.sh new file mode 100755 index 00000000000..2a2a0dd9425 --- /dev/null +++ b/addons/point_of_sale/tools/posbox/posbox_create_image.sh @@ -0,0 +1,75 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +set -o pipefail +# set -o xtrace + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +file_exists() { + [[ -f $1 ]]; +} + +__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +__file="${__dir}/$(basename "${BASH_SOURCE[0]}")" +__base="$(basename ${__file} .sh)" + +MOUNT_POINT="${__dir}/root_mount" +OVERWRITE_FILES_BEFORE_INIT_DIR="${__dir}/overwrite_before_init" +OVERWRITE_FILES_AFTER_INIT_DIR="${__dir}/overwrite_after_init" + +if [ ! -f kernel-qemu ] || ! file_exists *raspbian*.img ; then + ./posbox_download_images.sh +fi + +cp -a *raspbian*.img posbox.img + +CLONE_DIR="${OVERWRITE_FILES_BEFORE_INIT_DIR}/home/pi/odoo" +mkdir "${CLONE_DIR}" +git clone -b 8.0 --no-checkout --depth 1 https://github.com/odoo/odoo.git "${CLONE_DIR}" +cd "${CLONE_DIR}" +git config core.sparsecheckout true +echo "addons/web +addons/web_kanban +addons/hw_* +openerp/ +odoo.py" | tee --append .git/info/sparse-checkout > /dev/null +git read-tree -mu HEAD +cd "${__dir}" + +# rc.local +LOOP_MAPPER_PATH=$(kpartx -av posbox.img | tail -n 1 | cut -d ' ' -f 3) +LOOP_MAPPER_PATH="/dev/mapper/${LOOP_MAPPER_PATH}" +mkdir "${MOUNT_POINT}" +mount "${LOOP_MAPPER_PATH}" "${MOUNT_POINT}" + +# 'overlay' the overwrite directory onto the mounted image filesystem +cp -a "${OVERWRITE_FILES_BEFORE_INIT_DIR}"/* "${MOUNT_POINT}" + +# get rid of the git clone +rm -rf "${CLONE_DIR}" + +# get rid of the mount, we have to remount it anyway because we have +# to "refresh" the filesystem after qemu modified it +sleep 2 +umount "${MOUNT_POINT}" + +# from http://paulscott.co.za/blog/full-raspberry-pi-raspbian-emulation-with-qemu/ +# ssh pi@localhost -p10022 +qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda posbox.img -net user,hostfwd=tcp::10022-:22,hostfwd=tcp::18069-:8069 -net nic + +mount "${LOOP_MAPPER_PATH}" "${MOUNT_POINT}" +cp -av "${OVERWRITE_FILES_AFTER_INIT_DIR}"/* "${MOUNT_POINT}" + +# cleanup +sleep 2 +umount "${MOUNT_POINT}" +rm -r "${MOUNT_POINT}" + +echo "Running zerofree..." +zerofree -v "${LOOP_MAPPER_PATH}" || true + +kpartx -d posbox.img diff --git a/addons/point_of_sale/tools/posbox/posbox_download_images.sh b/addons/point_of_sale/tools/posbox/posbox_download_images.sh new file mode 100755 index 00000000000..a138e44bfab --- /dev/null +++ b/addons/point_of_sale/tools/posbox/posbox_download_images.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +wget 'http://downloads.raspberrypi.org/raspbian_latest' -O raspbian.img.zip +unzip raspbian.img.zip +wget 'https://github.com/dhruvvyas90/qemu-rpi-kernel/raw/master/kernel-qemu' diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py index 28c48bc8a67..0be952c936b 100644 --- a/addons/sale/wizard/sale_make_invoice_advance.py +++ b/addons/sale/wizard/sale_make_invoice_advance.py @@ -79,7 +79,8 @@ class sale_advance_payment_inv(osv.osv_memory): result = [] for sale in sale_obj.browse(cr, uid, sale_ids, context=context): val = inv_line_obj.product_id_change(cr, uid, [], wizard.product_id.id, - False, partner_id=sale.partner_id.id, fposition_id=sale.fiscal_position.id) + False, partner_id=sale.partner_id.id, fposition_id=sale.fiscal_position.id, + company_id=sale.company_id.id) res = val['value'] # determine and check income account @@ -143,7 +144,7 @@ class sale_advance_payment_inv(osv.osv_memory): 'partner_id': sale.partner_invoice_id.id, 'invoice_line': [(0, 0, inv_line_values)], 'currency_id': sale.pricelist_id.currency_id.id, - 'comment': '', + 'comment': sale.note, 'payment_term': sale.payment_term.id, 'fiscal_position': sale.fiscal_position.id or sale.partner_id.property_account_position.id, 'team_id': sale.team_id.id, diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 11d5e8442eb..5791b050f23 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -993,7 +993,8 @@ class stock_picking(osv.osv): move_obj = self.pool.get("stock.move") move_obj.write(cr, uid, backorder_move_ids, {'picking_id': backorder_id}, context=context) - self.write(cr, uid, [picking.id], {'date_done': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) + if not picking.date_done: + self.write(cr, uid, [picking.id], {'date_done': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) self.action_confirm(cr, uid, [backorder_id], context=context) return backorder_id return False @@ -1744,12 +1745,14 @@ class stock_move(osv.osv): settings_obj = self.pool.get('stock.config.settings') uom_obj = self.pool.get('product.uom') res = dict.fromkeys(ids, '') + precision = self.pool['decimal.precision'].precision_get(cr, uid, 'Product Unit of Measure') for move in self.browse(cr, uid, ids, context=context): if move.state in ('draft', 'done', 'cancel') or move.location_id.usage != 'internal': res[move.id] = '' # 'not applicable' or 'n/a' could work too continue total_available = min(move.product_qty, move.reserved_availability + move.availability) - total_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, total_available, move.product_uom, context=context) + total_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, total_available, move.product_uom, round=False, context=context) + total_available = float_round(total_available, precision_digits=precision) info = str(total_available) #look in the settings if we need to display the UoM name or not config_ids = settings_obj.search(cr, uid, [], limit=1, order='id DESC', context=context) @@ -1760,7 +1763,8 @@ class stock_move(osv.osv): if move.reserved_availability: if move.reserved_availability != total_available: #some of the available quantity is assigned and some are available but not reserved - reserved_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, move.reserved_availability, move.product_uom, context=context) + reserved_available = uom_obj._compute_qty_obj(cr, uid, move.product_id.uom_id, move.reserved_availability, move.product_uom, round=False, context=context) + reserved_available = float_round(reserved_available, precision_digits=precision) info += _(' (%s reserved)') % str(reserved_available) else: #all available quantity is assigned diff --git a/addons/stock_account/stock.py b/addons/stock_account/stock.py index 1b12d4d95b4..f40e7b3c561 100644 --- a/addons/stock_account/stock.py +++ b/addons/stock_account/stock.py @@ -315,9 +315,15 @@ class stock_picking(osv.osv): invoices[key] = invoice_id else: invoice = invoice_obj.browse(cr, uid, invoices[key], context=context) + merge_vals = {} if not invoice.origin or invoice_vals['origin'] not in invoice.origin.split(', '): invoice_origin = filter(None, [invoice.origin, invoice_vals['origin']]) - invoice.write({'origin': ', '.join(invoice_origin)}) + merge_vals['origin'] = ', '.join(invoice_origin) + if not invoice.name or invoice_vals['name'] not in invoice.name.split(', '): + invoice_name = filter(None, [invoice.name, invoice_vals['name']]) + merge_vals['name'] = ', '.join(invoice_name) + if merge_vals: + invoice.write(merge_vals) invoice_line_vals = move_obj._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context) invoice_line_vals['invoice_id'] = invoices[key] diff --git a/addons/survey/security/survey_security.xml b/addons/survey/security/survey_security.xml index 7375cf227ab..97bcb8cc65e 100644 --- a/addons/survey/security/survey_security.xml +++ b/addons/survey/security/survey_security.xml @@ -50,7 +50,7 @@ <record id="survey_input_users_access" model="ir.rule"> <field name="name">Access to user_input for regular users</field> <field name="model_id" ref="survey.model_survey_user_input"/> - <field name="domain_force">[('create_uid', '=', user.id)]</field> + <field name="domain_force">['|', ('create_uid', '=', user.id), ('partner_id', '=', user.partner_id.id)]</field> <field name="groups" eval="[(4, ref('base.group_survey_user'))]"/> <field eval="0" name="perm_unlink"/> <field eval="0" name="perm_write"/> diff --git a/addons/web/static/src/css/ie.css b/addons/web/static/src/css/ie.css index f628ed1213d..a547120033e 100644 --- a/addons/web/static/src/css/ie.css +++ b/addons/web/static/src/css/ie.css @@ -24,9 +24,6 @@ } /** web_kanban */ -:root .openerp .oe_kanban_view .oe_kanban_group_title_vertical { - writing-mode: lr-tb; -} .openerp .oe_kanban_column_cards { min-height: 80px; } diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index d7762f76398..8cde68b17d8 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -145,7 +145,6 @@ .openerp .oe_kanban_view .oe_kanban_group_title_undefined { color: #666666; } .openerp .oe_kanban_view .oe_kanban_group_title_vertical { - writing-mode: vertical-rl; -webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); -o-transform: rotate(90deg); @@ -483,7 +482,6 @@ .openerp_ie .oe_kanban_view .oe_kanban_group_header.oe_kanban_group_folded .oe_kanban_group_title_vertical { display: inline-block !important; } .openerp_ie .oe_kanban_view .oe_kanban_group_title_vertical { - -ms-writing-mode: lr-tb !important; background: #f0eeee; } .openerp_ie .oe_kanban_view.oe_kanban_grouped .oe_kanban_group_header { height: 1%; } diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index 463cc916bc6..0933e3aa836 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -203,7 +203,6 @@ .oe_kanban_group_title_undefined color: #666666 .oe_kanban_group_title_vertical - writing-mode: vertical-rl -webkit-transform: rotate(90deg) -moz-transform: rotate(90deg) -o-transform: rotate(90deg) @@ -515,7 +514,6 @@ .oe_kanban_group_header.oe_kanban_group_folded .oe_kanban_group_title_vertical display: inline-block !important .oe_kanban_group_title_vertical - -ms-writing-mode: lr-tb !important background: rgb(240, 238, 238) &.oe_kanban_grouped .oe_kanban_group_header diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js index 3869986e48a..a11961e8e5c 100644 --- a/addons/website/static/src/js/website.js +++ b/addons/website/static/src/js/website.js @@ -369,8 +369,8 @@ // retrieve the hash before the redirect var redirect = { lang: self.data('lang'), - url: self.attr('href'), - hash: location.hash + url: encodeURIComponent(self.attr('href')), + hash: encodeURIComponent(location.hash) }; location.href = _.str.sprintf("/website/lang/%(lang)s?r=%(url)s%(hash)s", redirect); }); diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index 15965a2d8da..086473fec5c 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -84,7 +84,7 @@ $('.oe_website_sale').each(function () { return; } if (!data.quantity) { - location.reload(); + location.reload(true); return; } var $q = $(".my_cart_quantity"); |
