[MERGE] merge the branch of the point_of_sale
bzr revid: stw@openerp.com-20120822093223-sdf72z5vhw2cejac
This commit is contained in:
commit
d0057766ab
File diff suppressed because it is too large
Load Diff
|
@ -83,16 +83,16 @@ Main features:
|
|||
'application': True,
|
||||
# Web client
|
||||
'js': [
|
||||
'static/lib/backbone/backbone-0.9.2.js',
|
||||
'static/lib/mousewheel/jquery.mousewheel-3.0.6.js',
|
||||
'static/src/js/pos_models.js',
|
||||
'static/src/js/pos_basewidget.js',
|
||||
'static/src/js/pos_keyboard_widget.js',
|
||||
'static/src/js/pos_scrollbar_widget.js',
|
||||
'static/src/js/pos_widgets.js',
|
||||
'static/src/js/pos_devices.js',
|
||||
'static/src/js/pos_screens.js',
|
||||
'static/src/js/pos_main.js'
|
||||
'static/src/js/db.js',
|
||||
'static/src/js/models.js',
|
||||
'static/src/js/widget_base.js',
|
||||
'static/src/js/widget_keyboard.js',
|
||||
'static/src/js/widget_scrollbar.js',
|
||||
'static/src/js/widgets.js',
|
||||
'static/src/js/devices.js',
|
||||
'static/src/js/screens.js',
|
||||
'static/src/js/main.js'
|
||||
],
|
||||
'css': [
|
||||
'static/src/css/pos.css',
|
||||
|
|
|
@ -34,8 +34,8 @@ class account_journal(osv.osv):
|
|||
'self_checkout_payment_method' : fields.boolean('Self Checkout Payment Method'),
|
||||
}
|
||||
_defaults = {
|
||||
'opening_control' : True,
|
||||
'closing_control' : True,
|
||||
'opening_control' : False,
|
||||
'closing_control' : False,
|
||||
'self_checkout_payment_method' : False,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import main
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
@ -1,14 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
import simplejson
|
||||
import os
|
||||
import openerp
|
||||
|
||||
try:
|
||||
import openerp.addons.web.common.http as openerpweb
|
||||
from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template
|
||||
except ImportError:
|
||||
import web.common.http as openerpweb
|
||||
|
||||
class PointOfSaleController(openerpweb.Controller):
|
||||
_cp_path = '/pos'
|
||||
|
||||
@openerpweb.httprequest
|
||||
def app(self, req, s_action=None, **kw):
|
||||
js = "\n ".join('<script type="text/javascript" src="%s"></script>' % i for i in manifest_list(req, None, 'js'))
|
||||
css = "\n ".join('<link rel="stylesheet" href="%s">' % i for i in manifest_list(req, None, 'css'))
|
||||
|
||||
cookie = req.httprequest.cookies.get("instance0|session_id")
|
||||
session_id = cookie.replace("%22","")
|
||||
template = html_template.replace('<html','<html manifest="/pos/manifest?session_id=%s"'%session_id)
|
||||
r = template % {
|
||||
'js': js,
|
||||
'css': css,
|
||||
'modules': simplejson.dumps(module_boot(req)),
|
||||
'init': 'var wc = new s.web.WebClient();wc.appendTo($(document.body));'
|
||||
}
|
||||
return r
|
||||
|
||||
@openerpweb.httprequest
|
||||
def manifest(self, req, **kwargs):
|
||||
""" This generates a HTML5 cache manifest files that preloads the categories and products thumbnails
|
||||
and other ressources necessary for the point of sale to work offline """
|
||||
|
||||
ml = ["CACHE MANIFEST"]
|
||||
|
||||
# loading all the images in the static/src/img/* directories
|
||||
def load_css_img(srcdir,dstdir):
|
||||
for f in os.listdir(srcdir):
|
||||
path = os.path.join(srcdir,f)
|
||||
dstpath = os.path.join(dstdir,f)
|
||||
if os.path.isdir(path) :
|
||||
load_css_img(path,dstpath)
|
||||
elif f.endswith(('.png','.PNG','.jpg','.JPG','.jpeg','.JPEG','.gif','.GIF')):
|
||||
ml.append(dstpath)
|
||||
|
||||
imgdir = openerp.modules.get_module_resource('point_of_sale','static/src/img');
|
||||
load_css_img(imgdir,'/point_of_sale/static/src/img')
|
||||
|
||||
products = req.session.model('product.product')
|
||||
for p in products.search_read([('pos_categ_id','!=',False)], ['name']):
|
||||
product_id = p['id']
|
||||
url = "/web/binary/image?session_id=%s&model=product.product&field=image&id=%s" % (req.session_id, product_id)
|
||||
ml.append(url)
|
||||
|
||||
categories = req.session.model('pos.category')
|
||||
for c in categories.search_read([],['name']):
|
||||
category_id = c['id']
|
||||
url = "/web/binary/image?session_id=%s&model=pos.category&field=image&id=%s" % (req.session_id, category_id)
|
||||
ml.append(url)
|
||||
|
||||
ml += ["NETWORK:","*"]
|
||||
m = "\n".join(ml)
|
||||
|
||||
return m
|
||||
|
||||
@openerpweb.jsonrequest
|
||||
def dispatch(self, request, iface, **kwargs):
|
||||
method = 'iface_%s' % iface
|
||||
|
@ -109,3 +166,4 @@ class PointOfSaleController(openerpweb.Controller):
|
|||
print 'print_receipt' + str(receipt)
|
||||
return
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 75 KiB |
|
@ -0,0 +1,506 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="744.09448819"
|
||||
height="1052.3622047"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="barcode_test_sheet.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.86706515"
|
||||
inkscape:cx="381.55817"
|
||||
inkscape:cy="597.57819"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1301"
|
||||
inkscape:window-height="744"
|
||||
inkscape:window-x="1985"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g4158"
|
||||
transform="matrix(0.92675002,0,0,0.92675002,27.597551,38.360312)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text2985"
|
||||
y="72.12545"
|
||||
x="140.86679"
|
||||
style="font-size:46.51613998px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="72.12545"
|
||||
x="140.86679"
|
||||
id="tspan2987"
|
||||
sodipodi:role="line">BARCODE TEST SHEET</tspan></text>
|
||||
<g
|
||||
transform="translate(0,-5.3405762e-5)"
|
||||
id="g3347">
|
||||
<image
|
||||
y="124.14642"
|
||||
x="388.17426"
|
||||
id="image3083"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAADqUlEQVR4 nO3a226jMABFUYjy/7/MPCChDBfHARM4zVpP1dQY4u66JEw/DEO3S9/3XdeNh79+vRwz2hr5OmZr 5JH5t0YuX0X51W0dW3PNNa9xOWf5au8wsrxu9Ud95HHkYPg+yRJGsoSRLGEkSxjJEkayhJEsYSRL GMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJ EkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJG soSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKE kSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEs YSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEk SxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxh+mEY dh7Z913XjYe/fv3LrMlS8zWxyxJGsjuNGwbf91z911Z/1GY/18oJ689+cOTb7LZmPtJr/ZrcfOTu 1SucseaQlV221f6xnKdm5vqznzHy1Nn6vq9fk5SRrYzzry7RzHyXbd7r9HszXVP9b3bN/EdGlq/k 0y250uu0W2tSv3oXjvxo9d4ahmE6b/mP58ou2/BNbuUr3Hf2M0aOzthRVn8M5QurX71rR87sXr1h GGa/z6tT/Zds2y12+TpfP+nYOqp+/rYjZ4esXvzk0zkLlmtSv3rXjlx1/F3QMtzZgMfse1d9jvi1 t1zND2HScPUK2+2j+cl2uEmvl/Bh2Zat+4TH64gLruvzs599C3vSOqz+Yf1LvZ60estwn93ehdt9 ez5zk1vYJmrW5C9lWqNVJ5OnW4IjR31kudFWvqe5v/NWb/lE47n6jbOvo3xZhbOfMfLL7n97fRNb j9/WH9j+mgtTtsUW5hzNN6PVMx2/iMLO93ba798tfPp6d398tjyqfqFu+I9vv7XD1uY6Ofd/ci0/ o/5ZhR/2lvrVu3ZkK7PPX7ee2px1YzA9Mn77S/Nrlj/+1UdNlat37ciGCncCMyfuslsP/e7mazey y22j8Pi3fvWuHdlq9cYZap6H/wMqFm5yx9XfMwAAAABJRU5ErkJggg== "
|
||||
height="107.96206"
|
||||
width="163.36363" />
|
||||
<rect
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3086"
|
||||
width="417.54495"
|
||||
height="126.4052"
|
||||
x="141.08452"
|
||||
y="114.51707"
|
||||
rx="2.0839903"
|
||||
ry="2.0839903" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="201.46712"
|
||||
y="147.73848"
|
||||
id="text3856"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3858"
|
||||
x="201.46712"
|
||||
y="147.73848"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">CASHIER</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3860"
|
||||
y="182.10147"
|
||||
x="154.5717"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="182.10147"
|
||||
x="154.5717"
|
||||
id="tspan3862"
|
||||
sodipodi:role="line">Prefix: 40</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="200.85837"
|
||||
id="text3149"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3151"
|
||||
x="154.5717"
|
||||
y="200.85837"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">ID: 4447190000</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,0.97855377)"
|
||||
id="g3335">
|
||||
<g
|
||||
id="g3173"
|
||||
transform="translate(0,-3.2620699)">
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3153"
|
||||
y="341.12738"
|
||||
x="154.5717"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="341.12738"
|
||||
x="154.5717"
|
||||
id="tspan3155"
|
||||
sodipodi:role="line">Prefix: 42</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="359.88428"
|
||||
id="text3157"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3159"
|
||||
x="154.5717"
|
||||
y="359.88428"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">ID: 1182180000</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g3954"
|
||||
transform="translate(0,-18.756902)">
|
||||
<rect
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3876"
|
||||
width="417.54495"
|
||||
height="126.4052"
|
||||
x="141.08452"
|
||||
y="284.96024"
|
||||
rx="2.0839903"
|
||||
ry="2.0839903" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="209.6223"
|
||||
y="318.18164"
|
||||
id="text3878"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3880"
|
||||
x="209.6223"
|
||||
y="318.18164"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">CLIENT</tspan></text>
|
||||
<image
|
||||
width="162.31204"
|
||||
height="107.26709"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAADyUlEQVR4 nO3a3Y6qShSFUTC+/yvXuSAxbCgQsPiZp8e46mgJq/ETxe6+lNId0vd913XDw8c/z+8d3zIYP2p8 y9LKLbcvbXN8y5Zt/jLn0jHZcnzm29z+m961cmn+vY/a5fXLg+F6kiWMZAkjWcJIljCSJYxkCSNZ wkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJI ljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYw kiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIl jGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxk CSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkj WcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nC 9KWUg4/s+67rhoePf/7LHJO55sfEWZYwj0t2eCG2XXmGe/f+l72rt7Z6U5s8r1832LbX+ZqlAc6b 85qpbln59SDs7afvN31MrZxlm5w/+r6fb6d644H9Huu1euOpcx6eqnrj0n7vXdnKsP31Iz+YnmWb TzZ+3Wx/wqoOrJzvfeml3HDO36ear1wa/saV62fovafYUspnv+tv8pWzbMPPA5NNjS8bL1Dd+9gt c36dqnrX+pNy78qJw8etlDJ53VY39U+ybZ+kjb9nGWm1cpfmc/5o6RwzfyHdu3LX8NvNw50seE3u a/J8XPC8bjH5bavXPdfP+XWqXG0TGm92fJTezXf2BJ8PRtsvzy/wzKkea3Je/yT6mqw41e0vjI27 vnjO/0evJx20+eeEd3f0vWnXx/OlC52TVA/f8P6yPsCPc64fk8NTRTt8GbfkffYZ5eJYu9ULiJU+ zp7z2FQpzqtocj4tpbyrdzSZY7zNJz8fKXP+NfNYhx/qf7BtuL+HR5Ay55OdcYpdOY+8Ss1n6Y9z pHTwqDmXvgGdl3HvypNMvtKa7/GU/+S695uB7Qf9yjkPpDD/hn/JvStbmcdaPSxnfTDoVn/PK783 +GXZBdcTS/utfoO7dPV218qGtl9RPO7/ZZuovkBv/5vcrqmqK5c2e+PKVu9Uwxa2PEf/AXnknj+O sxSLAAAAAElFTkSuQmCC "
|
||||
id="image3951"
|
||||
x="388.17426"
|
||||
y="294.58957" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,0.3261795)"
|
||||
id="g3322">
|
||||
<rect
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect3964"
|
||||
width="417.54495"
|
||||
height="126.4052"
|
||||
x="141.08452"
|
||||
y="419.52063"
|
||||
rx="2.0839903"
|
||||
ry="2.0839903" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="209.6223"
|
||||
y="452.74203"
|
||||
id="text3966"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3968"
|
||||
x="209.6223"
|
||||
y="452.74203"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">WEIGHT</tspan></text>
|
||||
<image
|
||||
width="162.12962"
|
||||
height="107.14654"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAAERElEQVR4 nO3a0ZKaQBRFUbX8/182D1QZInRzadDxTNZ6mjgNNrhBYHJ9PB6XIdfr9XK5TIvPf57/drJ8/ayR rVdaG9Wfc+Vd+vPc+3N/hv3XK68st2i5Xa09XNnS+sjKthfdjiwMnydZwkiWMJIljGQJI1nCSJYw kiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIl jGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxk CSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkj WcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nC SJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiW MJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCS Jcz18XgMLnm9Xi6XafH5z/8z+2Tp9H3iLEuYDyU7HV7njuT/dH/+9NLKid9o5/Zan+fYFnW+vFrT 27uv+hPb3AnLt1su0prSO/beWeVcr6XL1Ns0dLnNqy+OzeOskfV5Dm9RZ8BZe2N1YgfXWXlx11u/ Y2TftFTlM7rP/zFv/B378eDIp+I8V89enUO5MpMjXz7P9S/nP59V/3zWOiX317k6/9aw5TqPj9z0 eDyea+vfpd1Wt/ny7y3eN6jP88jX9wdu8Jfzn2wuWD84W1cOm8Navz1rZN/LfmidcW/H36nz9pUP oz7yUs6uuLa5dx+cB5/vvOmRWeuAb52ex0bunVL/W/Se8uDw+Dw3r1MHTnVjs5qvpP6m9QuG7/lu HNa5Trg3F/oVKrfSR05ge5dt3awMH5DPj7b+0KA/n+/xcrZ+7qhmsm/6JjpdfZ6dMZuLd+5yBuxa ydgHsbxsnS4N407Gy3BXkm3d6KyuqzLyTSrzXH5Cex+Cdt5ifoabBlT2SSWmutZGtVb4+UxP7+Sf v34979EGbl8+aWye9RuIuoMnv039Ge66AVruqy//lCcvzw3+XhjsvSH4Ke+YZ+dR/DfvijFBW9S6 071fylcCP644z19T2wc25GsvZzvnpnvrF1/rxHl2rvZWL3lbTxuK77V6ifmZaPpH+8vlZmeeYyPH ptqa8C3lnPTjj5OW6xz7dlr9Q93YrFoP7Vfz6s+kOM+DI/uWl63r095c0VnP8A8+M9/cF8XHN8Xn WfUT6nCvm2uo7Lf6lu6af32eu7aoo36X8jv/i/fqAXrwBrm1zr0rKa6heJzXt3TXE4P6PI/vk/lS lc/oD6RX6TSeNJuDAAAAAElFTkSuQmCC "
|
||||
id="image4065"
|
||||
x="387.35876"
|
||||
y="429.14993" />
|
||||
<g
|
||||
transform="translate(0,140.26901)"
|
||||
id="g3179">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
id="text3181"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3183"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Prefix: 21</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3185"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
id="tspan3187"
|
||||
sodipodi:role="line">ID: 12345</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
id="text3189"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3191"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Value: 67.89Kg</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1.9572678)"
|
||||
id="g3308">
|
||||
<rect
|
||||
ry="2.0839903"
|
||||
rx="2.0839903"
|
||||
y="574.46893"
|
||||
x="141.08452"
|
||||
height="126.4052"
|
||||
width="417.54495"
|
||||
id="rect4081"
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<g
|
||||
id="g3296">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="195.7585"
|
||||
y="607.69037"
|
||||
id="text4083"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4085"
|
||||
x="195.7585"
|
||||
y="607.69037"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">DISCOUNT</tspan></text>
|
||||
<image
|
||||
y="584.09827"
|
||||
x="385.72772"
|
||||
id="image4202"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAADsElEQVR4 nO3aXXOiMACGUej4//8ye+EMZYHECBF96zlXHTd8iE8jYTtO0zQcMo7jMAz3zUs/b8ffLUcuXymN bHn92ZHtR3l2ZOnnpfazOvauS3toP3rLyPr5tGx1wM+ZjeF6kiWMZAkjWcJIljCSJYxkCSNZwkiW MJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCS JYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWM ZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJ I1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZ wkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJI ljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCjNM0 HdxyHIdhuG++/PmbuSZb3a+JWZYwH5fs/RfxL42kr9vuq6/4UmvZZ0qFZ3pdbVu5II0jSyezO777 0XdP4Fg549h0m7ozy75i/mjZZ0qFHXst7W0cx92RjZufPPrJkc+e1XKT3fe4sp5lr+81pb/zV2be wzyXzJ9TaXZZvl45gZbJqf3oZ0ZWBtdN0zTvrf6FvDPLvmKRa+E8W16K+nf36l+Xi+7XHf3kyIeD 6/tZpb/7Zv+bZd9yS9A4kQSN3FWaOe6zy3ZOumYhsT36s+fZ3eo3c3vE32TfteRi5cDlal8qvcKq qi4TX+U+4bb7ahd6fZfLrvwcVq+HBts9bMO9rUb0pdeOtiFWVj/v1fFz34Z7G46+yfrt+SdcuOu1 L1meUl+Qbc/h2Jr98IltHyMsD939mvy4Jfhk86p5tZquu+bKVxZqQ785a/Xc4PfGoPJA+OTfzfTd 5/dYfU5vPJN3Ka0p9//Dlvcq3Ql8j8pv7K3yNPvMM+Hu+0xXeq5ZuSwPr1Vp2931e+PRD5xnXw8f 2H3cX3L9ecuPpMu902on9Rn64dHbR5buWQ/Hvb1t3d2JG4PrlJ5itvzJ1e74px6Lth/9qfOsn2q7 9nt3s+ylSuvrMzts32f3kaWjH3hT901atv0Hm+wpnHOLKX0AAAAASUVORK5CYII= "
|
||||
height="108.34499"
|
||||
width="163.94308"
|
||||
inkscape:transform-center-x="-24.4145"
|
||||
inkscape:transform-center-y="6.3942733" />
|
||||
<g
|
||||
transform="translate(0,296.03285)"
|
||||
id="g3210">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
id="text3212"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3214"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Prefix: 44</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3216"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
id="tspan3218"
|
||||
sodipodi:role="line">ID: 11111</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
id="text3220"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3222"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Value: 25%</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-0.97866058)"
|
||||
id="g3283">
|
||||
<rect
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4115"
|
||||
width="417.54495"
|
||||
height="126.4052"
|
||||
x="141.08452"
|
||||
y="726.15521"
|
||||
rx="2.0839903"
|
||||
ry="2.0839903" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="212.88437"
|
||||
y="759.37659"
|
||||
id="text4117"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4119"
|
||||
x="212.88437"
|
||||
y="759.37659"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">PRICE</tspan></text>
|
||||
<image
|
||||
width="163.36363"
|
||||
height="107.96206"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAAD70lEQVR4 nO3Z3XKbOhiGUezJ/d8yPfBsbwaB+Phz/aZrHaWukDB+goE8xnEcDnk8HsMwvDaf/tz+7/SVl3bR drbEkWvHZG3O/gytyvxrq6yt265emWfvyMq7K3qe2Rg+T7KEkSxhJEsYyRJGsoSRLGEkSxjJEkay hJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSR LGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxh JEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRL GMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJ EkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJG soSRLGEkSxjJEkayhJEsYSRLGMkSRrKEkSxhJEsYyRJGsoSRLGEkSxjJEkayhJEsYSRLmMc4jge3 fDyGYXhtPv35X+aYtC4/Js6yhJHsX/M65bDXz/un2RG85ButPufvG9lX6fXYWp0v37VFK4M/c0wq 2z4XV118Ze/yi3PWX6zP+W0jN21uVT9Q9Zl37Wr9nV57TCrv8We6xrvx9/bnz7XTGTp70w5bWz1l ZGvvZzmbdnO5yvyVXa33cGE54zi+Z+vfpT2n2yz+fED7Tqb/nB7ZxZ3rfE99/8jzdn19HxhTVO/h qnLGcZydERYPxXOt6DavA3twctv6aeP7Rw7/fSSzD6YzrDLn21U3c/UebiqnDXc24Ge4gYeRd9i8 Tt31pf/ytZ9U5zrhlmTPq/+Opow8pp2/jaze69r83xnu7Gz93tWPPpdtD9Dil8hiBykj79O5Wths bnp3cezC429prxOOn2V3XXSv3ZC1AzZ988gLb2HbSRbPiPXL6MUXL3w0VFn6klVuP8u+7/vWfrPb 19NH3qR+A7R3zm82e24wjuON17KzlfqD68cuZeTHrP3hY/jKva1bu1O8K9nNK4Hi5r9mZN0vqO28 zvnu53VBs/aHjZMH7uQ17uLzuS8f+UmL63YuedeeNszmLPZwUzmbj+Gei0NPnjzqO9056KEjr9JO fv4ksvbEY/Pd9d/pVeW0l63LO7b4+Oa9zeG1+wMWT2Cbq6eMrOj31zmAxS+uk/t/x294X/3O5/+z +oV/F9mVbLvJxh6HjOyrnDKPfSK7fhk6c94xsq/4rO0Pc0/7XuEpWE8AAAAASUVORK5CYII= "
|
||||
id="image4264"
|
||||
x="386.54324"
|
||||
y="734.96906" />
|
||||
<g
|
||||
transform="translate(0,442.82599)"
|
||||
id="g3224">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
id="text3226"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3228"
|
||||
x="154.5717"
|
||||
y="341.12738"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Prefix: 02</tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3230"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="359.88428"
|
||||
x="154.5717"
|
||||
id="tspan3232"
|
||||
sodipodi:role="line">ID: 99999</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
id="text3234"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3236"
|
||||
x="154.5717"
|
||||
y="379.4567"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">Value: 134.50€</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g3269">
|
||||
<g
|
||||
id="g3061"
|
||||
transform="translate(0,284.6156)">
|
||||
<g
|
||||
id="g3063"
|
||||
transform="translate(0,154.94832)">
|
||||
<rect
|
||||
ry="2.0839903"
|
||||
rx="2.0839903"
|
||||
y="438.27753"
|
||||
x="141.08452"
|
||||
height="126.4052"
|
||||
width="417.54495"
|
||||
id="rect3065"
|
||||
style="fill:none;stroke:#c3c3c3;stroke-width:1.07903957;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3067"
|
||||
y="471.49893"
|
||||
x="216.61778"
|
||||
style="font-size:27.53050041px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="471.49893"
|
||||
x="216.61778"
|
||||
sodipodi:role="line"
|
||||
id="tspan3083">UNIT</tspan></text>
|
||||
<g
|
||||
transform="translate(0,156.57936)"
|
||||
id="g3071" />
|
||||
</g>
|
||||
</g>
|
||||
<image
|
||||
y="887.47076"
|
||||
x="386.54324"
|
||||
id="image3146"
|
||||
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOYAAACYCAIAAAB/IAJdAAAAA3NCSVQICAjb4U/gAAADz0lEQVR4 nO3Z0ZKaMACGUdnx/V+ZXjBjGWKyEQjyt+fcdIsBY/ZTgZ3meX7sMk3T4/FYdq/9XI5frB9db18/ Wh6nfJZyr/Yz9s+t/Yp65tw/22+N3Pe6asevhdQ/stPPkZ3hepIljGQJI1nCSJYwkiWMZAkjWcJI ljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYw kiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIl jGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxk CSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkj WcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nC SJYwkiWMZAkjWcJIljCSJYxkCSNZwkiWMJIljGQJI1nCSJYwkiWMZAkjWcJIljCSJYxkCSNZwkzz PO/cc5oej8ey+/rn/5k1KZ2+Jj5lCSNZwjyXf5ZP7NKJ32v9XwrtkZupNg743ZH3nNWgV3p8WZaD 9Oz4Uz7fCP1P0Rg5TVP5aG38d0fWfHFW/av36TofX5bXLm+PtvF8/TTuQuGUXl/W83y9zs3kX8d5 bb9yZM0dZtWzev0jy2f/9bA18zy/jtb+mr3oXLZ/9u3zgc2j7cOuH71+5K1m1b96B9d5+e+isUvt OJv0336EDU/23I/Y0vruyfo45ZJdM7LmnrM6MnLQXbwy3M2AZ+2xU6Zy1iUXN7eO55RfYuM84Vnb 53hD1/R6wbXjP+z4d2Dt2ut4uJvP9ddhf9Zn0LvPQtrPesrIt19heu3Uv3r71nlEPOsjr2fyrF0t /nrd1z7lH3cKe+dMj1+cjTbi91Jefi1XTsv209ekevl1w1OC8k084m39r+pfvY/WefT6b+4bzPNc PZc95clqGzevs3/k2y30O/FUbbTa/YCByV7jzucJ9zf6FuRujVsQb/56sdnnrHfbwbOF2nwag7+1 ccfrGr2xf/XOWudye6dfb7b+vB13eq/HvZ1J+61f3ve+cuStZtW/emet845yytPW95NZ37PdOLfX 49dkH83zst/cR6v0xVn1r96gdW7r/2PE33tYI/76Vc7p+G2ED15b9ysaMfKes9q3emetc1vjjura Hwkp3Xa7HcbMAAAAAElFTkSuQmCC "
|
||||
height="108.34499"
|
||||
width="163.94308" />
|
||||
<g
|
||||
id="g3255"
|
||||
transform="translate(0,598.58983)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:17.41555405px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="154.5717"
|
||||
y="351.81107"
|
||||
id="text3261"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3263"
|
||||
x="154.5717"
|
||||
y="351.81107"
|
||||
style="font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium">ID: 5449000000996</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,261.82237,1622.2884)"
|
||||
id="g4150">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
|
||||
x="618.97778"
|
||||
y="320.0275"
|
||||
id="text3357"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3359"
|
||||
x="618.97778"
|
||||
y="320.0275">This is a test sheet intended to help you test the codebar aquisition in OpenERP's Point of Sale module. </tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="618.97778"
|
||||
y="330.0275"
|
||||
id="tspan3363">The codes provided in this list are randomly chosen and are encoded in the EAN13 format. Their codes</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="618.97778"
|
||||
y="340.0275"
|
||||
id="tspan3367">and prefixes are not intended to match any specified standard. </tspan></text>
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3369"
|
||||
y="349.54001"
|
||||
x="618.99207"
|
||||
style="font-size:6.53564215px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan3375"
|
||||
y="349.54001"
|
||||
x="618.99207"
|
||||
sodipodi:role="line"
|
||||
style="fill:#b3b3b3;fill-opacity:1">This document is licensed by OpenERP S.A. under the Creative Commons CC BY 3.0 license htttp://www.creativecommons.org</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 31 KiB |
|
@ -22,6 +22,7 @@
|
|||
import pdb
|
||||
import openerp
|
||||
import addons
|
||||
import openerp.addons.product.product
|
||||
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
@ -59,16 +60,9 @@ class pos_config(osv.osv):
|
|||
help="Accounting journal used to post sales entries."),
|
||||
'iface_self_checkout' : fields.boolean('Self Checkout Mode',
|
||||
help="Check this if this point of sale should open by default in a self checkout mode. If unchecked, OpenERP uses the normal cashier mode by default."),
|
||||
'iface_websql' : fields.boolean('WebSQL (Faster but Chrome Only)',
|
||||
help="If have more than 200 products, it's highly suggested to use WebSQL "\
|
||||
"to store the data in the browser, instead of localStore mechanism. "\
|
||||
"It's more efficient but works on the Chrome browser only."
|
||||
),
|
||||
'iface_led' : fields.boolean('Help Notification'),
|
||||
'iface_cashdrawer' : fields.boolean('Cashdrawer Interface'),
|
||||
'iface_payment_terminal' : fields.boolean('Payment Terminal Interface'),
|
||||
'iface_electronic_scale' : fields.boolean('Electronic Scale Interface'),
|
||||
'iface_barscan' : fields.boolean('BarScan Interface'),
|
||||
'iface_vkeyboard' : fields.boolean('Virtual KeyBoard Interface'),
|
||||
'iface_print_via_proxy' : fields.boolean('Print via Proxy'),
|
||||
|
||||
|
@ -77,7 +71,7 @@ class pos_config(osv.osv):
|
|||
help="This sequence is automatically created by OpenERP but you can change it "\
|
||||
"to customize the reference numbers of your orders."),
|
||||
'session_ids': fields.one2many('pos.session', 'config_id', 'Sessions'),
|
||||
'group_by' : fields.boolean('Group By', help="Check this if you want to group the Journal Items by Product while closing a Session"),
|
||||
'group_by' : fields.boolean('Group Journal Items', help="Check this if you want to group the Journal Items by Product while closing a Session"),
|
||||
}
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
|
@ -93,7 +87,7 @@ class pos_config(osv.osv):
|
|||
result.append((record.id, record.name+' ('+_('not used')+')'))
|
||||
continue
|
||||
session = record.session_ids[0]
|
||||
result.append((record.id, record.name + ' ('+session.user_id.name+', '+states[session.state]+')'))
|
||||
result.append((record.id, record.name + ' ('+session.user_id.name+')')) #, '+states[session.state]+')'))
|
||||
return result
|
||||
|
||||
|
||||
|
@ -143,8 +137,6 @@ class pos_config(osv.osv):
|
|||
obj.sequence_id.unlink()
|
||||
return super(pos_config, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
pos_config()
|
||||
|
||||
class pos_session(osv.osv):
|
||||
_name = 'pos.session'
|
||||
_order = 'id desc'
|
||||
|
@ -459,8 +451,6 @@ class pos_session(osv.osv):
|
|||
'context' : context,
|
||||
}
|
||||
|
||||
pos_session()
|
||||
|
||||
class pos_order(osv.osv):
|
||||
_name = "pos.order"
|
||||
_description = "Point of Sale"
|
||||
|
@ -1079,8 +1069,6 @@ class pos_order(osv.osv):
|
|||
self.create_account_move(cr, uid, ids, context=context)
|
||||
return True
|
||||
|
||||
pos_order()
|
||||
|
||||
class account_bank_statement(osv.osv):
|
||||
_inherit = 'account.bank.statement'
|
||||
_columns= {
|
||||
|
@ -1179,8 +1167,6 @@ class pos_order_line(osv.osv):
|
|||
})
|
||||
return super(pos_order_line, self).copy_data(cr, uid, id, default, context=context)
|
||||
|
||||
pos_order_line()
|
||||
|
||||
class pos_category(osv.osv):
|
||||
_name = 'pos.category'
|
||||
_description = "Point of Sale Category"
|
||||
|
@ -1230,6 +1216,11 @@ class pos_category(osv.osv):
|
|||
'parent_id': fields.many2one('pos.category','Parent Category', select=True),
|
||||
'child_id': fields.one2many('pos.category', 'parent_id', string='Children Categories'),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of product categories."),
|
||||
|
||||
# NOTE: there is no 'default image', because by default we don't show thumbnails for categories. However if we have a thumbnail
|
||||
# for at least one category, then we display a default image on the other, so that the buttons have consistent styling.
|
||||
# In this case, the default image is set by the js code.
|
||||
|
||||
'image': fields.binary("Image",
|
||||
help="This field holds the image used for the category. "\
|
||||
"The image is base64 encoded, and PIL-supported. "\
|
||||
|
@ -1252,21 +1243,40 @@ class pos_category(osv.osv):
|
|||
"Use this field anywhere a small image is required."),
|
||||
}
|
||||
|
||||
def _get_default_image(self, cr, uid, context=None):
|
||||
image_path = openerp.modules.get_module_resource('point_of_sale', 'images', 'default_category_photo.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
|
||||
_defaults = {
|
||||
'image': _get_default_image,
|
||||
}
|
||||
|
||||
pos_category()
|
||||
|
||||
import io, StringIO
|
||||
|
||||
class ean_wizard(osv.osv_memory):
|
||||
_name = 'pos.ean_wizard'
|
||||
_columns = {
|
||||
'ean13_pattern': fields.char('Ean13 Pattern', size=32, required=True, translate=True),
|
||||
}
|
||||
def sanitize_ean13(self, cr, uid, ids, context):
|
||||
for r in self.browse(cr,uid,ids):
|
||||
ean13 = openerp.addons.product.product.sanitize_ean13(r.ean13_pattern)
|
||||
m = context.get('active_model')
|
||||
m_id = context.get('active_id')
|
||||
self.pool.get(m).write(cr,uid,[m_id],{'ean13':ean13})
|
||||
return { 'type' : 'ir.actions.act_window_close' }
|
||||
|
||||
class product_product(osv.osv):
|
||||
_inherit = 'product.product'
|
||||
|
||||
|
||||
#def _get_small_image(self, cr, uid, ids, prop, unknow_none, context=None):
|
||||
# result = {}
|
||||
# for obj in self.browse(cr, uid, ids, context=context):
|
||||
# if not obj.product_image:
|
||||
# result[obj.id] = False
|
||||
# continue
|
||||
|
||||
# image_stream = io.BytesIO(obj.product_image.decode('base64'))
|
||||
# img = Image.open(image_stream)
|
||||
# img.thumbnail((120, 100), Image.ANTIALIAS)
|
||||
# img_stream = StringIO.StringIO()
|
||||
# img.save(img_stream, "JPEG")
|
||||
# result[obj.id] = img_stream.getvalue().encode('base64')
|
||||
# return result
|
||||
|
||||
_columns = {
|
||||
'income_pdt': fields.boolean('Point of Sale Cash In', help="This is a product you can use to put cash into a statement for the point of sale backend."),
|
||||
'expense_pdt': fields.boolean('Point of Sale Cash Out', help="This is a product you can use to take cash from a statement for the point of sale backend, exemple: money lost, transfer to bank, etc."),
|
||||
|
@ -1278,7 +1288,16 @@ class product_product(osv.osv):
|
|||
'to_weight' : False,
|
||||
}
|
||||
|
||||
product_product()
|
||||
|
||||
def edit_ean(self, cr, uid, ids, context):
|
||||
return {
|
||||
'name': "Edit Ean",
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'pos.ean_wizard',
|
||||
'target' : 'new',
|
||||
'view_id': False,
|
||||
'context':context,
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,12 +1,40 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="base.user_root" model="res.users">
|
||||
<field name="ean13">0410100000006</field>
|
||||
</record>
|
||||
<record id="base.user_demo" model="res.users">
|
||||
<field name="groups_id" eval="[(4,ref('group_pos_user'))]"/>
|
||||
<field name="ean13">0410200000005</field>
|
||||
</record>
|
||||
<record id="account.cash_journal" model="account.journal">
|
||||
<record id="account.cash_journal" model="account.journal">
|
||||
<field eval="True" name="journal_user"/>
|
||||
</record>
|
||||
<record id="base.user_jsmith" model="res.users">
|
||||
<field name="name">John Smith (Cashier)</field>
|
||||
<field name="login">jsmith</field>
|
||||
<field name="ean13">0410300000004</field>
|
||||
<field name="groups_id" eval="[(4,ref('group_pos_manager'))]"/>
|
||||
</record>
|
||||
<record id="base.user_jdoe" model="res.users">
|
||||
<field name="name">John Doe (Cashier)</field>
|
||||
<field name="login">jdoe</field>
|
||||
<field name="ean13">0410400000003</field>
|
||||
<field name="groups_id" eval="[(4,ref('group_pos_manager'))]"/>
|
||||
</record>
|
||||
<record id="base.user_jbloggs" model="res.users">
|
||||
<field name="name">Joe Bloggs (Client)</field>
|
||||
<field name="login">jbloggs</field>
|
||||
<field name="ean13">0420100000005</field>
|
||||
<field name="groups_id" eval="[(4,ref('group_pos_user'))]"/>
|
||||
</record>
|
||||
<record id="base.user_bsoap" model="res.users">
|
||||
<field name="name">Bob Soap (Client)</field>
|
||||
<field name="login">bsoap</field>
|
||||
<field name="ean13">0420200000004</field>
|
||||
<field name="groups_id" eval="[(4,ref('group_pos_user'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Resource: pos.category -->
|
||||
|
||||
|
@ -154,6 +182,7 @@
|
|||
<field name="list_price">1.98</field>
|
||||
<field name="name">Boni Oranges</field>
|
||||
<field name="to_weight">True</field>
|
||||
<field name="ean13">2100002000003</field>
|
||||
<field name="pos_categ_id" ref="oranges"/>
|
||||
<field name="uom_id" ref="product.product_uom_kgm" />
|
||||
<field name="uom_po_id" ref="product.product_uom_kgm" />
|
||||
|
@ -248,6 +277,7 @@
|
|||
<field name="list_price">5.10</field>
|
||||
<field name="name">Fishing</field>
|
||||
<field name="to_weight">True</field>
|
||||
<field name="ean13">2300001000008</field>
|
||||
<field name="pos_categ_id" ref="rouges_noyau_fruits"/>
|
||||
<field name="uom_id" ref="product.product_uom_kgm" />
|
||||
<field name="uom_po_id" ref="product.product_uom_kgm" />
|
||||
|
@ -316,6 +346,7 @@
|
|||
<field name="list_price">1.28</field>
|
||||
<field name="name">Onions</field>
|
||||
<field name="to_weight">True</field>
|
||||
<field name="ean13">2100001000004</field>
|
||||
<field name="pos_categ_id" ref="oignons_ail_echalotes"/>
|
||||
<field name="uom_id" ref="product.product_uom_kgm" />
|
||||
<field name="uom_po_id" ref="product.product_uom_kgm" />
|
||||
|
@ -389,6 +420,7 @@
|
|||
<record id="coca_regular_33cl" model="product.product">
|
||||
<field name="list_price">0.51</field>
|
||||
<field name="name">Coca-Cola Regular 33cl</field>
|
||||
<field name="ean13">5449000000996</field>
|
||||
<field name="pos_categ_id" ref="coke"/>
|
||||
<field name="image">/9j/4AAQSkZJRgABAAEBLAEsAAD/2wCEAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9PjsBCwoKDg0OHBYWHCgoKCgoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O//AABEIAGQAOAMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/APZSQoJJwByTQBCt1HIxVOSOvtQBBe36WkDyySLGqAse5wKB2M1fEqHDYkZCu7ds4xQFi/Zaql7brPCVdGzjBweDjvQFix9ujVgsmULdM9/oelAiwrB1DKcgjINAFTVL6DT9PluLggIqnI9amUlFXZrQoyrTUY7s5OLWpJbINIs1ozjO6ICRfy4IrGOIT3R3VsslGTUJJ/g/8jPkngaXzZ9Wif2nDrn8wRWqq031OZ4LEL7D+Wo0ahp6uP8AiYaf5f8Ac81cflt/pT9pDuifqtf+SX3MVby2kuPMg1aBPRYSzlfYYGKTq0+5SwWJ/kf3WNy4muLTTUkJkvGlQspYCNcYHXqT1/8A1UqlTlV0h4fC+1m1J2szY8NanHquiQTLtWRB5cqD+Fhwf8fxopT543FjsK8PWcenT0OU8dXUlx4gtNK8wJF5aytlsbiWI/p+PHpXPipNySPZyWlGGHnVtd3t+A6bakaqvQDArJhC7d2Ub1AkJ3gcrke4qZaG9F3locBfMr3blVGAalI+joxtBHVeFirWwIUD6CnHc8fMk1I76JkudJj3n/Uttb6dv6V2RtKHofNyTp13bqZWgXMVp4xbT7NgIZomeRAcjI6GppSSqWR242nKpg/aT3TsjG+IJ2+NLY562i/+hNWeJ+M7sj1wUv8AF+iOTGq3trd7VuJDGH5TOQRmsEe08NTnDZXsdHrtzLcaLbm2eJmMzCBVJHmxMMgjnOQwYEZJycdxW9SKcVY8bBJQry5r7a+TWmvk1Zp9vmZFjoNlqGhwXEt6LK7mkdUeUZicg8KT/C1KMFKCd7M66+ZVqOIlFR5opLbdefmixPpuqeH7Ge4VZ4kDKoUhXVSe+7HzAjoeOeo6ZU6TimzOljKOMqRi2np5p/d0f9INK1u9udL1qKe6dybVWUdMfOAcY/3qVOXuy9C8ThKcK1Fxj9r9H/kaPw+H/FXRe1q9PC/GYZ4/9jf+JFj4h/8AI52h/wCnVf8A0JqrE/GjPIv9yn/i/RHGSQNPfCNMbnfaM+5rnWrse4pqFO76I39X1TSdL1A6GbQ3OnQoI5+fmEo6uno3r64ronOMXy20PHw2GxFel7fm5Zt3Xa3Z9127Fy2tZlsprvSpIdas3wZrdx88o/2l7SD+8OuOmetxi7Nx1X9ficdWrH2ihVTpyWz6L0f8r7dPTavqlzYf8Ii8dn/aUQFwgNtOTtgP905/h7jryO1TUcfZO1zbCU6v11OfI/deq6+fr38jn9PJR7he0tuy/lhv/Za5oPf0PZrK6i+0l/l+p1Xw7GfFg9rVv5itsL8Z5We/7p/28S/Ec7PF1m3/AE7L/wChNV4n40TkCvhJr+9+hyDTJFeq8jFVWQEkdRzXNH4j2nFyptLsXte0uOXVJwkPkSPKQGVyyFzyA2c7d2chuhyOnONqsLs4MFipRoxu7pL52XVd7dVuvuvL4UiSVEax2LqFqWeSA5WS4XqArZGPQjp3welOgrrTdGGaScW1P4JWs+i9VZ+qf5Brl/4hutFf7S9wLRZQk0U8IV0bquWAG4e/HPXtkqSqOOuw8DQwdOuuVLmtdNO6a66X0fkZNm25tw/55t/6Ca51uepU0XzX5nWfDZt/it/a1b+a1vhfj+R5Gfq2FX+L/MsfEqPzPFOnrnG63A/8eNaYle+jPh+XLhaj8/0PPrknz5Of4j/Oudn0kPhXodLpUyeIrKKx+1my1i2TZbXAcqJ0/uMR3Hatov2itezPExcHg6jny81OTu1vZ90NstMaCJbGY2+n6rBIzYu0AW4B6bZOoI6cGiELK2zM6+JU5c6vODX2Xt6r/NEGq6vq2paNKj3Mnk28qpc28gBKNztO7GSuR3OQcdampOco7muEwuHo101FXabT799Nr+n4GXo5LX8cQ/jyv5g1lBXaPSxNlSb7HW/C47vFEv8A16v/AOhLW2G+P5HlcR6YVf4v0ZpfEhf+Km0pvWIj/wAerTEfGjkyF/7NV9Tzi5/4+JM/3j/OuZn1EPhXoafhq1mu5b6KGW3jLWpXNwPlyWULhv4WyQQfUVdKLd/Q87M6saag2m/e6b7O+nVW3RuJrerafbNZ+INMj1JIRl0mH7xF/vZIIYe4/E1sqk0rSVzyZYPD1Z8+HqOF+23p3T8vuMzVvEdpe6VJp+kaQllA7LJOwxlsHgce+KzqVU42irHbg8vqU6yqVajk9kUfC8XneI7KPrmT+hqKKvNHdmMuXCzfkdP8K+fFEx7C0b/0JK0w3x/I83iP/do/4v0Zp/EzP9u6QV67G7e4q8T8SOTh+3sK1/L9Tzi9QR3cqhg2G6iuaW59PSleCZo+GEuPt8skLwCOOL9+lxnZIhIBBwOnIOe2M1VK/McGaSh7NJp3b0tunvp/l12Oy0W4t5fM+yalA1rEGVrS+Ic2zYI+V8/Mvb0wetddNp7PTz6HzuMhONueD5nb3o6c3quj/U5e401IfAQvFaJXmvizYP3lG5QF9ccn8a55w/dX8z2KWIcsx5NbKH52eongGEzeLrQ44jDuf++SP5kVOGV6iNs7ny4Kfnb8zc+FA/4qS79rVv8A0Na0wy/efI5OJH/s8P8AF+jND4mNjxBpABx8jc/jV4j4kc+QL9xV+R59er5upugO3e4GW7Z71yvVn0dJ8tFPyNa10uXStUeay1FWktUdnjERMnysEZWjz05z16c1pGDjK6Z5lbExxFFKcNJNa301V00/61NaaDwta3gv5RcWnygSwxLuhcsuSmMZXr0OOlbctNO+x50amPqQ5FaXZvRqz38/VXOYvLoz+HrKGMkRW9xMAp9DtIz+ZrCbvBep69Cny4mbe7jH9U/0Oj+GNsDf318w4ghCA+7HP/staYRe82cHEdT91CHd/l/w5rfC3TZba/kvJAdtzbNs9MB1zVYaOt/Iw4hxMZpQX2WvyY74lRyHxLpUgU7PKOGxnkNk/pijEfGgyGUfq1VeZ57qY238w56965pbn0lB3pI6W1jm1+KLWNIl8vXLJQJ4sj9+AMBxnjJHBHf+eyTn70d0eHWccJJ0aqvSls+3l/kEGseG2upptV0y4srxlZLiGIHy5SeuVPQ559jzmqjOm3qrEVMJjVFKlNSj0b3XzOdtoTNpGpOisIYXikBPY5Kgfkx/KsbXiz1JS5a9NPdpr8L/AKHoHhi0/sXwBc3kg2yTwyTn6bcKP6/jXVQjyUmz57Mav1nMowWyaX46mv4Jkid7ZIoyPL06Pe/GCSE/wP5GrpWtH0OLMIy9rVb61P8AP/gHTappNnrFqba8i3qDlWBwyH1B7GrnBSVmcmHxFShLmgzzTxJ8OprWRri3vg6N084Yx9SOK5pYZ9GfQ4XiNRjacPu/yf8Amc1BpuoaTdJdW9zGssZyro+B/wCPYzUKjUi7o6amc4HEQcZ3s+6/yN3/AISa11CMJ4g0S2uZFGPNhljyfwzkfnW2sviieW1Sou9DEWXZ3/y/QjnuLXVUh0uysU0zS/NEk77wWkx9M/5xSlTcvdSsi6eMp0G6sqvPO1lo7I7prBPEejvp8BNvauFQyDBwoI4XqO2K3lFSjY8nD4mVGsqlrtfmbOi6HYaDZi1sItinlmJyzn1JpU6cYKyFisXVxM+abuaB6mrZziEBhggEHsaAM668PaPekm406Bye+3H8qVkO7M5vAPhlm3HTh9PMb/GiwcxetPDGh2JBt9MgUjoSu4/rmiyC7NQAKAFAAHQCmIUUIAAA/9k=</field>
|
||||
</record>
|
||||
|
@ -1022,3 +1054,4 @@
|
|||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
|
|
@ -55,10 +55,14 @@
|
|||
</group>
|
||||
</form>
|
||||
</field>
|
||||
<group class="oe_subtotal_footer">
|
||||
<group class="oe_subtotal_footer oe_right" colspan="2" name="order_total">
|
||||
<field name="amount_tax"/>
|
||||
<field name="amount_total"/>
|
||||
<button name="button_dummy" string="Update" class="oe_link" states="draft"/>
|
||||
<div class="oe_subtotal_footer_separator oe_inline">
|
||||
<label for="amount_total" />
|
||||
<button name="button_dummy"
|
||||
states="draft" string="(update)" type="object" class="oe_edit_only oe_link"/>
|
||||
</div>
|
||||
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Payments">
|
||||
|
@ -630,6 +634,9 @@
|
|||
<field name="expense_pdt"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="ean13" position="after">
|
||||
<button name="edit_ean" type="object" string="Edit" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
@ -773,10 +780,10 @@
|
|||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="shop_id" widget="selection" />
|
||||
<field name="shop_id" widget="selection" groups="stock.group_locations" />
|
||||
<field name="journal_id" widget="selection" />
|
||||
<field name="sequence_id" readonly="1"/>
|
||||
<field name="group_by" />
|
||||
<field name="sequence_id" readonly="1" groups="base.group_no_one" />
|
||||
<field name="group_by" groups="account.group_account_user" />
|
||||
</group>
|
||||
<separator string="Available Payment Methods" colspan="4"/>
|
||||
<field name="journal_ids" colspan="4" nolabel="1">
|
||||
|
@ -791,14 +798,11 @@
|
|||
<group string="Material Interfaces" >
|
||||
<group>
|
||||
<field name="iface_self_checkout" />
|
||||
<field name="iface_websql" />
|
||||
<field name="iface_led" />
|
||||
<field name="iface_cashdrawer" />
|
||||
<field name="iface_payment_terminal" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="iface_electronic_scale" />
|
||||
<field name="iface_barscan" />
|
||||
<field name="iface_vkeyboard" />
|
||||
<field name="iface_print_via_proxy" />
|
||||
</group>
|
||||
|
@ -877,7 +881,7 @@
|
|||
class="oe_highlight"/>
|
||||
<button name="close" type="workflow" string="Validate Closing & Post Entries" states="closing_control"
|
||||
class="oe_highlight"/>
|
||||
<button name="open_frontend_cb" type="object" string="Start Selling" states="opened"/>
|
||||
<button name="open_frontend_cb" type="object" string="Continue Selling" states="opened"/>
|
||||
<div class="oe_right">
|
||||
<field name="state" widget="statusbar" statusbar_visible="opening_control,opened,closing_control,closed" nolabel="1"/>
|
||||
</div>
|
||||
|
@ -888,7 +892,7 @@
|
|||
<button name="%(action_pos_box_out)d" string="Take Money Out" type="action" states="opened,closing_control"/>
|
||||
</div>
|
||||
<h1 class="oe_title">
|
||||
Point of Sale Session:
|
||||
Session:
|
||||
<field name="name" attrs="{'invisible': [('name','=','/')]}" class="oe_inline"/>
|
||||
</h1>
|
||||
<field name="has_opening_control" invisible="1" />
|
||||
|
@ -1057,5 +1061,20 @@
|
|||
parent="menu_point_of_sale"
|
||||
id="menu_pos_session_opening" sequence="0"/>
|
||||
|
||||
<record model="ir.ui.view" id="pos_ean13_generator">
|
||||
<field name="name">pos.ean_wizard</field>
|
||||
<field name="model">pos.ean_wizard</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Ean13 Generator" version="7.0">
|
||||
<field name="ean13_pattern"/>
|
||||
<footer>
|
||||
<button name="sanitize_ean13" type="object" string="Apply"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -37,14 +37,14 @@ class pos_sales_user(report_sxw.rml_parse):
|
|||
dt1 = form['date_start'] + ' 00:00:00'
|
||||
dt2 = form['date_end'] + ' 23:59:59'
|
||||
data={}
|
||||
self.cr.execute("select po.name as pos,po.date_order,ru.name as user,po.state,rc.name " \
|
||||
"from pos_order as po,res_users as ru,res_company as rc " \
|
||||
self.cr.execute("select po.name as pos,po.date_order,rp.name as user,po.state,rc.name " \
|
||||
"from pos_order as po,res_users as ru,res_company as rc, res_partner as rp " \
|
||||
"where po.date_order >= %s and po.date_order <= %s " \
|
||||
"and po.company_id=rc.id and po.user_id=ru.id and po.user_id IN %s " \
|
||||
"and po.company_id=rc.id and po.user_id=ru.id and po.user_id IN %s and ru.partner_id = rp.id" \
|
||||
,(dt1,dt2,tuple(form['user_id'])))
|
||||
|
||||
return self.cr.dictfetchall()
|
||||
|
||||
report_sxw.report_sxw('report.pos.sales.user', 'pos.order', 'addons/point_of_sale/report/pos_sales_user.rml', parser=pos_sales_user,header='internal')
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,38 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
from osv import osv, fields
|
||||
import math
|
||||
import openerp.addons.product.product
|
||||
|
||||
def is_pair(x):
|
||||
return not x%2
|
||||
# This code is a duplicate of product#check_ean function
|
||||
def check_ean(eancode):
|
||||
if not eancode:
|
||||
return True
|
||||
if len(eancode) <> 13:
|
||||
return False
|
||||
try:
|
||||
int(eancode)
|
||||
except:
|
||||
return False
|
||||
oddsum=0
|
||||
evensum=0
|
||||
total=0
|
||||
eanvalue=eancode
|
||||
reversevalue = eanvalue[::-1]
|
||||
finalean=reversevalue[1:]
|
||||
|
||||
for i in range(len(finalean)):
|
||||
if is_pair(i):
|
||||
oddsum += int(finalean[i])
|
||||
else:
|
||||
evensum += int(finalean[i])
|
||||
total=(oddsum * 3) + evensum
|
||||
|
||||
check = int(10 - math.ceil(total % 10.0)) %10
|
||||
|
||||
if check != int(eancode[-1]):
|
||||
return False
|
||||
return True
|
||||
|
||||
class res_users(osv.osv):
|
||||
_inherit = 'res.users'
|
||||
|
@ -43,10 +13,22 @@ class res_users(osv.osv):
|
|||
|
||||
def _check_ean(self, cr, uid, ids, context=None):
|
||||
return all(
|
||||
check_ean(user.ean13) == True
|
||||
openerp.addons.product.product.check_ean(user.ean13) == True
|
||||
for user in self.browse(cr, uid, ids, context=context)
|
||||
)
|
||||
|
||||
def edit_ean(self, cr, uid, ids, context):
|
||||
return {
|
||||
'name': "Edit Ean",
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'pos.ean_wizard',
|
||||
'target' : 'new',
|
||||
'view_id': False,
|
||||
'context':context,
|
||||
}
|
||||
|
||||
_constraints = [
|
||||
(_check_ean, "Error: Invalid ean code", ['ean13'],),
|
||||
]
|
||||
|
|
|
@ -20,8 +20,11 @@
|
|||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Point Of Sale">
|
||||
<field name="ean13" />
|
||||
<field name="pos_config" />
|
||||
<group>
|
||||
<field name="pos_config" />
|
||||
<field name="ean13" />
|
||||
<button name="edit_ean" type="object" string="Edit" />
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
|
|
|
@ -60,7 +60,8 @@ access_product_uom_manager,product.uom manager,product.model_product_uom,group_p
|
|||
access_res_partner_manager,res.partner manager,base.model_res_partner,group_pos_manager,1,0,0,0
|
||||
access_product_category_manager,product.category manager,product.model_product_category,group_pos_manager,1,1,1,1
|
||||
access_product_pricelist_manager,product.pricelist manager,product.model_product_pricelist,group_pos_manager,1,0,0,0
|
||||
access_product_category_pos_manager,pos.category manager,model_pos_category,group_pos_manager,1,1,1,"1"""
|
||||
access_product_category_pos_user,pos.category user,model_pos_category,group_pos_user,1,0,0,"0"""
|
||||
access_product_category_pos_manager,pos.category manager,model_pos_category,group_pos_manager,1,1,1,1
|
||||
access_product_category_pos_user,pos.category user,model_pos_category,group_pos_user,1,0,0,0
|
||||
access_pos_session_user,pos.session user,model_pos_session,group_pos_user,1,1,1,0
|
||||
access_pos_config_user,pos.config user,model_pos_config,group_pos_user,1,1,1,0
|
||||
access_ir_sequence_manager,ir.sequence manager,base.model_ir_sequence,group_pos_manager,1,1,1,1
|
||||
|
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -31,6 +31,7 @@
|
|||
background: -ms-linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0));
|
||||
background: linear-gradient(top,rgba(0,0,0,0.09),rgba(0,0,0,0));
|
||||
}
|
||||
|
||||
.point-of-sale .darker-shadow-top{
|
||||
position: absolute;
|
||||
top:0;
|
||||
|
@ -42,6 +43,7 @@
|
|||
background: -ms-linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0));
|
||||
background: linear-gradient(top,rgba(0,0,0,0.15),rgba(0,0,0,0));
|
||||
}
|
||||
|
||||
/* ********* The black loading screen ********* */
|
||||
|
||||
.point-of-sale .loader{
|
||||
|
@ -156,11 +158,11 @@
|
|||
}
|
||||
|
||||
.point-of-sale #rightheader button {
|
||||
color: black;
|
||||
height:29px;
|
||||
margin:2px;
|
||||
color: #273072;
|
||||
height:27px;
|
||||
margin:3px;
|
||||
margin-right:0px;
|
||||
border: 1px solid black;
|
||||
border: 1px solid #353A7E;
|
||||
background: #7f82ac;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#b2b3d7), to(#7f82ac));
|
||||
background: -moz-linear-gradient(#b2b3d7, #7f82ac);
|
||||
|
@ -187,6 +189,33 @@
|
|||
font-weight: 900;
|
||||
}
|
||||
|
||||
/* c) The session buttons */
|
||||
|
||||
.point-of-sale #rightheader .header-button{
|
||||
float:right;
|
||||
height:32px;
|
||||
padding-left:10px;
|
||||
padding-right:10px;
|
||||
border-right: 1px solid #3a3a3a;
|
||||
border-left: 1px solid #3a3a3a;
|
||||
color:#DDD;
|
||||
line-height:32px;
|
||||
text-align:center;
|
||||
cursor: pointer;
|
||||
|
||||
-webkit-transition-property: background;
|
||||
-webkit-transition-duration: 0.2s;
|
||||
-webkit-transition-timing-function: ease-out;
|
||||
}
|
||||
.point-of-sale #rightheader .header-button:last-child{
|
||||
border-left: 1px solid #3a3a3a;
|
||||
}
|
||||
.point-of-sale #rightheader .header-button:hover{
|
||||
background: rgba(0,0,0,0.2);
|
||||
text-shadow: #000 0px 0px 3px;
|
||||
color:#EEE;
|
||||
}
|
||||
|
||||
/* c) The notifications indicator */
|
||||
|
||||
.point-of-sale .oe_pos_synch-notification{
|
||||
|
@ -234,7 +263,8 @@
|
|||
left:0;
|
||||
width:440px;
|
||||
top:0px;
|
||||
bottom:105px;
|
||||
/*bottom:105px;*/
|
||||
bottom:0;
|
||||
border-right: solid 1px #CECBCB;
|
||||
background-color: white;
|
||||
}
|
||||
|
@ -318,7 +348,8 @@
|
|||
.point-of-sale #rightpane {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 105px;
|
||||
/*bottom: 105px;*/
|
||||
bottom:0;
|
||||
left: 440px;
|
||||
right: 0;
|
||||
vertical-align: top;
|
||||
|
@ -454,6 +485,42 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.point-of-sale .category-simple-button{
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
margin-right:10px;
|
||||
padding:5px;
|
||||
|
||||
cursor: pointer;
|
||||
border: 1px solid #cacaca;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #e2e2e2;
|
||||
background: -webkit-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: -moz-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: -ms-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: linear-gradient(#f0f0f0, #e2e2e2);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
}
|
||||
.point-of-sale .category-simple-button:hover {
|
||||
color: white;
|
||||
background: #7f82ac;
|
||||
border: 1px solid #7f82ac;
|
||||
background: -webkit-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: -moz-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: -ms-linear-gradient(#9d9fc5, #7f82ac);
|
||||
background: linear-gradient(#9d9fc5, #7f82ac);
|
||||
|
||||
-webkit-transition-property: background, border;
|
||||
-webkit-transition-duration: 0.2s;
|
||||
-webkit-transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.point-of-sale .category-button .category-img {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
|
@ -463,7 +530,8 @@
|
|||
}
|
||||
|
||||
.point-of-sale .category-button .category-img img {
|
||||
height: 100px;
|
||||
max-height: 100px;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.point-of-sale .category-button .category-name {
|
||||
|
@ -490,6 +558,7 @@
|
|||
position:relative;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
line-height: 100px;
|
||||
font-size: 11px;
|
||||
margin: 5px;
|
||||
width: 120px;
|
||||
|
@ -497,9 +566,9 @@
|
|||
background:#fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
-webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.2);
|
||||
-webkit-box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
-moz-box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
box-shadow: 0px 1px 8px rgba(127,130,172,0.4);
|
||||
}
|
||||
|
||||
.point-of-sale .product .product-img {
|
||||
|
@ -511,7 +580,8 @@
|
|||
}
|
||||
|
||||
.point-of-sale .product .product-img img {
|
||||
height: 100px;
|
||||
max-height: 100px;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.point-of-sale .product .price-tag {
|
||||
|
@ -520,6 +590,7 @@
|
|||
right: 2px;
|
||||
vertical-align: top;
|
||||
color: white;
|
||||
line-height: 14px;
|
||||
background: #7f82ac;
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
|
@ -533,6 +604,7 @@
|
|||
box-sizing: border-box;
|
||||
bottom:0;
|
||||
top:auto;
|
||||
line-height: 14px;
|
||||
width:100%;
|
||||
background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1));
|
||||
|
@ -598,8 +670,16 @@
|
|||
display: inline-block;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.point-of-sale .greyed-out{
|
||||
color: #AAA;
|
||||
}
|
||||
.point-of-sale .pos-step-container input{
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.point-of-sale .pos-payment-container {
|
||||
text-align: left;
|
||||
min-width: 500px;
|
||||
}
|
||||
.point-of-sale .pos-payment-container .left-block{
|
||||
display: inline-block;
|
||||
|
@ -648,8 +728,17 @@
|
|||
width: 300px;
|
||||
background-color: white;
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
padding: 15px;
|
||||
padding-bottom:30px;
|
||||
display: inline-block;
|
||||
font-family: "Inconsolata";
|
||||
-webkit-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
box-shadow: 0px 5px 16px rgba(0,0,0, 0.3);
|
||||
}
|
||||
.point-of-sale .pos-sale-ticket .emph{
|
||||
font-size: 20px;
|
||||
margin:5px;
|
||||
}
|
||||
.point-of-sale .pos-sale-ticket table {
|
||||
width: 100%;
|
||||
|
@ -660,18 +749,18 @@
|
|||
}
|
||||
|
||||
@media print {
|
||||
#oe_header, #oe_menu, .point-of-sale #topheader, .point-of-sale #leftpane {
|
||||
display: none;
|
||||
.point-of-sale #topheader, .point-of-sale #leftpane {
|
||||
display: none !important;
|
||||
}
|
||||
.point-of-sale #content {
|
||||
top: 0px;
|
||||
top: 0px !important;
|
||||
}
|
||||
.point-of-sale #rightpane {
|
||||
left: 0px;
|
||||
left: 0px !important;
|
||||
background-color: white;
|
||||
}
|
||||
#receipt-screen header {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
#receipt-screen {
|
||||
text-align: left;
|
||||
|
@ -761,6 +850,28 @@
|
|||
font-family: "Inconsolata";
|
||||
}
|
||||
|
||||
/* e) The Welcome Screen */
|
||||
.point-of-sale .goodbye-message{
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top:30%;
|
||||
width:500px;
|
||||
height:400px;
|
||||
margin-left: -250px;
|
||||
margin-top: -200px;
|
||||
padding:10px;
|
||||
padding-top:20px;
|
||||
text-align:center;
|
||||
font-size:20px;
|
||||
font-weight:bold;
|
||||
background-color: #F0EEEE;
|
||||
border: 1px solid #E0DDDD;
|
||||
-webkit-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
-ms-box-shadow: 0px 10px 20px rgba(0,0,0, 0.3);
|
||||
z-index:1150;
|
||||
}
|
||||
|
||||
/* ********* The OrderWidget ********* */
|
||||
|
||||
.point-of-sale .order-container{
|
||||
|
@ -846,6 +957,10 @@
|
|||
-moz-transition: background 50ms ease-in-out;
|
||||
transition: background 50ms ease-in-out;
|
||||
}
|
||||
.point-of-sale .order .orderline.empty:hover{
|
||||
background: transparent;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.point-of-sale .order .orderline.selected{
|
||||
background: rgba(140,143,183,0.2);
|
||||
|
@ -933,9 +1048,9 @@
|
|||
background: -moz-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: -ms-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: linear-gradient(#f0f0f0, #e2e2e2);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.3);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
}
|
||||
.point-of-sale .pos-actionbar .button .label{
|
||||
margin-top: 37px;
|
||||
|
@ -957,6 +1072,23 @@
|
|||
-webkit-transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
.point-of-sale .pos-actionbar .button.disabled{
|
||||
color:#AAA;
|
||||
}
|
||||
.point-of-sale .pos-actionbar .button.disabled:hover{
|
||||
border: 1px solid #cacaca;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #e2e2e2;
|
||||
background: -webkit-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: -moz-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: -ms-linear-gradient(#f0f0f0, #e2e2e2);
|
||||
background: linear-gradient(#f0f0f0, #e2e2e2);
|
||||
-webkit-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
-moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
box-shadow: 0px 2px 2px rgba(0,0,0, 0.1);
|
||||
}
|
||||
|
||||
.point-of-sale .pos-actionbar .button.rightalign{
|
||||
float:right;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 46 KiB |
|
@ -0,0 +1,984 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="48"
|
||||
overflow="visible"
|
||||
enable-background="new 0 0 128 129.396"
|
||||
xml:space="preserve"
|
||||
id="svg2"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="scale.svg"
|
||||
version="1.0"
|
||||
inkscape:export-filename="/home/fva/Code/openerp/src/addons/trunk-pos-fva/point_of_sale/static/src/img/scale.png"
|
||||
inkscape:export-xdpi="600"
|
||||
inkscape:export-ydpi="600"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||
id="metadata367"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:title></dc:title><dc:creator><cc:Agent><dc:title>Jakub Steiner</dc:title></cc:Agent></dc:creator><dc:source>http://jimmac.musichall.cz</dc:source><dc:subject><rdf:Bag><rdf:li>home</rdf:li><rdf:li>return</rdf:li><rdf:li>go</rdf:li><rdf:li>default</rdf:li><rdf:li>user</rdf:li><rdf:li>directory</rdf:li></rdf:Bag></dc:subject><dc:contributor><cc:Agent><dc:title>Tuomas Kuosmanen</dc:title></cc:Agent></dc:contributor></cc:Work><cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><defs
|
||||
id="defs365"><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4977"><stop
|
||||
style="stop-color:#ff0000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4979" /><stop
|
||||
style="stop-color:#ff0000;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop4981" /></linearGradient><inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective92" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5031"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5060"><stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5062" /><stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5064" /></linearGradient><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient5029"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><linearGradient
|
||||
id="linearGradient5048"><stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="0"
|
||||
id="stop5050" /><stop
|
||||
id="stop5056"
|
||||
offset="0.5"
|
||||
style="stop-color:black;stop-opacity:1;" /><stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5052" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient5027"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" /><linearGradient
|
||||
id="linearGradient2406"><stop
|
||||
style="stop-color:#7c7e79;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2408" /><stop
|
||||
id="stop2414"
|
||||
offset="0.1724138"
|
||||
style="stop-color:#848681;stop-opacity:1;" /><stop
|
||||
style="stop-color:#898c86;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2410" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2390"><stop
|
||||
style="stop-color:#919191;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2392" /><stop
|
||||
style="stop-color:#919191;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2394" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2378"><stop
|
||||
style="stop-color:#575757;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2380" /><stop
|
||||
style="stop-color:#575757;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2382" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2368"><stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2370" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2372" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2349"><stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2351" /><stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2353" /></linearGradient><linearGradient
|
||||
id="linearGradient2341"><stop
|
||||
id="stop2343"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:1;" /><stop
|
||||
id="stop2345"
|
||||
offset="1"
|
||||
style="stop-color:#000000;stop-opacity:0;" /></linearGradient><linearGradient
|
||||
id="linearGradient2329"><stop
|
||||
style="stop-color:#000000;stop-opacity:0.18556701;"
|
||||
offset="0"
|
||||
id="stop2331" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2333" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2319"><stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2321" /><stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2323" /></linearGradient><linearGradient
|
||||
id="linearGradient2307"><stop
|
||||
style="stop-color:#edd400;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2309" /><stop
|
||||
style="stop-color:#998800;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop2311" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2299"><stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2301" /><stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2303" /></linearGradient><linearGradient
|
||||
id="XMLID_2_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="80.223602"
|
||||
y1="117.5205"
|
||||
x2="48.046001"
|
||||
y2="59.7995"
|
||||
gradientTransform="matrix(0.314683,0.000000,0.000000,0.314683,4.128264,3.742874)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#CCCCCC"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="0.9831"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop19" />
|
||||
<midPointStop
|
||||
offset="0"
|
||||
style="stop-color:#CCCCCC"
|
||||
id="midPointStop48" />
|
||||
<midPointStop
|
||||
offset="0.5"
|
||||
style="stop-color:#CCCCCC"
|
||||
id="midPointStop50" />
|
||||
<midPointStop
|
||||
offset="0.9831"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="midPointStop52" />
|
||||
</linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#XMLID_2_"
|
||||
id="linearGradient1514"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.336922,0,0,0.166888,143.49433,15.46151)"
|
||||
x1="52.006104"
|
||||
y1="166.1331"
|
||||
x2="14.049017"
|
||||
y2="-42.218513" /><linearGradient
|
||||
id="XMLID_39_"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="64.387703"
|
||||
y1="65.124001"
|
||||
x2="64.387703"
|
||||
y2="35.569"
|
||||
gradientTransform="matrix(0.354101,0,0,0.354101,127.15013,-0.08364921)">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="stop336" />
|
||||
<stop
|
||||
offset="0.8539"
|
||||
style="stop-color:#FF6200"
|
||||
id="stop338" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#F25D00"
|
||||
id="stop340" />
|
||||
<midPointStop
|
||||
offset="0"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="midPointStop335" />
|
||||
<midPointStop
|
||||
offset="0.5"
|
||||
style="stop-color:#FFFFFF"
|
||||
id="midPointStop337" />
|
||||
<midPointStop
|
||||
offset="0.8539"
|
||||
style="stop-color:#FF6200"
|
||||
id="midPointStop339" />
|
||||
<midPointStop
|
||||
offset="0.5"
|
||||
style="stop-color:#FF6200"
|
||||
id="midPointStop341" />
|
||||
<midPointStop
|
||||
offset="1"
|
||||
style="stop-color:#F25D00"
|
||||
id="midPointStop343" />
|
||||
</linearGradient><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2299"
|
||||
id="radialGradient2305"
|
||||
cx="7.5326638"
|
||||
cy="24.202574"
|
||||
fx="7.5326638"
|
||||
fy="24.202574"
|
||||
r="8.2452128"
|
||||
gradientTransform="matrix(4.100086,0,0,4.201322,100.09639,-78.53967)"
|
||||
gradientUnits="userSpaceOnUse" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2307"
|
||||
id="radialGradient2313"
|
||||
cx="19.985598"
|
||||
cy="36.77816"
|
||||
fx="19.985598"
|
||||
fy="36.77816"
|
||||
r="1.0821035"
|
||||
gradientTransform="matrix(1.125263,0,0,0.982744,122.08278,0.565787)"
|
||||
gradientUnits="userSpaceOnUse" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2319"
|
||||
id="radialGradient2325"
|
||||
cx="20.443665"
|
||||
cy="37.425829"
|
||||
fx="20.443665"
|
||||
fy="37.425829"
|
||||
r="1.0821035"
|
||||
gradientTransform="matrix(1.125263,0,0,0.982744,122.08278,0.731106)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2329"
|
||||
id="linearGradient2335"
|
||||
x1="17.602522"
|
||||
y1="26.057423"
|
||||
x2="17.682528"
|
||||
y2="32.654099"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.898789,0,0,1.071914,125.98948,-2.080838)" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2341"
|
||||
id="radialGradient2339"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(4.100086,0,0,-4.201322,120.31334,105.3535)"
|
||||
cx="11.68129"
|
||||
cy="19.554111"
|
||||
fx="11.68129"
|
||||
fy="19.554111"
|
||||
r="8.2452126" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2349"
|
||||
id="radialGradient2355"
|
||||
cx="24.023088"
|
||||
cy="40.56913"
|
||||
fx="24.023088"
|
||||
fy="40.56913"
|
||||
r="16.28684"
|
||||
gradientTransform="matrix(1.000000,0.000000,0.000000,0.431250,1.157278e-15,23.07369)"
|
||||
gradientUnits="userSpaceOnUse" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2368"
|
||||
id="radialGradient2374"
|
||||
cx="29.913452"
|
||||
cy="30.442923"
|
||||
fx="29.913452"
|
||||
fy="30.442923"
|
||||
r="4.0018832"
|
||||
gradientTransform="matrix(3.751495,0,0,3.147818,43.502383,-65.70704)"
|
||||
gradientUnits="userSpaceOnUse" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2378"
|
||||
id="radialGradient2384"
|
||||
cx="24.195112"
|
||||
cy="10.577631"
|
||||
fx="24.195112"
|
||||
fy="10.577631"
|
||||
r="15.242914"
|
||||
gradientTransform="matrix(1.125263,-3.585417e-8,4.269819e-8,1.340059,122.50475,1.355395)"
|
||||
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2390"
|
||||
id="linearGradient2396"
|
||||
x1="30.603519"
|
||||
y1="37.337803"
|
||||
x2="30.603519"
|
||||
y2="36.112415"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.263867,0,0,0.859794,-6.499556,8.390924)" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2406"
|
||||
id="linearGradient2412"
|
||||
x1="17.850183"
|
||||
y1="28.939463"
|
||||
x2="19.040216"
|
||||
y2="41.03223"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.888785,0,0,1.08932,127.92244,-1.524336)" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient4689"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient4691"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient4693"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5048"
|
||||
id="linearGradient4894"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
|
||||
x1="302.85715"
|
||||
y1="366.64789"
|
||||
x2="302.85715"
|
||||
y2="609.50507" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient4896"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5060"
|
||||
id="radialGradient4898"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
|
||||
cx="605.71429"
|
||||
cy="486.64789"
|
||||
fx="605.71429"
|
||||
fy="486.64789"
|
||||
r="117.14286" /><filter
|
||||
inkscape:collect="always"
|
||||
id="filter4971"
|
||||
x="-0.064853556"
|
||||
width="1.1297071"
|
||||
y="-1.9456067"
|
||||
height="4.8912134"><feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.81066946"
|
||||
id="feGaussianBlur4973" /></filter><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4977"
|
||||
id="linearGradient4983"
|
||||
x1="23.6875"
|
||||
y1="32"
|
||||
x2="23.75"
|
||||
y2="45.25"
|
||||
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||
inkscape:cy="-2.746436"
|
||||
inkscape:cx="31.130127"
|
||||
inkscape:zoom="8"
|
||||
inkscape:window-height="1176"
|
||||
inkscape:window-width="1855"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="0.21568627"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-x="65"
|
||||
inkscape:window-y="24"
|
||||
inkscape:current-layer="svg2"
|
||||
fill="#555753"
|
||||
showgrid="true"
|
||||
stroke="#a40000"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:window-maximized="1"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3818" /></sodipodi:namedview>
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g5022"
|
||||
transform="matrix(0.02158196,0,0,0.01859457,168.63396,41.63767)"><rect
|
||||
y="-150.69685"
|
||||
x="-1559.2523"
|
||||
height="478.35718"
|
||||
width="1339.6335"
|
||||
id="rect4173"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /><path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path5058"
|
||||
d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
|
||||
id="path5018"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0" /></g><path
|
||||
style="color:#000000;fill:url(#linearGradient1514);fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:1.0000006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m 147.13103,8.1833733 5.95746,0 c 0.83973,0 13.88647,15.4353277 13.88647,16.3406587 l -0.44352,18.496745 c 0,0.905333 -0.67603,1.634177 -1.51576,1.634177 l -31.45728,0 c -0.83973,0 -1.51576,-0.728844 -1.51576,-1.634177 l 0.0565,-18.496745 c 0,-0.905331 14.19218,-16.3406587 15.03191,-16.3406587 z"
|
||||
id="rect1512"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:none"
|
||||
id="path5"
|
||||
d="m 172.47503,45.735573 -45.3249,0 0,-45.32489746 45.3249,0 0,45.32489746 z"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:url(#linearGradient2335);fill-opacity:1;fill-rule:evenodd"
|
||||
id="path2327"
|
||||
d="m 148.51145,29 -0.0457,15.090942 -11.84279,0 L 136.51145,29 l 12,0 z"
|
||||
clip-rule="evenodd"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
id="path2357"
|
||||
d="m 147.29191,9.405584 5.5591,0 c 0.78358,0 13.00087,14.399588 13.00087,15.244172 l -0.34716,18.212311 c 0,0.459259 -0.14374,0.653465 -0.51237,0.653465 l -31.38721,0.01428 c -0.36863,0 -0.58396,-0.07992 -0.58396,-0.45355 l 0.21534,-18.426506 c 0,-0.844584 13.27181,-15.244172 14.05539,-15.244172 z"
|
||||
style="opacity:0.3125;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
clip-rule="evenodd"
|
||||
d="m 132.71898,27.943053 -0.0543,2.595194 18.36817,-13.179254 15.28639,11.154428 0.0713,-0.311714 -16.37045,-15.904131 -17.30116,15.645477 z"
|
||||
id="path23"
|
||||
style="opacity:0.2;fill:url(#radialGradient2384);fill-opacity:1;fill-rule:evenodd"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
clip-rule="evenodd"
|
||||
d="m 147.51145,30 0,14.090942 -9.81103,0 L 137.51145,30 l 10,0 z"
|
||||
id="path188"
|
||||
style="fill:url(#linearGradient2412);fill-opacity:1;fill-rule:evenodd"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="opacity:0.40909089;fill:url(#radialGradient2325);fill-opacity:1;fill-rule:evenodd"
|
||||
id="path2315"
|
||||
d="m 145.08831,36.44767 c 0.67279,0 1.21662,0.474605 1.21662,1.058507 0,0.589811 -0.54383,1.068355 -1.21662,1.068355 -0.67227,0 -1.21869,-0.478544 -1.21869,-1.068355 5.2e-4,-0.583902 0.54642,-1.058507 1.21869,-1.058507 z"
|
||||
clip-rule="evenodd"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
clip-rule="evenodd"
|
||||
d="m 144.97377,35.932229 c 0.67279,0 1.21661,0.474605 1.21661,1.058507 0,0.589809 -0.54382,1.068353 -1.21661,1.068353 -0.67228,0 -1.21869,-0.478544 -1.21869,-1.068353 5.2e-4,-0.583902 0.54641,-1.058507 1.21869,-1.058507 z"
|
||||
id="path217"
|
||||
style="fill:url(#radialGradient2313);fill-opacity:1;fill-rule:evenodd"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 149.9592,11.559337 18.92706,17.169868 0.49468,0.391991 0.40368,-0.171385 -0.37287,-0.761673 -0.27762,-0.223436 -19.17493,-15.572306 -19.38951,15.743335 -0.23761,0.14412 -0.21671,0.706786 0.43342,0.129248 0.38456,-0.308423 19.02585,-17.248125 z"
|
||||
id="path342"
|
||||
style="fill:url(#XMLID_39_)"
|
||||
sodipodi:nodetypes="ccccccccccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="fill:#ef2929;stroke:#a40000"
|
||||
id="path362"
|
||||
d="m 149.84162,2.2713382 -21.88174,18.1013368 -0.62473,7.165928 1.99994,2.064323 c 0,0 20.40738,-17.157285 20.62409,-17.327963 l 19.63254,17.54326 1.89843,-2.323997 -1.61579,-7.111374 -19.91518,-18.2159732 -0.11756,0.1044594 z"
|
||||
sodipodi:nodetypes="cccccccccc"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="opacity:0.40909089;color:#000000;fill:url(#radialGradient2305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 128.3528,20.613129 128.06124,27.236494 149.88067,8.980075 149.81034,3.0867443 128.3528,20.613129 z"
|
||||
id="path1536"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="path2337"
|
||||
d="m 149.99522,8.7509884 0.0995,-5.8411017 19.32896,17.6519533 1.49181,6.500812 -20.92023,-18.3116636 z"
|
||||
style="opacity:0.13636367;color:#000000;fill:url(#radialGradient2339);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
style="opacity:0.31818183;color:#000000;fill:none;stroke:#ffffff;stroke-width:0.99999934;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m 152.61368,27.719824 9.04,0 c 0.77059,0 1.39096,0.62037 1.39096,1.390967 l -0.008,9.079221 c 0,0.770596 -0.59632,1.265969 -1.36691,1.265969 l -9.05609,0 c -0.77059,0 -1.39096,-0.620373 -1.39096,-1.390969 l 0,-8.954221 c 0,-0.770597 0.62037,-1.390967 1.39096,-1.390967 z"
|
||||
id="rect2361"
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0" /><rect
|
||||
style="color:#000000;fill:#3465a4;fill-opacity:1;fill-rule:nonzero;stroke:#757575;stroke-width:0.9999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect3263"
|
||||
width="10.001333"
|
||||
height="9.9624557"
|
||||
x="152.01923"
|
||||
y="28.514256"
|
||||
rx="0.38128215"
|
||||
ry="0.38128215" /><path
|
||||
style="opacity:0.39772728;color:#000000;fill:url(#radialGradient2374);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999958;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m 152.61857,34.408261 c 3.61798,0.331177 5.52773,-1.445704 8.86815,-1.55274 l 0.0247,-3.849491 -8.91161,-0.006 0.0187,5.408261 z"
|
||||
id="rect2363"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0" /><g
|
||||
transform="translate(65.937707,2.0108349)"
|
||||
id="g4739"><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#6adb4d;fill-opacity:1;stroke:#34781d;stroke-width:1.05264175;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4741"
|
||||
sodipodi:cx="25.367456"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:ry="5.3033009"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
transform="matrix(0.95416667,0,0,0.94583333,1.405743,0.73519001)" /><path
|
||||
transform="matrix(0.77083333,0,0,0.77916666,6.0564434,2.1576238)"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
sodipodi:ry="5.3033009"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:cx="25.367456"
|
||||
id="path4743"
|
||||
style="fill:none;stroke:#b3ff9a;stroke-width:1.29034114;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" /></g><g
|
||||
id="g4733"
|
||||
transform="translate(76.897863,5.0160386)"><path
|
||||
transform="matrix(0.95416667,0,0,0.94583333,1.405743,0.73519001)"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
sodipodi:ry="5.3033009"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:cx="25.367456"
|
||||
id="path4735"
|
||||
style="fill:#6adb4d;fill-opacity:1;stroke:#34781d;stroke-width:1.05264175;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" /><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#b3ff9a;stroke-width:1.29034114;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4737"
|
||||
sodipodi:cx="25.367456"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:ry="5.3033009"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
transform="matrix(0.77083333,0,0,0.77916666,6.0564434,2.1576238)" /></g><g
|
||||
transform="translate(70.887455,7.0268736)"
|
||||
id="g4727"><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#6adb4d;fill-opacity:1;stroke:#34781d;stroke-width:1.05264175;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4729"
|
||||
sodipodi:cx="25.367456"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:ry="5.3033009"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
transform="matrix(0.95416667,0,0,0.94583333,1.405743,0.73519001)" /><path
|
||||
transform="matrix(0.77083333,0,0,0.77916666,6.0564434,2.1576238)"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
sodipodi:ry="5.3033009"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:cx="25.367456"
|
||||
id="path4731"
|
||||
style="fill:none;stroke:#b3ff9a;stroke-width:1.29034114;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" /></g><g
|
||||
id="g4723"
|
||||
transform="translate(59.662134,5.9662134)"><path
|
||||
transform="matrix(0.95416667,0,0,0.94583333,1.405743,0.73519001)"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
sodipodi:ry="5.3033009"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:cx="25.367456"
|
||||
id="path4719"
|
||||
style="fill:#6adb4d;fill-opacity:1;stroke:#34781d;stroke-width:1.05264175;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="arc" /><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#b3ff9a;stroke-width:1.29034114;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4721"
|
||||
sodipodi:cx="25.367456"
|
||||
sodipodi:cy="8.2694378"
|
||||
sodipodi:rx="5.3033009"
|
||||
sodipodi:ry="5.3033009"
|
||||
d="m 30.670757,8.2694378 c 0,2.9289322 -2.374368,5.3033012 -5.303301,5.3033012 -2.928932,0 -5.3033,-2.374369 -5.3033,-5.3033012 0,-2.9289322 2.374368,-5.3033009 5.3033,-5.3033009 2.928933,0 5.303301,2.3743687 5.303301,5.3033009 z"
|
||||
transform="matrix(0.77083333,0,0,0.77916666,6.0564434,2.1576238)" /></g><g
|
||||
id="g4695"
|
||||
transform="matrix(1.1326331,0,0,0.44340824,65.580189,2.4215088)"><rect
|
||||
style="fill:#8a8a8a;fill-opacity:1;stroke:none"
|
||||
id="rect4697"
|
||||
width="29.256544"
|
||||
height="18.119614"
|
||||
x="10.297243"
|
||||
y="27.449707"
|
||||
rx="1.7190553"
|
||||
ry="4.3911204" /><g
|
||||
id="g4699"><g
|
||||
id="g4701"><rect
|
||||
rx="1.7051755"
|
||||
y="27.517153"
|
||||
x="10.510214"
|
||||
height="17.982044"
|
||||
width="29.020325"
|
||||
id="rect4703"
|
||||
style="fill:none;stroke:#646464;stroke-width:1.41005611;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
ry="4.3556657" /></g><rect
|
||||
rx="0.88575488"
|
||||
y="29.624025"
|
||||
x="11.337327"
|
||||
height="13.83156"
|
||||
width="27.319036"
|
||||
id="rect4705"
|
||||
style="fill:none;stroke:#b3b3b3;stroke-width:1.40048993;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
ry="2.2625546" /></g></g><g
|
||||
transform="matrix(0.01936185,0,0,0.01859457,111.41659,40.621203)"
|
||||
id="g4681"
|
||||
style="display:inline"><rect
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#linearGradient4689);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect4683"
|
||||
width="1339.6335"
|
||||
height="478.35718"
|
||||
x="-1559.2523"
|
||||
y="-150.69685" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient4691);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
|
||||
id="path4685"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path4687"
|
||||
d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient4693);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /></g><g
|
||||
id="g4672"
|
||||
transform="translate(68.942911,-2.9168155)"><rect
|
||||
ry="1.9470588"
|
||||
rx="1.9470588"
|
||||
y="27.449707"
|
||||
x="10.297243"
|
||||
height="18.119614"
|
||||
width="29.256544"
|
||||
id="rect4658"
|
||||
style="fill:#dddddd;fill-opacity:1;stroke:none" /><g
|
||||
id="g4667"><g
|
||||
id="g4664"><rect
|
||||
ry="1.9313381"
|
||||
style="fill:none;stroke:#646464;stroke-width:0.99927008;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4660"
|
||||
width="29.020325"
|
||||
height="17.982044"
|
||||
x="10.510214"
|
||||
y="27.517153"
|
||||
rx="1.9313381" /></g><rect
|
||||
ry="1.0032353"
|
||||
style="fill:none;stroke:#f6f6f6;stroke-width:0.99249077;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4662"
|
||||
width="26.967867"
|
||||
height="16.005489"
|
||||
x="11.532422"
|
||||
y="28.489801"
|
||||
rx="1.0032353" /></g></g><path
|
||||
transform="matrix(1.0023678,0,0,0.95596394,68.883716,-0.0273148)"
|
||||
d="m 35,33 a 10,10 0 1 1 -20,0 10,10 0 1 1 20,0 z"
|
||||
sodipodi:ry="10"
|
||||
sodipodi:rx="10"
|
||||
sodipodi:cy="33"
|
||||
sodipodi:cx="25"
|
||||
id="path4679"
|
||||
style="fill:#b8b8b8;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
sodipodi:type="arc" /><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#b8b8b8;fill-opacity:1;fill-rule:evenodd;stroke:#646464;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path3820"
|
||||
sodipodi:cx="25"
|
||||
sodipodi:cy="33"
|
||||
sodipodi:rx="10"
|
||||
sodipodi:ry="10"
|
||||
d="m 35,33 a 10,10 0 1 1 -20,0 10,10 0 1 1 20,0 z"
|
||||
transform="matrix(0.94933484,0,0,0.95596394,70.209541,-1.4857225)" /><path
|
||||
transform="matrix(0.6928006,0,0,0.69727163,76.6008,8.0344445)"
|
||||
d="m 35,33 a 10,10 0 1 1 -20,0 10,10 0 1 1 20,0 z"
|
||||
sodipodi:ry="10"
|
||||
sodipodi:rx="10"
|
||||
sodipodi:cy="33"
|
||||
sodipodi:cx="25"
|
||||
id="path4590"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:evenodd;stroke:none"
|
||||
sodipodi:type="arc" /><g
|
||||
id="g4644"
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,99.594592,-10.924363)"><rect
|
||||
style="fill:#232323;fill-opacity:1;stroke:none"
|
||||
id="rect4646"
|
||||
width="0.68500972"
|
||||
height="1.1490486"
|
||||
x="24.638252"
|
||||
y="26.853086" /><rect
|
||||
y="37.990021"
|
||||
x="24.660349"
|
||||
height="1.1490486"
|
||||
width="0.68500972"
|
||||
id="rect4648"
|
||||
style="fill:#232323;fill-opacity:1;stroke:none" /></g><g
|
||||
id="g4600"
|
||||
style="fill:#a2a2a2;fill-opacity:1"
|
||||
transform="translate(69.009202,-2.3643883)"><rect
|
||||
style="fill:#a2a2a2;fill-opacity:1;stroke:none"
|
||||
id="rect4602"
|
||||
width="1"
|
||||
height="5.9375"
|
||||
x="40.742825"
|
||||
y="-1.6325631"
|
||||
transform="matrix(0.67898035,0.73415645,-0.73415645,0.67898035,0,0)" /><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#a2a2a2;fill-opacity:1;stroke:none"
|
||||
id="path4604"
|
||||
sodipodi:cx="25.03125"
|
||||
sodipodi:cy="33.03125"
|
||||
sodipodi:rx="1.03125"
|
||||
sodipodi:ry="0.96875"
|
||||
d="M 26.0625,33.03125 C 26.0625,33.566276 25.600794,34 25.03125,34 24.461706,34 24,33.566276 24,33.03125 c 0,-0.535026 0.461706,-0.96875 1.03125,-0.96875 0.569544,0 1.03125,0.433724 1.03125,0.96875 z"
|
||||
transform="matrix(0.95714504,0,0,1.0228099,1.028519,-0.77553647)" /></g><g
|
||||
id="g4596"
|
||||
transform="translate(68.942911,-2.9168155)"><rect
|
||||
transform="matrix(0.67898035,0.73415645,-0.73415645,0.67898035,0,0)"
|
||||
y="-1.6325631"
|
||||
x="40.742825"
|
||||
height="5.9375"
|
||||
width="1"
|
||||
id="rect4592"
|
||||
style="fill:#ff2121;fill-opacity:1;stroke:none" /><path
|
||||
transform="matrix(0.95714504,0,0,1.0228099,1.028519,-0.77553647)"
|
||||
d="M 26.0625,33.03125 C 26.0625,33.566276 25.600794,34 25.03125,34 24.461706,34 24,33.566276 24,33.03125 c 0,-0.535026 0.461706,-0.96875 1.03125,-0.96875 0.569544,0 1.03125,0.433724 1.03125,0.96875 z"
|
||||
sodipodi:ry="0.96875"
|
||||
sodipodi:rx="1.03125"
|
||||
sodipodi:cy="33.03125"
|
||||
sodipodi:cx="25.03125"
|
||||
id="path4594"
|
||||
style="fill:#ff2121;fill-opacity:1;stroke:none"
|
||||
sodipodi:type="arc" /></g><path
|
||||
sodipodi:type="arc"
|
||||
style="fill:none;stroke:#646464;stroke-width:1.37966764;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4608"
|
||||
sodipodi:cx="25"
|
||||
sodipodi:cy="33"
|
||||
sodipodi:rx="10"
|
||||
sodipodi:ry="10"
|
||||
d="m 35,33 a 10,10 0 1 1 -20,0 10,10 0 1 1 20,0 z"
|
||||
transform="matrix(0.74693846,0,0,0.74919978,75.258402,5.3595919)" /><g
|
||||
id="g4628"
|
||||
transform="translate(68.942911,-2.9168155)"><rect
|
||||
y="26.853086"
|
||||
x="24.638252"
|
||||
height="1.1490486"
|
||||
width="0.68500972"
|
||||
id="rect4624"
|
||||
style="fill:#232323;fill-opacity:1;stroke:none" /><rect
|
||||
style="fill:#232323;fill-opacity:1;stroke:none"
|
||||
id="rect4626"
|
||||
width="0.68500972"
|
||||
height="1.1490486"
|
||||
x="24.660349"
|
||||
y="37.990021" /></g><g
|
||||
id="g4632"
|
||||
transform="matrix(0,1,-1,0,126.93079,5.087457)"><rect
|
||||
style="fill:#232323;fill-opacity:1;stroke:none"
|
||||
id="rect4634"
|
||||
width="0.68500972"
|
||||
height="1.1490486"
|
||||
x="24.638252"
|
||||
y="26.853086" /><rect
|
||||
y="37.990021"
|
||||
x="24.660349"
|
||||
height="1.1490486"
|
||||
width="0.68500972"
|
||||
id="rect4636"
|
||||
style="fill:#232323;fill-opacity:1;stroke:none" /></g><rect
|
||||
style="fill:#232323;fill-opacity:1;stroke:none"
|
||||
id="rect4640"
|
||||
width="0.68500972"
|
||||
height="1.1490486"
|
||||
x="-45.50618"
|
||||
y="-93.834114"
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)" /><rect
|
||||
y="-82.697182"
|
||||
x="-45.484081"
|
||||
height="1.1490486"
|
||||
width="0.68500972"
|
||||
id="rect4642"
|
||||
style="fill:#232323;fill-opacity:1;stroke:none"
|
||||
transform="matrix(-0.70710678,0.70710678,-0.70710678,-0.70710678,0,0)" /><g
|
||||
transform="matrix(1.2021267,0,0,0.11694557,63.863529,11.401153)"
|
||||
id="g4707"><rect
|
||||
ry="16.649275"
|
||||
rx="1.6196786"
|
||||
y="27.449707"
|
||||
x="10.297243"
|
||||
height="18.119614"
|
||||
width="29.256544"
|
||||
id="rect4709"
|
||||
style="fill:#d4d4d4;fill-opacity:1;stroke:none" /><g
|
||||
id="g4711"><g
|
||||
id="g4713"><rect
|
||||
ry="16.514845"
|
||||
style="fill:none;stroke:#646464;stroke-width:2.66511464;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4715"
|
||||
width="29.020325"
|
||||
height="17.982044"
|
||||
x="10.510214"
|
||||
y="27.517153"
|
||||
rx="1" /></g></g></g><g
|
||||
id="g4985"
|
||||
transform="translate(0,-11.125)"><g
|
||||
transform="matrix(0.01936185,0,0,0.01859457,41.505849,40.621203)"
|
||||
id="g4874"
|
||||
style="display:inline"><rect
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#linearGradient4894);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
id="rect4876"
|
||||
width="1339.6335"
|
||||
height="478.35718"
|
||||
x="-1559.2523"
|
||||
y="-150.69685" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient4896);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="m -219.61876,-150.68038 c 0,0 0,478.33079 0,478.33079 142.874166,0.90045 345.40022,-107.16966 345.40014,-239.196175 0,-132.026537 -159.436816,-239.134595 -345.40014,-239.134615 z"
|
||||
id="path4878"
|
||||
sodipodi:nodetypes="cccc" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path4880"
|
||||
d="m -1559.2523,-150.68038 c 0,0 0,478.33079 0,478.33079 -142.8742,0.90045 -345.4002,-107.16966 -345.4002,-239.196175 0,-132.026537 159.4368,-239.134595 345.4002,-239.134615 z"
|
||||
style="opacity:0.40206185;color:#000000;fill:url(#radialGradient4898);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /></g><g
|
||||
id="g4882"
|
||||
transform="translate(-0.96783034,-2.9168155)"><rect
|
||||
ry="1.9470588"
|
||||
rx="1.9470588"
|
||||
y="27.449707"
|
||||
x="10.297243"
|
||||
height="18.119614"
|
||||
width="29.256544"
|
||||
id="rect4884"
|
||||
style="fill:#eaeaea;fill-opacity:1;stroke:none" /><g
|
||||
id="g4886"><g
|
||||
id="g4888"><rect
|
||||
ry="1.9313381"
|
||||
style="fill:none;stroke:#646464;stroke-width:0.99927008;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4890"
|
||||
width="29.020325"
|
||||
height="17.982044"
|
||||
x="10.510214"
|
||||
y="27.517153"
|
||||
rx="1.9313381" /></g><rect
|
||||
ry="1.0032353"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:0.99249077;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect4892"
|
||||
width="26.967867"
|
||||
height="16.005489"
|
||||
x="11.532422"
|
||||
y="28.489801"
|
||||
rx="1.0032353" /></g></g><g
|
||||
transform="matrix(1,0,0,0.9039548,0,2.5932203)"
|
||||
id="g4922"><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect4900"
|
||||
width="1"
|
||||
height="11.0625"
|
||||
x="13.0625"
|
||||
y="27" /><rect
|
||||
y="27"
|
||||
x="15.0625"
|
||||
height="11.0625"
|
||||
width="1"
|
||||
id="rect4902"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect4904"
|
||||
width="1"
|
||||
height="11.0625"
|
||||
x="18"
|
||||
y="27" /><rect
|
||||
y="27"
|
||||
x="19.9375"
|
||||
height="11.0625"
|
||||
width="2"
|
||||
id="rect4906"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" /><rect
|
||||
y="27"
|
||||
x="22.9375"
|
||||
height="11.0625"
|
||||
width="1"
|
||||
id="rect4908"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect4910"
|
||||
width="2.0625"
|
||||
height="11.0625"
|
||||
x="25.9375"
|
||||
y="27" /><rect
|
||||
y="27"
|
||||
x="28.9375"
|
||||
height="11.0625"
|
||||
width="1.125"
|
||||
id="rect4912"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" /><rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect4914"
|
||||
width="1.125"
|
||||
height="11.0625"
|
||||
x="30.9375"
|
||||
y="27" /><rect
|
||||
y="27"
|
||||
x="33.9375"
|
||||
height="11.0625"
|
||||
width="1.125"
|
||||
id="rect4916"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" /></g><text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text4918"
|
||||
y="40.195068"
|
||||
x="12.981453"
|
||||
style="font-size:36.59571838px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
style="font-size:3.65957189px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Inconsolata;-inkscape-font-specification:Inconsolata Medium"
|
||||
y="40.195068"
|
||||
x="12.981453"
|
||||
id="tspan4920"
|
||||
sodipodi:role="line">5 92102431 8</tspan></text>
|
||||
<rect
|
||||
y="31.0625"
|
||||
x="9.0625"
|
||||
height="1"
|
||||
width="30"
|
||||
id="rect4933"
|
||||
style="fill:#ff0000;fill-opacity:1;stroke:none" /><rect
|
||||
style="fill:#ff0000;fill-opacity:1;stroke:none;filter:url(#filter4971)"
|
||||
id="rect4957"
|
||||
width="30"
|
||||
height="1"
|
||||
x="9.0625"
|
||||
y="31.0625" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4975"
|
||||
d="M 9.0625,32.0625 20,47.875 28.9375,47.9375 39,32.0625 z"
|
||||
style="opacity:0.29787233;fill:url(#linearGradient4983);fill-opacity:1;stroke:none" /></g></svg>
|
After Width: | Height: | Size: 41 KiB |
|
@ -0,0 +1,62 @@
|
|||
v Affichage Catégories doivent respecter le poids
|
||||
v Affichage Catégories par poids doivent avoir une hiérarchie plate
|
||||
v Le Onscreen keyboard ne fonctionne plus
|
||||
v Scrolling dans la sélection produit et dans
|
||||
la liste de courses
|
||||
v Réductions
|
||||
v Redesign liste de courses
|
||||
v bugs scans produits par prix par poids
|
||||
v si pas photo photo par defaut
|
||||
v WebSQL
|
||||
v Redesign header, bouton retour aux backend en mode caissière
|
||||
v bouton exit en mode caissière doit retourner au backend.
|
||||
v posting orders
|
||||
v bug ajout ligne payment à zero + curseur dedans + suppression + design plus grand
|
||||
v si case print via proxy cochée, alors on skip l'ecran receipt
|
||||
v bouton exit self checkout
|
||||
v demarrage en mode self-checkout si self-checkout
|
||||
v produits poid code barre non reconnus
|
||||
v activer popup client aux écrans self-checkout
|
||||
v discount pas plus grand que 100
|
||||
v numpad dans l'écran payment pour pouvoir entrer le montant
|
||||
v différence de total. Methode d'arrondis
|
||||
|
||||
- login alternatif
|
||||
- user preferences : désactiver la balance etc.
|
||||
- numpad state parfois sans state
|
||||
- numpad state en mode pesée ?? le cacher ?
|
||||
- Redesign du receipt
|
||||
- retirer le receipt screen
|
||||
- le numpad en mode paymenet marche pas
|
||||
- l'écran de payement est hyper laid
|
||||
- l'écran de pesée est hyper laid
|
||||
x générer les données de printing
|
||||
x popups d'erreur certainement buggés
|
||||
|
||||
TODO AUG 20
|
||||
-----------
|
||||
|
||||
* GREEN STATUS
|
||||
- make it green !
|
||||
|
||||
* TRUNK
|
||||
- Connection status tooltip
|
||||
v Remove receipt screen
|
||||
- Finish the receipt JSON generation
|
||||
- Modifie le widget de liste course
|
||||
v supprimer l'écran
|
||||
v bloquer sur l'impression
|
||||
v L'impression est foireuse
|
||||
|
||||
* CLIENT
|
||||
- create a new branch
|
||||
- Self-checkout welcome screen
|
||||
- removal of products for the root category
|
||||
- Terminal de payement
|
||||
- Code à barres
|
||||
- Vidanges
|
||||
- Design
|
||||
- Backport
|
||||
- CSS pour écran résistif
|
||||
- Test sur matos
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
function openerp_pos_db(instance, module){
|
||||
|
||||
/* PosLS is a LocalStorage based implementation of the point of sale database,
|
||||
it performs better for few products, but does not scale beyond 500 products.
|
||||
*/
|
||||
module.PosLS = instance.web.Class.extend({
|
||||
name: 'openerp_pos_ls', //the prefix of the localstorage data
|
||||
limit: 100, // the maximum number of results returned by a search
|
||||
init: function(options){
|
||||
options = options || {};
|
||||
this.name = options.name || this.name;
|
||||
this.limit = options.limit || this.limit;
|
||||
|
||||
//cache the data in memory to avoid roundtrips to the localstorage
|
||||
this.cache = {};
|
||||
|
||||
this.category_by_id = {};
|
||||
this.root_category_id = 0;
|
||||
this.category_products = {};
|
||||
this.category_ancestors = {};
|
||||
this.category_childs = {};
|
||||
this.category_parent = {};
|
||||
this.category_search_string = {};
|
||||
},
|
||||
/* returns the category object from its id. If you pass a list of id as parameters, you get
|
||||
* a list of category objects.
|
||||
*/
|
||||
get_category_by_id: function(categ_id){
|
||||
if(categ_id instanceof Array){
|
||||
var list = [];
|
||||
for(var i = 0, len = categ_id.length; i < len; i++){
|
||||
var cat = this.category_by_id[categ_id[i]];
|
||||
if(cat){
|
||||
list.push(cat);
|
||||
}else{
|
||||
console.error("get_category_by_id: no category has id:",categ_id[i]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}else{
|
||||
return this.category_by_id[categ_id];
|
||||
}
|
||||
},
|
||||
/* returns a list of the category's child categories ids, or an empty list
|
||||
* if a category has no childs */
|
||||
get_category_childs_ids: function(categ_id){
|
||||
return this.category_childs[categ_id] || [];
|
||||
},
|
||||
/* returns a list of all ancestors (parent, grand-parent, etc) categories ids
|
||||
* starting from the root category to the direct parent */
|
||||
get_category_ancestors_ids: function(categ_id){
|
||||
return this.category_ancestors[categ_id] || [];
|
||||
},
|
||||
/* returns the parent category's id of a category, or the root_category_id if no parent.
|
||||
* the root category is parent of itself. */
|
||||
get_category_parent_id: function(categ_id){
|
||||
return this.category_parent[categ_id] || this.root_category_id;
|
||||
},
|
||||
/* adds categories definitions to the database. categories is a list of categories objects as
|
||||
* returned by the openerp server. Categories must be inserted before the products or the
|
||||
* product/ categories association may (will) not work properly */
|
||||
add_categories: function(categories){
|
||||
var self = this;
|
||||
if(!this.category_by_id[this.root_category_id]){
|
||||
this.category_by_id[this.root_category_id] = {
|
||||
id : this.root_category_id,
|
||||
name : 'Root',
|
||||
};
|
||||
}
|
||||
for(var i=0, len = categories.length; i < len; i++){
|
||||
this.category_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
for(var i=0, len = categories.length; i < len; i++){
|
||||
var cat = categories[i];
|
||||
var parent_id = cat.parent_id[0] || this.root_category_id;
|
||||
this.category_parent[cat.id] = cat.parent_id[0];
|
||||
if(!this.category_childs[parent_id]){
|
||||
this.category_childs[parent_id] = [];
|
||||
}
|
||||
this.category_childs[parent_id].push(cat.id);
|
||||
}
|
||||
function make_ancestors(cat_id, ancestors){
|
||||
self.category_ancestors[cat_id] = ancestors;
|
||||
|
||||
ancestors = ancestors.slice(0);
|
||||
ancestors.push(cat_id);
|
||||
|
||||
var childs = self.category_childs[cat_id] || [];
|
||||
for(var i=0, len = childs.length; i < len; i++){
|
||||
make_ancestors(childs[i], ancestors);
|
||||
}
|
||||
}
|
||||
make_ancestors(this.root_category_id, []);
|
||||
},
|
||||
/* loads a record store from the database. returns default if nothing is found */
|
||||
load: function(store,deft){
|
||||
if(this.cache[store] !== undefined){
|
||||
return this.cache[store];
|
||||
}
|
||||
var data = localStorage[this.name + '_' + store];
|
||||
if(data !== undefined){
|
||||
data = JSON.parse(data);
|
||||
this.cache[store] = data;
|
||||
return data;
|
||||
}else{
|
||||
return deft;
|
||||
}
|
||||
},
|
||||
/* saves a record store to the database */
|
||||
save: function(store,data){
|
||||
localStorage[this.name + '_' + store] = JSON.stringify(data);
|
||||
this.cache[store] = data;
|
||||
},
|
||||
_product_search_string: function(product){
|
||||
var str = '' + product.id + ':' + product.name;
|
||||
if(product.ean13){
|
||||
str += '|' + product.ean13;
|
||||
}
|
||||
return str + '\n';
|
||||
},
|
||||
add_products: function(products){
|
||||
var stored_products = this.load('products',{});
|
||||
var stored_categories = this.load('categories',{});
|
||||
|
||||
if(!products instanceof Array){
|
||||
products = [products];
|
||||
}
|
||||
for(var i = 0, len = products.length; i < len; i++){
|
||||
var product = products[i];
|
||||
var search_string = this._product_search_string(product);
|
||||
var categ_id = product.pos_categ_id[0];
|
||||
if(!stored_categories[categ_id]){
|
||||
stored_categories[categ_id] = [];
|
||||
}
|
||||
stored_categories[categ_id].push(product.id);
|
||||
|
||||
if(this.category_search_string[categ_id] === undefined){
|
||||
this.category_search_string[categ_id] = '';
|
||||
}
|
||||
this.category_search_string[categ_id] += search_string;
|
||||
|
||||
var ancestors = this.get_category_ancestors_ids(categ_id) || [];
|
||||
|
||||
for(var j = 0; j < ancestors.length; j++){
|
||||
var ancestor = ancestors[j];
|
||||
if(! stored_categories[ancestor]){
|
||||
stored_categories[ancestor] = [];
|
||||
}
|
||||
stored_categories[ancestor].push(product.id);
|
||||
|
||||
if( this.category_search_string[ancestor] === undefined){
|
||||
this.category_search_string[ancestor] = '';
|
||||
}
|
||||
this.category_search_string[ancestor] += search_string;
|
||||
}
|
||||
stored_products[product.id] = product;
|
||||
}
|
||||
this.save('products',stored_products);
|
||||
this.save('categories',stored_categories);
|
||||
},
|
||||
/* removes all the data from the database. TODO : being able to selectively remove data */
|
||||
clear: function(stores){
|
||||
for(var i = 0, len = arguments.length; i < len; i++){
|
||||
localStorage.removeItem(this.name + '_' + arguments[i]);
|
||||
}
|
||||
},
|
||||
/* this internal methods returns the count of properties in an object. */
|
||||
_count_props : function(obj){
|
||||
var count = 0;
|
||||
for(var prop in obj){
|
||||
if(obj.hasOwnProperty(prop)){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
},
|
||||
get_product_by_id: function(id){
|
||||
return this.load('products',{})[id];
|
||||
},
|
||||
get_product_by_ean13: function(ean13){
|
||||
var products = this.load('products',{});
|
||||
for(var i in products){
|
||||
if( products[i] && products[i].ean13 === ean13){
|
||||
return products[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
get_product_by_category: function(category_id){
|
||||
var stored_categories = this.load('categories',{});
|
||||
var stored_products = this.load('products',{});
|
||||
var product_ids = stored_categories[category_id];
|
||||
var list = [];
|
||||
for(var i = 0, len = Math.min(product_ids.length,this.limit); i < len; i++){
|
||||
list.push(stored_products[product_ids[i]]);
|
||||
}
|
||||
return list;
|
||||
},
|
||||
/* returns a list of products with :
|
||||
* - a category that is or is a child of category_id,
|
||||
* - a name, package or ean13 containing the query (case insensitive)
|
||||
*/
|
||||
search_product_in_category: function(category_id, query){
|
||||
var re = RegExp("([0-9]+):.*?"+query,"gi");
|
||||
var results = [];
|
||||
for(var i = 0; i < this.limit; i++){
|
||||
r = re.exec(this.category_search_string[category_id]);
|
||||
if(r){
|
||||
var id = Number(r[1]);
|
||||
results.push(this.get_product_by_id(id));
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
add_order: function(order){
|
||||
var last_id = this.load('last_order_id',0);
|
||||
var orders = this.load('orders',[]);
|
||||
orders.push({id: last_id + 1, data: order});
|
||||
this.save('last_order_id',last_id+1);
|
||||
this.save('orders',orders);
|
||||
},
|
||||
remove_order: function(order_id){
|
||||
var orders = this.load('orders',[]);
|
||||
orders = _.filter(orders, function(order){
|
||||
return order.id !== order_id;
|
||||
});
|
||||
this.save('orders',orders);
|
||||
},
|
||||
get_orders: function(){
|
||||
return this.load('orders',[]);
|
||||
},
|
||||
});
|
||||
}
|
|
@ -17,7 +17,9 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
delay_payment: function(){ this.activate(); this.payment_status = 'waiting_for_payment'; },
|
||||
}))();
|
||||
|
||||
//window.debug_devices = debug_devices;
|
||||
if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
|
||||
window.debug_devices = debug_devices;
|
||||
}
|
||||
|
||||
// this object interfaces with the local proxy to communicate to the various hardware devices
|
||||
// connected to the Point of Sale. As the communication only goes from the POS to the proxy,
|
||||
|
@ -42,21 +44,26 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
success_callback = success_callback || function(){};
|
||||
error_callback = error_callback || function(){};
|
||||
|
||||
if(debug_devices && debug_devices.active){
|
||||
|
||||
if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
|
||||
console.log('PROXY:',name,params);
|
||||
}else{
|
||||
}
|
||||
|
||||
if(!(debug_devices && debug_devices.active)){
|
||||
this.connection.rpc('/pos/'+name, params || {}, success_callback, error_callback);
|
||||
}
|
||||
},
|
||||
|
||||
//a product has been scanned and recognized with success
|
||||
scan_item_success: function(){
|
||||
this.message('scan_item_success');
|
||||
// ean is a parsed ean object
|
||||
scan_item_success: function(ean){
|
||||
this.message('scan_item_success',ean);
|
||||
},
|
||||
|
||||
//a product has been scanned but not recognized
|
||||
scan_item_error_unrecognized: function(){
|
||||
this.message('scan_item_error_unrecognized');
|
||||
// a product has been scanned but not recognized
|
||||
// ean is a parsed ean object
|
||||
scan_item_error_unrecognized: function(ean){
|
||||
this.message('scan_item_error_unrecognized',ean);
|
||||
},
|
||||
|
||||
//the client is asking for help
|
||||
|
@ -222,11 +229,11 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
|
||||
this.action_callback_stack = [];
|
||||
|
||||
this.price_prefix_set = attributes.price_prefix_set || {'02':'', '22':'', '24':'', '26':'', '28':''};
|
||||
this.weight_prefix_set = attributes.weight_prefix_set || {'21':'','23':'','27':'','29':'','25':''};
|
||||
this.client_prefix_set = attributes.weight_prefix_set || {'42':''};
|
||||
this.cashier_prefix_set = attributes.weight_prefix_set || {'40':''};
|
||||
this.discount_prefix_set = attributes.weight_prefix_set || {'44':''};
|
||||
this.weight_prefix_set = attributes.weight_prefix_set || {'21':''};
|
||||
this.discount_prefix_set = attributes.discount_prefix_set || {'22':''};
|
||||
this.price_prefix_set = attributes.price_prefix_set || {'23':''};
|
||||
this.cashier_prefix_set = attributes.cashier_prefix_set || {'041':''};
|
||||
this.client_prefix_set = attributes.client_prefix_set || {'042':''};
|
||||
},
|
||||
save_callbacks: function(){
|
||||
var callbacks = {};
|
||||
|
@ -270,41 +277,37 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
this.action_callback[action] = undefined;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// returns the checksum of the ean, or -1 if the ean has not the correct length, ean must be a string
|
||||
ean_checksum: function(ean){
|
||||
var code = ean.split('');
|
||||
if(code.length !== 13){
|
||||
return -1;
|
||||
}
|
||||
var oddsum = 0, evensum = 0, total = 0;
|
||||
code = code.reverse().splice(1);
|
||||
for(var i = 0; i < code.length; i++){
|
||||
if(i % 2 == 0){
|
||||
oddsum += Number(code[i]);
|
||||
}else{
|
||||
evensum += Number(code[i]);
|
||||
}
|
||||
}
|
||||
total = oddsum * 3 + evensum;
|
||||
return Number((10 - total % 10) % 10);
|
||||
},
|
||||
// returns true if the ean is a valid EAN codebar number by checking the control digit.
|
||||
// ean must be a string
|
||||
check_ean: function(ean){
|
||||
var code = ean.split('');
|
||||
for(var i = 0; i < code.length; i++){
|
||||
code[i] = Number(code[i]);
|
||||
return this.ean_checksum(ean) === Number(ean[ean.length-1]);
|
||||
},
|
||||
// returns a valid zero padded ean13 from an ean prefix. the ean prefix must be a string.
|
||||
sanitize_ean:function(ean){
|
||||
ean = ean.substr(0,13);
|
||||
|
||||
for(var n = 0, count = (13 - ean.length); n < count; n++){
|
||||
ean = ean + '0';
|
||||
}
|
||||
var st1 = code.slice();
|
||||
var st2 = st1.slice(0,st1.length-1).reverse();
|
||||
// some EAN13 barcodes have a length of 12, as they start by 0
|
||||
while (st2.length < 12) {
|
||||
st2.push(0);
|
||||
}
|
||||
var countSt3 = 1;
|
||||
var st3 = 0;
|
||||
$.each(st2, function() {
|
||||
if (countSt3%2 === 1) {
|
||||
st3 += this;
|
||||
}
|
||||
countSt3 ++;
|
||||
});
|
||||
st3 *= 3;
|
||||
var st4 = 0;
|
||||
var countSt4 = 1;
|
||||
$.each(st2, function() {
|
||||
if (countSt4%2 === 0) {
|
||||
st4 += this;
|
||||
}
|
||||
countSt4 ++;
|
||||
});
|
||||
var st5 = st3 + st4;
|
||||
var cd = (10 - (st5%10)) % 10;
|
||||
return code[code.length-1] === cd;
|
||||
return ean.substr(0,12) + this.ean_checksum(ean);
|
||||
},
|
||||
|
||||
// attempts to interpret an ean (string encoding an ean)
|
||||
|
@ -327,41 +330,47 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
type:'unknown', //
|
||||
prefix:'',
|
||||
ean:ean,
|
||||
base_ean: ean,
|
||||
id:'',
|
||||
value: 0,
|
||||
unit: 'none',
|
||||
};
|
||||
var prefix2 = ean.substring(0,2);
|
||||
console.log('ean',ean);
|
||||
|
||||
if(!this.check_ean(ean)){
|
||||
function match_prefix(prefix_set, type){
|
||||
for(prefix in prefix_set){
|
||||
if(ean.substring(0,prefix.length) === prefix){
|
||||
parse_result.prefix = prefix;
|
||||
parse_result.type = type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.check_ean(ean)){
|
||||
parse_result.type = 'error';
|
||||
}else if (prefix2 in this.price_prefix_set){
|
||||
parse_result.type = 'price';
|
||||
parse_result.prefix = prefix2;
|
||||
} else if( match_prefix(this.price_prefix_set,'price')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = 'euro';
|
||||
} else if (prefix2 in this.weight_prefix_set){
|
||||
parse_result.type = 'weight';
|
||||
parse_result.prefix = prefix2;
|
||||
} else if( match_prefix(this.weight_prefix_set,'weight')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.value = Number(ean.substring(7,12))/1000.0;
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.unit = 'Kg';
|
||||
}else if (prefix2 in this.client_prefix_set){
|
||||
parse_result.type = 'client';
|
||||
parse_result.prefix = prefix2;
|
||||
} else if( match_prefix(this.client_prefix_set,'client')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
}else if (prefix2 in this.cashier_prefix_set){
|
||||
parse_result.type = 'cashier';
|
||||
parse_result.prefix = prefix2;
|
||||
parse_result.unit = 'Kg';
|
||||
} else if( match_prefix(this.cashier_prefix_set,'cashier')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
}else if (prefix2 in this.discount_prefix_set){
|
||||
parse_result.type = 'discount';
|
||||
parse_result.prefix = prefix2;
|
||||
} else if( match_prefix(this.discount_prefix_set,'discount')){
|
||||
parse_result.id = ean.substring(0,7);
|
||||
parse_result.base_ean = this.sanitize_ean(ean.substring(0,7));
|
||||
parse_result.value = Number(ean.substring(7,12))/100.0;
|
||||
parse_result.unit = '%';
|
||||
}else{
|
||||
} else {
|
||||
parse_result.type = 'unit';
|
||||
parse_result.prefix = '';
|
||||
parse_result.id = ean;
|
||||
|
@ -402,7 +411,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
|||
var parse_result = self.parse_ean(codeNumbers.join(''));
|
||||
|
||||
if (parse_result.type === 'error') { //most likely a checksum error, raise warning
|
||||
console.error('ERROR: barcode checksum error:',parse_result);
|
||||
console.warn('WARNING: barcode checksum error:',parse_result);
|
||||
}else if(parse_result.type in {'unit':'', 'weight':'', 'price':''}){ //ean is associated to a product
|
||||
if(self.action_callback['product']){
|
||||
self.action_callback['product'](parse_result);
|
|
@ -5,6 +5,8 @@ openerp.point_of_sale = function(instance) {
|
|||
|
||||
var module = instance.point_of_sale;
|
||||
|
||||
openerp_pos_db(instance,module); // import db.js
|
||||
|
||||
openerp_pos_models(instance,module); // import pos_models.js
|
||||
|
||||
openerp_pos_basewidget(instance,module); // import pos_basewidget.js
|
|
@ -1,51 +1,6 @@
|
|||
function openerp_pos_models(instance, module){ //module is instance.point_of_sale
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
module.LocalStorageDAO = instance.web.Class.extend({
|
||||
add_operation: function(operation) {
|
||||
var self = this;
|
||||
return $.async_when().pipe(function() {
|
||||
var tmp = self._get('oe_pos_operations', []);
|
||||
var last_id = self._get('oe_pos_operations_sequence', 1);
|
||||
tmp.push({'id': last_id, 'data': operation});
|
||||
self._set('oe_pos_operations', tmp);
|
||||
self._set('oe_pos_operations_sequence', last_id + 1);
|
||||
});
|
||||
},
|
||||
remove_operation: function(id) {
|
||||
var self = this;
|
||||
return $.async_when().pipe(function() {
|
||||
var tmp = self._get('oe_pos_operations', []);
|
||||
tmp = _.filter(tmp, function(el) {
|
||||
return el.id !== id;
|
||||
});
|
||||
self._set('oe_pos_operations', tmp);
|
||||
});
|
||||
},
|
||||
get_operations: function() {
|
||||
var self = this;
|
||||
return $.async_when().pipe(function() {
|
||||
return self._get('oe_pos_operations', []);
|
||||
});
|
||||
},
|
||||
_get: function(key, default_) {
|
||||
var txt = localStorage['oe_pos_dao_'+key];
|
||||
if (! txt)
|
||||
return default_;
|
||||
return JSON.parse(txt);
|
||||
},
|
||||
_set: function(key, value) {
|
||||
localStorage['oe_pos_dao_'+key] = JSON.stringify(value);
|
||||
},
|
||||
reset_stored_data: function(){
|
||||
for(key in localStorage){
|
||||
if(key.indexOf('oe_pos_dao_') === 0){
|
||||
delete localStorage[key];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var fetch = function(model, fields, domain, ctx){
|
||||
return new instance.web.Model(model).query(fields).filter(domain).context(ctx).all()
|
||||
};
|
||||
|
@ -58,29 +13,20 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// this is done asynchronously, a ready deferred alows the GUI to wait interactively
|
||||
// for the loading to be completed
|
||||
// There is a single instance of the PosModel for each Front-End instance, it is usually called
|
||||
// 'pos' and is available to almost all widgets.
|
||||
// 'pos' and is available to all widgets extending PosWidget.
|
||||
|
||||
module.PosModel = Backbone.Model.extend({
|
||||
initialize: function(session, attributes) {
|
||||
Backbone.Model.prototype.initialize.call(this, attributes);
|
||||
var self = this;
|
||||
this.dao = new module.LocalStorageDAO(); // used to store the order's data on the Hard Drive
|
||||
this.session = session;
|
||||
this.ready = $.Deferred(); // used to notify the GUI that the PosModel has loaded all resources
|
||||
this.flush_mutex = new $.Mutex(); // used to make sure the orders are sent to the server once at time
|
||||
//this.build_tree = _.bind(this.build_tree, this); // ???
|
||||
this.session = session;
|
||||
this.categories = {};
|
||||
this.root_category = null;
|
||||
this.weightable_categories = []; // a flat list of all categories that directly contain weightable products
|
||||
this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes
|
||||
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
||||
|
||||
// pos settings
|
||||
this.use_scale = false;
|
||||
this.use_proxy_printer = false;
|
||||
this.use_virtual_keyboard = false;
|
||||
this.use_websql = false;
|
||||
this.use_barcode_scanner = false;
|
||||
this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes
|
||||
this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy
|
||||
this.db = new module.PosLS(); // a database used to store the products and categories
|
||||
this.db.clear('products','categories');
|
||||
|
||||
// default attributes values. If null, it will be loaded below.
|
||||
this.set({
|
||||
|
@ -98,12 +44,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
'products': new module.ProductCollection(),
|
||||
'cashRegisters': null,
|
||||
|
||||
'product_list': null, // the list of all products, does not change.
|
||||
'bank_statements': null,
|
||||
'taxes': null,
|
||||
'pos_session': null,
|
||||
'pos_config': null,
|
||||
'categories': null,
|
||||
'units': null,
|
||||
'units_by_id': null,
|
||||
|
||||
'selectedOrder': undefined,
|
||||
});
|
||||
|
@ -113,10 +59,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// We fetch the backend data on the server asynchronously. this is done only when the pos user interface is launched,
|
||||
// Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched.
|
||||
|
||||
var user_def = fetch('res.users',['name','company_id'],[['id','=',this.session.uid]])
|
||||
var loaded = fetch('res.users',['name','company_id'],[['id','=',this.session.uid]])
|
||||
.pipe(function(users){
|
||||
var user = users[0];
|
||||
self.set('user',user);
|
||||
self.set('user',users[0]);
|
||||
|
||||
return fetch('res.company',
|
||||
[
|
||||
|
@ -124,171 +69,114 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
'email',
|
||||
'website',
|
||||
'company_registry',
|
||||
//TODO contact_address
|
||||
'vat',
|
||||
'name',
|
||||
'phone'
|
||||
'phone',
|
||||
'partner_id',
|
||||
],
|
||||
[['id','=',user.company_id[0]]])
|
||||
[['id','=',users[0].company_id[0]]]);
|
||||
}).pipe(function(companies){
|
||||
var company = companies[0];
|
||||
self.set('company',company);
|
||||
self.set('company',companies[0]);
|
||||
|
||||
return fetch('res.currency',['symbol','position'],[['id','=',company.currency_id[0]]]);
|
||||
}).pipe(function (currencies){
|
||||
return fetch('res.partner',['contact_address'],[['id','=',companies[0].partner_id[0]]]);
|
||||
}).pipe(function(company_partners){
|
||||
self.get('company').contact_address = company_partners[0].contact_address;
|
||||
|
||||
return fetch('res.currency',['symbol','position'],[['id','=',self.get('company').currency_id[0]]]);
|
||||
}).pipe(function(currencies){
|
||||
self.set('currency',currencies[0]);
|
||||
});
|
||||
|
||||
var cat_def = fetch('pos.category', ['id','name', 'parent_id', 'child_id', 'image_medium'])
|
||||
.pipe(function(result){
|
||||
return self.set({'categories': result});
|
||||
});
|
||||
|
||||
var uom_def = fetch( //unit of measure
|
||||
'product.uom',
|
||||
null,
|
||||
null
|
||||
).then(function(result){
|
||||
self.set({'units': result});
|
||||
return fetch('product.uom', null, null);
|
||||
}).pipe(function(units){
|
||||
self.set('units',units);
|
||||
var units_by_id = {};
|
||||
for(var i = 0, len = result.length; i < len; i++){
|
||||
units_by_id[result[i].id] = result[i];
|
||||
for(var i = 0, len = units.length; i < len; i++){
|
||||
units_by_id[units[i].id] = units[i];
|
||||
}
|
||||
self.set({'units_by_id':units_by_id});
|
||||
});
|
||||
|
||||
var pack_def = fetch(
|
||||
'product.packaging',
|
||||
null,
|
||||
null
|
||||
).then(function(packaging){
|
||||
self.set('product.packaging',packaging);
|
||||
});
|
||||
|
||||
var users_def = fetch(
|
||||
'res.users',
|
||||
['name','ean13'],
|
||||
[['ean13', '!=', false]]
|
||||
).then(function(result){
|
||||
self.set({'user_list':result});
|
||||
});
|
||||
|
||||
var tax_def = fetch('account.tax', ['amount','price_include','type'])
|
||||
.then(function(result){
|
||||
self.set({'taxes': result});
|
||||
});
|
||||
|
||||
var session_def = fetch( // loading the PoS Session.
|
||||
'pos.session',
|
||||
['id', 'journal_ids','name','user_id','config_id','start_at','stop_at'],
|
||||
[['state', '=', 'opened'], ['user_id', '=', this.session.uid]]
|
||||
).pipe(function(result) {
|
||||
|
||||
// some data are associated with the pos session, like the pos config and bank statements.
|
||||
// we must have a valid session before we can read those.
|
||||
self.set('units_by_id',units_by_id);
|
||||
|
||||
var session_data_def = new $.Deferred();
|
||||
return fetch('product.packaging', null, null);
|
||||
}).pipe(function(packagings){
|
||||
self.set('product.packaging',packagings);
|
||||
|
||||
if( result.length !== 0 ) {
|
||||
var pos_session = result[0];
|
||||
return fetch('res.users', ['name','ean13'], [['ean13', '!=', false]]);
|
||||
}).pipe(function(users){
|
||||
self.set('user_list',users);
|
||||
|
||||
self.set({'pos_session': pos_session});
|
||||
return fetch('account.tax', ['amount', 'price_include', 'type']);
|
||||
}).pipe(function(taxes){
|
||||
self.set('taxes', taxes);
|
||||
|
||||
var pos_config_def = fetch(
|
||||
'pos.config',
|
||||
['name','journal_ids','shop_id','journal_id',
|
||||
'iface_self_checkout', 'iface_websql', 'iface_led', 'iface_cashdrawer',
|
||||
'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard',
|
||||
'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'],
|
||||
[['id','=', pos_session.config_id[0]]]
|
||||
).pipe(function(result){
|
||||
var pos_config = result[0]
|
||||
|
||||
self.set({'pos_config': pos_config});
|
||||
self.use_scale = pos_config.iface_electronic_scale || false;
|
||||
self.use_proxy_printer = pos_config.iface_print_via_proxy || false;
|
||||
self.use_virtual_keyboard = pos_config.iface_vkeyboard || false;
|
||||
self.use_websql = pos_config.iface_websql || false;
|
||||
self.use_barcode_scanner = pos_config.iface_barscan || false;
|
||||
self.use_selfcheckout = pos_config.iface_self_checkout || false;
|
||||
self.use_cashbox = pos_config.iface_cashdrawer || false;
|
||||
return fetch(
|
||||
'pos.session',
|
||||
['id', 'journal_ids','name','user_id','config_id','start_at','stop_at'],
|
||||
[['state', '=', 'opened'], ['user_id', '=', self.session.uid]]
|
||||
);
|
||||
}).pipe(function(sessions){
|
||||
self.set('pos_session', sessions[0]);
|
||||
|
||||
return shop_def = fetch('sale.shop',[], [['id','=',pos_config.shop_id[0]]])
|
||||
}).pipe(function(shops){
|
||||
self.set('shop',shops[0]);
|
||||
return fetch(
|
||||
'product.product',
|
||||
//context {pricelist: shop.pricelist_id[0]}
|
||||
['name', 'list_price','price','pos_categ_id', 'taxes_id','image_medium', 'ean13', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type'],
|
||||
[['pos_categ_id','!=', false]],
|
||||
{pricelist: shops[0].pricelist_id[0]} // context for price
|
||||
);
|
||||
}).pipe( function(product_list){
|
||||
self.set({'product_list': product_list});
|
||||
});
|
||||
return fetch(
|
||||
'pos.config',
|
||||
['name','journal_ids','shop_id','journal_id',
|
||||
'iface_self_checkout', 'iface_led', 'iface_cashdrawer',
|
||||
'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard',
|
||||
'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'],
|
||||
[['id','=', self.get('pos_session').config_id[0]]]
|
||||
);
|
||||
}).pipe(function(configs){
|
||||
var pos_config = configs[0];
|
||||
self.set('pos_config', pos_config);
|
||||
self.iface_electronic_scale = !!pos_config.iface_electronic_scale;
|
||||
self.iface_print_via_proxy = !!pos_config.iface_print_via_proxy;
|
||||
self.iface_vkeyboard = !!pos_config.iface_vkeyboard;
|
||||
self.iface_self_checkout = !!pos_config.iface_self_checkout;
|
||||
self.iface_cashdrawer = !!pos_config.iface_cashdrawer;
|
||||
|
||||
var bank_def = fetch(
|
||||
'account.bank.statement',
|
||||
['account_id','currency','journal_id','state','name','user_id','pos_session_id'],
|
||||
[['state','=','open'],['pos_session_id', '=', pos_session.id]]
|
||||
).then(function(result){
|
||||
self.set({'bank_statements':result});
|
||||
});
|
||||
return fetch('sale.shop',[],[['id','=',pos_config.shop_id[0]]]);
|
||||
}).pipe(function(shops){
|
||||
self.set('shop',shops[0]);
|
||||
|
||||
var journal_def = fetch(
|
||||
'account.journal',
|
||||
undefined,
|
||||
[['user_id','=',pos_session.user_id[0]]]
|
||||
).then(function(result){
|
||||
self.set({'journals':result});
|
||||
});
|
||||
return fetch('pos.category', ['id','name','parent_id','child_id','image'])
|
||||
}).pipe(function(categories){
|
||||
self.db.add_categories(categories);
|
||||
|
||||
// associate the bank statements with their journals.
|
||||
var bank_process_def = $.when(bank_def, journal_def)
|
||||
.then(function(){
|
||||
var bank_statements = self.get('bank_statements');
|
||||
var journals = self.get('journals');
|
||||
for(var i = 0, ilen = bank_statements.length; i < ilen; i++){
|
||||
for(var j = 0, jlen = journals.length; j < jlen; j++){
|
||||
if(bank_statements[i].journal_id[0] === journals[j].id){
|
||||
bank_statements[i].journal = journals[j];
|
||||
bank_statements[i].self_checkout_payment_method = journals[j].self_checkout_payment_method;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return fetch(
|
||||
'product.product',
|
||||
['name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type'],
|
||||
[['pos_categ_id','!=', false]],
|
||||
{pricelist: self.get('shop').pricelist_id[0]} // context for price
|
||||
);
|
||||
}).pipe(function(products){
|
||||
self.db.add_products(products);
|
||||
|
||||
session_data_def = $.when(pos_config_def,bank_def,journal_def,bank_process_def);
|
||||
return fetch(
|
||||
'account.bank.statement',
|
||||
['account_id','currency','journal_id','state','name','user_id','pos_session_id'],
|
||||
[['state','=','open'],['pos_session_id', '=', self.get('pos_session').id]]
|
||||
);
|
||||
}).pipe(function(bank_statements){
|
||||
self.set('bank_statements', bank_statements);
|
||||
|
||||
}else{
|
||||
session_data_def.reject();
|
||||
}
|
||||
return session_data_def;
|
||||
});
|
||||
|
||||
// associate the products with their categories
|
||||
var prod_process_def = $.when(cat_def, session_def)
|
||||
.pipe(function(){
|
||||
var product_list = self.get('product_list');
|
||||
var categories = self.get('categories');
|
||||
var cat_by_id = {};
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
cat_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
//set the parent in the category
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
categories[i].parent_category = cat_by_id[categories[i].parent_id[0]];
|
||||
}
|
||||
for(var i = 0; i < product_list.length; i++){
|
||||
product_list[i].pos_category = cat_by_id[product_list[i].pos_categ_id[0]];
|
||||
return fetch('account.journal', undefined, [['user_id','=', self.get('pos_session').user_id[0]]]);
|
||||
}).pipe(function(journals){
|
||||
self.set('journals',journals);
|
||||
|
||||
// associate the bank statements with their journals.
|
||||
var bank_statements = self.get('bank_statements');
|
||||
for(var i = 0, ilen = bank_statements.length; i < ilen; i++){
|
||||
for(var j = 0, jlen = journals.length; j < jlen; j++){
|
||||
if(bank_statements[i].journal_id[0] === journals[j].id){
|
||||
bank_statements[i].journal = journals[j];
|
||||
bank_statements[i].self_checkout_payment_method = journals[j].self_checkout_payment_method;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.set({'cashRegisters' : new module.CashRegisterCollection(self.get('bank_statements'))});
|
||||
});
|
||||
|
||||
// when all the data has loaded, we compute some stuff, and declare the Pos ready to be used.
|
||||
$.when(pack_def, cat_def, user_def, users_def, uom_def, session_def, tax_def, prod_process_def, user_def, this.flush())
|
||||
$.when(loaded)
|
||||
.then(function(){
|
||||
self.build_categories();
|
||||
self.set({'cashRegisters' : new module.CashRegisterCollection(self.get('bank_statements'))});
|
||||
//self.log_loaded_data(); //Uncomment if you want to log the data to the console for easier debugging
|
||||
self.ready.resolve();
|
||||
},function(){
|
||||
|
@ -302,7 +190,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
log_loaded_data: function(){
|
||||
console.log('PosModel data has been loaded:');
|
||||
console.log('PosModel: categories:',this.get('categories'));
|
||||
console.log('PosModel: product_list:',this.get('product_list'));
|
||||
console.log('PosModel: units:',this.get('units'));
|
||||
console.log('PosModel: bank_statements:',this.get('bank_statements'));
|
||||
console.log('PosModel: journals:',this.get('journals'));
|
||||
|
@ -316,7 +203,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
console.log('PosModel: user_list:',this.get('user_list'));
|
||||
console.log('PosModel: user:',this.get('user'));
|
||||
console.log('PosModel.session:',this.session);
|
||||
console.log('PosModel.categories:',this.categories);
|
||||
console.log('PosModel end of data log.');
|
||||
},
|
||||
|
||||
|
@ -324,7 +210,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
// order and a valid selected order
|
||||
on_removed_order: function(removed_order){
|
||||
if( this.get('orders').isEmpty()){
|
||||
this.add_and_select_order(new module.Order({ pos: this }));
|
||||
this.add_new_order();
|
||||
}
|
||||
if( this.get('selectedOrder') === removed_order){
|
||||
this.set({ selectedOrder: this.get('orders').last() });
|
||||
|
@ -333,175 +219,70 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
|
||||
// saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order
|
||||
push_order: function(record) {
|
||||
var self = this;
|
||||
return this.dao.add_operation(record).pipe(function(){
|
||||
return self.flush();
|
||||
});
|
||||
this.db.add_order(record);
|
||||
this.flush();
|
||||
},
|
||||
|
||||
add_and_select_order: function(newOrder) {
|
||||
(this.get('orders')).add(newOrder);
|
||||
return this.set({
|
||||
selectedOrder: newOrder
|
||||
});
|
||||
//creates a new empty order and sets it as the current order
|
||||
add_new_order: function(){
|
||||
var order = new module.Order({pos:this});
|
||||
this.get('orders').add(order);
|
||||
this.set('selectedOrder', order);
|
||||
},
|
||||
|
||||
// attemps to send all pending orders ( stored in the DAO ) to the server.
|
||||
// it will do it one by one, and remove the successfully sent ones from the DAO once
|
||||
// it has been confirmed that they have been received.
|
||||
|
||||
// attemps to send all pending orders ( stored in the pos_db ) to the server,
|
||||
// and remove the successfully sent ones from the db once
|
||||
// it has been confirmed that they have been sent correctly.
|
||||
flush: function() {
|
||||
//this makes sure only one _int_flush is called at the same time
|
||||
return this.flush_mutex.exec(_.bind(function() {
|
||||
return this._int_flush();
|
||||
return this._flush(0);
|
||||
}, this));
|
||||
},
|
||||
_int_flush : function() {
|
||||
// attempts to send an order of index 'index' in the list of order to send. The index
|
||||
// is used to skip orders that failed. do not call this method outside the mutex provided
|
||||
// by flush()
|
||||
_flush: function(index){
|
||||
var self = this;
|
||||
var orders = this.db.get_orders();
|
||||
self.set('nbr_pending_operations',orders.length);
|
||||
|
||||
this.dao.get_operations().pipe(function(operations) {
|
||||
// operations are really Orders that are converted to json.
|
||||
// they are saved to disk and then we attempt to send them to the backend so that they can
|
||||
// be applied.
|
||||
// since the network is not reliable we potentially have many 'pending operations' that have not been sent.
|
||||
self.set( {'nbr_pending_operations':operations.length} );
|
||||
if(operations.length === 0){
|
||||
return $.when();
|
||||
}
|
||||
var order = operations[0];
|
||||
|
||||
// we prevent the default error handler and assume errors
|
||||
// are a normal use case, except we stop the current iteration
|
||||
|
||||
return (new instance.web.Model('pos.order')).get_func('create_from_ui')([order])
|
||||
.fail(function(unused, event){
|
||||
// wtf ask niv
|
||||
event.preventDefault();
|
||||
})
|
||||
.pipe(function(){
|
||||
// success: remove the successfully sent operation, and try to send the next one
|
||||
self.dao.remove_operation(operations[0].id).pipe(function(){
|
||||
return self._int_flush();
|
||||
});
|
||||
}, function(){
|
||||
// in case of error we just sit there and do nothing. wtf ask niv
|
||||
return $.when();
|
||||
});
|
||||
});
|
||||
var order = orders[index];
|
||||
if(!order){
|
||||
return;
|
||||
}
|
||||
//try to push an order to the server
|
||||
(new instance.web.Model('pos.order')).get_func('create_from_ui')([order])
|
||||
.fail(function(unused, event){
|
||||
//don't show error popup if it fails
|
||||
event.preventDefault();
|
||||
console.error('Failed to send order:',order);
|
||||
self._flush(index+1);
|
||||
})
|
||||
.done(function(){
|
||||
//remove from db if success
|
||||
self.db.remove_order(order.id);
|
||||
self._flush(index);
|
||||
});
|
||||
},
|
||||
|
||||
// this adds several properties to the categories in order to make it easier to diplay them
|
||||
// fields added include the list of product relevant to each category, list of child categories,
|
||||
// list of ancestors, etc.
|
||||
build_categories : function(){
|
||||
var categories = this.get('categories');
|
||||
var products = this.get('product_list');
|
||||
scan_product: function(parsed_ean){
|
||||
var self = this;
|
||||
var product = this.db.get_product_by_ean13(parsed_ean.base_ean);
|
||||
var selectedOrder = this.get('selectedOrder');
|
||||
|
||||
//append the content of array2 into array1
|
||||
function append(array1, array2){
|
||||
for(var i = 0, len = array2.length; i < len; i++){
|
||||
array1.push(array2[i]);
|
||||
}
|
||||
if(!product){
|
||||
return false;
|
||||
}
|
||||
|
||||
function appendSet(set1, set2){
|
||||
for(key in set2){
|
||||
set1[key] = set2[key];
|
||||
}
|
||||
if(parsed_ean.type === 'price'){
|
||||
selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value});
|
||||
}else if(parsed_ean.type === 'weight'){
|
||||
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false});
|
||||
}else{
|
||||
selectedOrder.addProduct(new module.Product(product));
|
||||
}
|
||||
|
||||
var categories_by_id = {};
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
categories_by_id[categories[i].id] = categories[i];
|
||||
}
|
||||
this.categories_by_id = categories_by_id;
|
||||
|
||||
var root_category = {
|
||||
name : 'Root',
|
||||
id : 0,
|
||||
parent : null,
|
||||
childrens : [],
|
||||
};
|
||||
|
||||
// add parent and childrens field to categories, find root_categories
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
var cat = categories[i];
|
||||
|
||||
cat.parent = categories_by_id[cat.parent_id[0]];
|
||||
if(!cat.parent){
|
||||
root_category.childrens.push(cat);
|
||||
cat.parent = root_category;
|
||||
}
|
||||
|
||||
cat.childrens = [];
|
||||
for(var j = 0; j < cat.child_id.length; j++){
|
||||
cat.childrens.push(categories_by_id[ cat.child_id[j] ]);
|
||||
}
|
||||
}
|
||||
|
||||
categories.push(root_category);
|
||||
|
||||
// set some default fields for next steps
|
||||
for(var i = 0; i < categories.length; i++){
|
||||
var cat = categories[i];
|
||||
|
||||
cat.product_list = []; //list of all products in the category
|
||||
cat.product_set = {}; // [product.id] === true if product is in category
|
||||
cat.weightable_product_list = [];
|
||||
cat.weightable_product_set = {};
|
||||
cat.weightable = false; //true if directly contains weightable products
|
||||
}
|
||||
|
||||
this.root_category = root_category;
|
||||
|
||||
//we add the products to the categories.
|
||||
for(var i = 0, len = products.length; i < len; i++){
|
||||
var product = products[i];
|
||||
var cat = categories_by_id[product.pos_categ_id[0]];
|
||||
if(cat){
|
||||
cat.product_list.push(product);
|
||||
cat.product_set[product.id] = true;
|
||||
if(product.to_weight){
|
||||
cat.weightable_product_list.push(product);
|
||||
cat.weightable_product_set[product.id] = true;
|
||||
cat.weightable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we build a flat list of all categories that directly contains weightable products
|
||||
this.weightable_categories = [];
|
||||
for(var i = 0, len = categories.length; i < len; i++){
|
||||
var cat = categories[i];
|
||||
if(cat.weightable){
|
||||
this.weightable_categories.push(cat);
|
||||
}
|
||||
}
|
||||
|
||||
// add ancestor field to categories, contains the list of parents of parents, from root to parent
|
||||
function make_ancestors(cat, ancestors){
|
||||
cat.ancestors = ancestors.slice(0);
|
||||
ancestors.push(cat);
|
||||
|
||||
for(var i = 0; i < cat.childrens.length; i++){
|
||||
make_ancestors(cat.childrens[i], ancestors.slice(0));
|
||||
}
|
||||
}
|
||||
|
||||
//add the products of the subcategories to the parent categories
|
||||
function make_products(cat){
|
||||
for(var i = 0; i < cat.childrens.length; i++){
|
||||
make_products(cat.childrens[i]);
|
||||
|
||||
append(cat.product_list, cat.childrens[i].product_list);
|
||||
append(cat.weightable_product_list, cat.childrens[i].weightable_product_list);
|
||||
|
||||
appendSet(cat.product_set, cat.childrens[i].product_set);
|
||||
appendSet(cat.weightable_product_set, cat.childrens[i].weightable_product_set);
|
||||
}
|
||||
}
|
||||
|
||||
make_ancestors(root_category,[]);
|
||||
make_products(root_category);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -608,15 +389,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
return false;
|
||||
}else if(this.get_discount() > 0){ // we don't merge discounted orderlines
|
||||
return false;
|
||||
}else if(this.get_product_type() === 'unit'){
|
||||
return true;
|
||||
}else if(this.get_product_type() === 'weight'){
|
||||
return true;
|
||||
}else if(this.get_product_type() === 'price'){
|
||||
return this.get_product().get('list_price') === orderline.get_product().get('list_price');
|
||||
}else{
|
||||
console.error('point_of_sale/pos_models.js/Orderline.can_be_merged_with() : unknown product type:',this.get('product_type'));
|
||||
}else if(this.price !== orderline.price){
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
},
|
||||
merge: function(orderline){
|
||||
|
@ -882,6 +658,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
change: this.getChange(),
|
||||
name : this.getName(),
|
||||
client: client ? client.name : null ,
|
||||
invoice_id: null, //TODO
|
||||
cashier: cashier ? cashier.name : null,
|
||||
date: {
|
||||
year: date.getFullYear(),
|
||||
|
@ -895,7 +672,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
email: company.email,
|
||||
website: company.website,
|
||||
company_registry: company.company_registry,
|
||||
contact_address: null, //TODO
|
||||
contact_address: company.contact_address,
|
||||
vat: company.vat,
|
||||
name: company.name,
|
||||
phone: company.phone,
|
|
@ -152,14 +152,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.pos_widget.screen_selector.show_popup('help');
|
||||
},
|
||||
|
||||
logout_button_action: function(){
|
||||
this.pos_widget.screen_selector.set_user_mode('client');
|
||||
},
|
||||
|
||||
close_button_action: function(){
|
||||
this.pos_widget.try_close();
|
||||
},
|
||||
|
||||
barcode_product_screen: 'products', //if defined, this screen will be loaded when a product is scanned
|
||||
barcode_product_error_popup: 'error', //if defined, this popup will be loaded when there's an error in the popup
|
||||
|
||||
|
@ -167,14 +159,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
// it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if
|
||||
// there's an error.
|
||||
barcode_product_action: function(ean){
|
||||
if(this.pos_widget.scan_product(ean)){
|
||||
this.pos.proxy.scan_item_success();
|
||||
if(this.barcode_product_screen){
|
||||
this.pos_widget.screen_selector.set_current_screen(this.barcode_product_screen);
|
||||
var self = this;
|
||||
if(self.pos.scan_product(ean)){
|
||||
self.pos.proxy.scan_item_success(ean);
|
||||
if(self.barcode_product_screen){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
|
||||
}
|
||||
}else{
|
||||
if(this.barcode_product_error_popup){
|
||||
this.pos_widget.screen_selector.show_popup(this.barcode_product_error_popup);
|
||||
self.pos.proxy.scan_item_error_unrecognized(ean);
|
||||
if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){
|
||||
self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -194,6 +188,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
return true;
|
||||
}
|
||||
}
|
||||
this.pos.proxy.scan_item_unrecognized(ean);
|
||||
return false;
|
||||
},
|
||||
|
||||
|
@ -207,9 +202,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
if(users[i].ean13 === ean.ean){
|
||||
this.pos.get('selectedOrder').set_client(users[i]);
|
||||
this.pos_widget.username.refresh();
|
||||
this.pos.proxy.scan_item_success(ean);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.pos.proxy.scan_item_unrecognized(ean);
|
||||
return false;
|
||||
//TODO start the transaction
|
||||
},
|
||||
|
@ -217,29 +214,78 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
// what happens when a discount barcode is scanned : the default behavior
|
||||
// is to set the discount on the last order.
|
||||
barcode_discount_action: function(ean){
|
||||
this.pos.proxy.scan_item_success(ean);
|
||||
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
|
||||
if(last_orderline){
|
||||
last_orderline.set_discount(ean.value)
|
||||
}
|
||||
},
|
||||
|
||||
// shows an action bar on the screen. The actionbar is automatically shown when you add a button
|
||||
// with add_action_button()
|
||||
show_action_bar: function(){
|
||||
this.pos_widget.action_bar.show();
|
||||
this.$element.css({'bottom':'105px'});
|
||||
},
|
||||
|
||||
// hides the action bar. The actionbar is automatically hidden when it is empty
|
||||
hide_action_bar: function(){
|
||||
this.pos_widget.action_bar.hide();
|
||||
this.$element.css({'bottom':'0px'});
|
||||
},
|
||||
|
||||
// adds a new button to the action bar. The button definition takes three parameters, all optional :
|
||||
// - label: the text below the button
|
||||
// - icon: a small icon that will be shown
|
||||
// - click: a callback that will be executed when the button is clicked.
|
||||
// the method returns a reference to the button widget, and automatically show the actionbar.
|
||||
add_action_button: function(button_def){
|
||||
this.show_action_bar();
|
||||
return this.pos_widget.action_bar.add_new_button(button_def);
|
||||
},
|
||||
|
||||
// this method shows the screen and sets up all the widget related to this screen. Extend this method
|
||||
// if you want to alter the behavior of the screen.
|
||||
show: function(){
|
||||
var self = this;
|
||||
|
||||
this.hidden = false;
|
||||
if(this.$element){
|
||||
this.$element.show();
|
||||
}
|
||||
|
||||
if(this.pos_widget.action_bar.get_button_count() > 0){
|
||||
this.show_action_bar();
|
||||
}else{
|
||||
this.hide_action_bar();
|
||||
}
|
||||
|
||||
// we add the help button by default. we do this because the buttons are cleared on each refresh so that
|
||||
// the button stay local to each screen
|
||||
this.pos_widget.left_action_bar.add_new_button({
|
||||
label: 'help',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/help.png',
|
||||
click: function(){ self.help_button_action(); },
|
||||
});
|
||||
|
||||
var self = this;
|
||||
var cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier';
|
||||
|
||||
this.pos_widget.set_numpad_visible(this.show_numpad && cashier_mode);
|
||||
this.pos_widget.set_leftpane_visible(this.show_leftpane);
|
||||
this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !cashier_mode);
|
||||
this.pos_widget.set_cashier_controls_visible(cashier_mode);
|
||||
this.pos_widget.action_bar.set_element_visible('help-button', !cashier_mode, function(){ self.help_button_action(); });
|
||||
this.pos_widget.action_bar.set_element_visible('logout-button', cashier_mode && this.pos.use_selfcheckout, function(){ self.logout_button_action(); });
|
||||
this.pos_widget.action_bar.set_element_visible('close-button', cashier_mode, function(){ self.close_button_action(); });
|
||||
|
||||
if(cashier_mode && this.pos.iface_self_checkout){
|
||||
this.pos_widget.client_button.show();
|
||||
}else{
|
||||
this.pos_widget.client_button.hide();
|
||||
}
|
||||
if(cashier_mode){
|
||||
this.pos_widget.close_button.show();
|
||||
}else{
|
||||
this.pos_widget.close_button.hide();
|
||||
}
|
||||
|
||||
this.pos_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode());
|
||||
|
||||
|
@ -251,16 +297,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
});
|
||||
},
|
||||
|
||||
|
||||
// this method is called when the screen is closed to make place for a new screen. this is a good place
|
||||
// to put your cleanup stuff as it is guaranteed that for each show() there is one and only one close()
|
||||
close: function(){
|
||||
if(this.pos.barcode_reader){
|
||||
this.pos.barcode_reader.reset_action_callbacks();
|
||||
}
|
||||
if(this.pos_widget.action_bar){
|
||||
this.pos_widget.action_bar.destroy_buttons();
|
||||
}
|
||||
this.pos_widget.action_bar.destroy_buttons();
|
||||
this.pos_widget.left_action_bar.destroy_buttons();
|
||||
},
|
||||
|
||||
// this methods hides the screen. It's not a good place to put your cleanup stuff as it is called on the
|
||||
|
@ -349,6 +393,9 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
module.ScaleInviteScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ScaleInviteScreenWidget',
|
||||
|
||||
next_screen:'scale',
|
||||
previous_screen:'products',
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
@ -359,21 +406,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
var weight = self.pos.proxy.weighting_read_kg();
|
||||
if(weight > 0.001){
|
||||
clearInterval(this.intervalID);
|
||||
self.pos_widget.screen_selector.set_current_screen('scale');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
}
|
||||
},500);
|
||||
|
||||
this.pos_widget.action_bar.add_new_button(
|
||||
{
|
||||
this.add_action_button({
|
||||
label: 'back',
|
||||
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('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
close: function(){
|
||||
this._super();
|
||||
|
@ -383,25 +428,30 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
module.ScaleScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ScaleScreenWidget',
|
||||
|
||||
next_screen: 'products',
|
||||
previous_screen: 'products',
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
this.renderElement();
|
||||
var self = this;
|
||||
|
||||
this.pos_widget.action_bar.add_new_button({
|
||||
|
||||
this.add_action_button({
|
||||
label: 'back',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
});
|
||||
|
||||
this.validate_button = this.pos_widget.action_bar.add_new_button({
|
||||
this.validate_button = this.add_action_button({
|
||||
label: 'Validate',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
||||
click: function(){
|
||||
self.order_product();
|
||||
self.pos_widget.screen_selector.set_current_screen('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -419,7 +469,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this._super();
|
||||
this.$('.product-picture').click(function(){
|
||||
self.order_product();
|
||||
self.pos_widget.screen_selector.set_current_screen('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
});
|
||||
},
|
||||
get_product: function(){
|
||||
|
@ -444,7 +494,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
get_product_image: function(){
|
||||
var product = this.get_product();
|
||||
return product ? product.get('image_medium') : undefined;
|
||||
return product ? product.get('image') : undefined;
|
||||
},
|
||||
get_product_weight: function(){
|
||||
return this.weight || 0;
|
||||
|
@ -458,6 +508,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
module.ClientPaymentScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ClientPaymentScreenWidget',
|
||||
|
||||
next_screen: 'welcome',
|
||||
previous_screen: 'products',
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
|
@ -486,7 +540,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
self.pos.push_order(currentOrder.exportAsJSON()).then(function() {
|
||||
currentOrder.destroy();
|
||||
self.pos.proxy.transaction_end();
|
||||
self.pos_widget.screen_selector.set_current_screen('welcome');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.next_screen);
|
||||
});
|
||||
}else if(payment === 'payment_rejected'){
|
||||
clearInterval(this.intervalID);
|
||||
|
@ -494,17 +548,15 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
}
|
||||
},500);
|
||||
|
||||
this.pos_widget.action_bar.add_new_button(
|
||||
{
|
||||
this.add_action_button({
|
||||
label: 'back',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){ //TODO Go to ask for weighting screen
|
||||
click: function(){
|
||||
clearInterval(this.intervalID);
|
||||
self.pos.proxy.payment_canceled();
|
||||
self.pos_widget.screen_selector.set_current_screen('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.previous_screen);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
close: function(){
|
||||
this._super();
|
||||
|
@ -515,23 +567,32 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
module.WelcomeScreenWidget = module.ScreenWidget.extend({
|
||||
template:'WelcomeScreenWidget',
|
||||
|
||||
next_screen: 'products',
|
||||
|
||||
show_numpad: false,
|
||||
show_leftpane: false,
|
||||
|
||||
barcode_client_action: function(ean){
|
||||
this._super(ean);
|
||||
this.pos_widget.screen_selector.set_current_screen('products');
|
||||
this.pos_widget.screen_selector.set_current_screen(this.next_screen);
|
||||
},
|
||||
|
||||
show: function(){
|
||||
this._super();
|
||||
var self = this;
|
||||
$('.goodbye-message').css({opacity:1}).show();
|
||||
setTimeout(function(){
|
||||
$('.goodbye-message').animate({opacity:0},500,'swing',function(){$('.goodbye-message').hide();});
|
||||
},3000);
|
||||
},
|
||||
});
|
||||
|
||||
module.ProductScreenWidget = module.ScreenWidget.extend({
|
||||
template:'ProductScreenWidget',
|
||||
|
||||
scale_screen: 'scale_invite',
|
||||
client_next_screen: 'client_payment',
|
||||
|
||||
show_numpad: true,
|
||||
show_leftpane: true,
|
||||
|
||||
|
@ -542,8 +603,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
this.product_list_widget = new module.ProductListWidget(this,{
|
||||
click_product_action: function(product){
|
||||
if(product.get('to_weight') && self.pos.use_scale){
|
||||
self.pos_widget.screen_selector.set_current_screen('scale_invite', {product: product});
|
||||
if(product.get('to_weight') && self.pos.iface_electronic_scale){
|
||||
self.pos_widget.screen_selector.set_current_screen(self.scale_screen, {product: product});
|
||||
}else{
|
||||
self.pos.get('selectedOrder').addProduct(product);
|
||||
}
|
||||
|
@ -559,16 +620,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.product_categories_widget.reset_category();
|
||||
|
||||
this.pos_widget.order_widget.set_numpad_state(this.pos_widget.numpad.state);
|
||||
if(this.pos.use_virtual_keyboard){
|
||||
if(this.pos.iface_vkeyboard){
|
||||
this.pos_widget.onscreen_keyboard.connect();
|
||||
}
|
||||
|
||||
if(this.pos_widget.screen_selector.current_mode === 'client'){
|
||||
this.pos_widget.action_bar.add_new_button({
|
||||
this.add_action_button({
|
||||
label: 'pay',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen('client_payment');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.client_next_screen);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -604,17 +665,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this._super();
|
||||
var self = this;
|
||||
|
||||
this.pos_widget.action_bar.add_new_button({
|
||||
this.add_action_button({
|
||||
label: 'Print',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/printer.png',
|
||||
click: function(){ self.print(); },
|
||||
});
|
||||
|
||||
this.pos_widget.action_bar.add_new_button({
|
||||
this.add_action_button({
|
||||
label: 'Next Order',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-next.png',
|
||||
click: function() { self.finishOrder(); },
|
||||
});
|
||||
|
||||
window.print();
|
||||
},
|
||||
print: function() {
|
||||
window.print();
|
||||
|
@ -643,6 +706,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
module.PaymentScreenWidget = module.ScreenWidget.extend({
|
||||
template: 'PaymentScreenWidget',
|
||||
back_screen: 'products',
|
||||
next_screen: 'receipt',
|
||||
init: function(parent, options) {
|
||||
this._super(parent,options);
|
||||
this.model = options.model;
|
||||
|
@ -654,21 +719,21 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this._super();
|
||||
var self = this;
|
||||
|
||||
if(this.pos.use_cashbox){
|
||||
if(this.pos.iface_cashdrawer){
|
||||
this.pos.proxy.open_cashbox();
|
||||
}
|
||||
|
||||
this.set_numpad_state(this.pos_widget.numpad.state);
|
||||
|
||||
this.back_button = this.pos_widget.action_bar.add_new_button({
|
||||
this.back_button = this.add_action_button({
|
||||
label: 'Back',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png',
|
||||
click: function(){
|
||||
self.pos_widget.screen_selector.set_current_screen('products');
|
||||
self.pos_widget.screen_selector.set_current_screen(self.back_screen);
|
||||
},
|
||||
});
|
||||
|
||||
this.validate_button = this.pos_widget.action_bar.add_new_button({
|
||||
this.validate_button = this.add_action_button({
|
||||
label: 'Validate',
|
||||
icon: '/point_of_sale/static/src/img/icons/png48/validate.png',
|
||||
click: function(){
|
||||
|
@ -682,24 +747,18 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
|||
this.pos_widget.payment_screen.set_numpad_state(null);
|
||||
},
|
||||
back: function() {
|
||||
this.pos_widget.screen_selector.set_current_screen('products');
|
||||
this.pos_widget.screen_selector.set_current_screen(self.back_screen);
|
||||
},
|
||||
validateCurrentOrder: function() {
|
||||
var self = this;
|
||||
var currentOrder = this.pos.get('selectedOrder');
|
||||
|
||||
this.validate_button.$element.attr('disabled','disabled'); //FIXME is the css actually using this attr ?
|
||||
|
||||
this.pos.push_order(currentOrder.exportAsJSON())
|
||||
.then(function() {
|
||||
self.validate_button.$element.removeAttr('disabled');
|
||||
if(self.pos.use_proxy_printer){
|
||||
self.pos.proxy.print_receipt(currentOrder.export_for_printing());
|
||||
self.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen
|
||||
}else{
|
||||
self.pos_widget.screen_selector.set_current_screen('receipt');
|
||||
}
|
||||
});
|
||||
if(this.pos.iface_print_via_proxy){
|
||||
this.pos.proxy.print_receipt(currentOrder.export_for_printing());
|
||||
this.pos.get('selectedOrder').destroy(); //finish order and go back to scan screen
|
||||
}else{
|
||||
this.pos_widget.screen_selector.set_current_screen(this.next_screen);
|
||||
}
|
||||
},
|
||||
bindPaymentLineEvents: function() {
|
||||
this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines');
|
|
@ -65,6 +65,7 @@ function openerp_pos_scrollbar(instance, module){ //module is instance.point_of_
|
|||
this.auto_hide(false);
|
||||
this.$element.bind('mousewheel',function(event,delta){
|
||||
self.scroll(delta*self.wheel_step);
|
||||
return false;
|
||||
});
|
||||
this.$element.bind('click',function(event){
|
||||
var vpos = event.pageY - self.$element.offset().top;
|
|
@ -1,6 +1,57 @@
|
|||
function openerp_pos_widgets(instance, module){ //module is instance.point_of_sale
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
// The ImageCache is used to hide the latency of the application cache on-disk access in chrome
|
||||
// that causes annoying flickering on product pictures. Why the hell a simple access to
|
||||
// the application cache involves such latency is beyond me, hopefully one day this can be
|
||||
// removed.
|
||||
module.ImageCache = instance.web.Class.extend({
|
||||
init: function(options){
|
||||
options = options || {};
|
||||
this.max_size = options.max_size || 500;
|
||||
|
||||
this.cache = {};
|
||||
this.access_time = {};
|
||||
this.size = 0;
|
||||
},
|
||||
get_image_uncached: function(url){
|
||||
var img = new Image();
|
||||
img.src = url;
|
||||
return img;
|
||||
},
|
||||
// returns a DOM Image object from an url, and cache the last 500 (by default) results
|
||||
get_image: function(url){
|
||||
var cached = this.cache[url];
|
||||
if(cached){
|
||||
this.access_time[url] = (new Date()).getTime();
|
||||
return cached;
|
||||
}else{
|
||||
var img = new Image();
|
||||
img.src = url;
|
||||
while(this.size >= this.max_size){
|
||||
var oldestUrl = null;
|
||||
var oldestTime = (new Date()).getTime();
|
||||
for(var url in this.cache){
|
||||
var time = this.access_time[url];
|
||||
if(time <= oldestTime){
|
||||
oldestTime = time;
|
||||
oldestUrl = url;
|
||||
}
|
||||
}
|
||||
if(oldestUrl){
|
||||
delete this.cache[oldestUrl];
|
||||
delete this.access_time[oldestUrl];
|
||||
}
|
||||
this.size--;
|
||||
}
|
||||
this.cache[url] = img;
|
||||
this.access_time[url] = (new Date()).getTime();
|
||||
this.size++;
|
||||
return img;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
module.NumpadWidget = module.PosBaseWidget.extend({
|
||||
template:'NumpadWidget',
|
||||
init: function(parent, options) {
|
||||
|
@ -112,7 +163,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
template:'OrderWidget',
|
||||
init: function(parent, options) {
|
||||
this._super(parent,options);
|
||||
this.compact = false;
|
||||
this.display_mode = options.display_mode || 'numpad'; // 'maximized' | 'actionbar' | 'numpad'
|
||||
this.set_numpad_state(options.numpadState);
|
||||
this.pos.bind('change:selectedOrder', this.change_selected_order, this);
|
||||
this.bind_orderline_events();
|
||||
|
@ -165,8 +216,12 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var self = this;
|
||||
this._super();
|
||||
|
||||
if(!this.compact){
|
||||
if(this.display_mode === 'maximized'){
|
||||
$('.point-of-sale .order-container').css({'bottom':'0px'});
|
||||
}else if(this.display_mode === 'actionbar'){
|
||||
$('.point-of-sale .order-container').css({'bottom':'105px'});
|
||||
}else if(this.display_mode !== 'numpad'){
|
||||
console.error('ERROR: OrderWidget renderElement(): wrong display_mode:',this.display_mode);
|
||||
}
|
||||
|
||||
var $content = this.$('.orderlines');
|
||||
|
@ -211,9 +266,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
var total = order ? order.getTotal() : 0;
|
||||
this.$('.summary .value.total').html(this.format_currency(total));
|
||||
},
|
||||
set_compact: function(compact){
|
||||
if(this.compact !== compact){
|
||||
this.compact = compact;
|
||||
set_display_mode: function(mode){
|
||||
if(this.display_mode !== mode){
|
||||
this.display_mode = mode;
|
||||
this.renderElement();
|
||||
}
|
||||
},
|
||||
|
@ -225,20 +280,16 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this._super(parent,options);
|
||||
this.model = options.model;
|
||||
this.model.attributes.weight = options.weight;
|
||||
this.next_screen = options.next_screen;
|
||||
this.click_product_action = options.click_product_action;
|
||||
this.next_screen = options.next_screen; //when a product is clicked, this screen is set
|
||||
this.click_product_action = options.click_product_action;
|
||||
},
|
||||
add_to_order: function(event) {
|
||||
/* Preserve the category URL */
|
||||
event.preventDefault();
|
||||
return (this.pos.get('selectedOrder')).addProduct(this.model);
|
||||
},
|
||||
set_weight: function(weight){
|
||||
this.model.attributes.weight = weight;
|
||||
this.renderElement();
|
||||
// returns the url of the product thumbnail
|
||||
get_image_url: function() {
|
||||
return '/web/binary/image?session_id='+instance.session.session_id+'&model=product.product&field=image&id='+this.model.get('id');
|
||||
},
|
||||
renderElement: function() {
|
||||
this._super();
|
||||
this.$('img').replaceWith(this.pos_widget.image_cache.get_image(this.get_image_url()));
|
||||
var self = this;
|
||||
$("a", this.$element).click(function(e){
|
||||
if(self.click_product_action){
|
||||
|
@ -313,6 +364,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
module.ActionButtonWidget = instance.web.Widget.extend({
|
||||
template:'ActionButtonWidget',
|
||||
icon_template:'ActionButtonWidgetWithIcon',
|
||||
init: function(parent, options){
|
||||
this._super(parent, options);
|
||||
this.label = options.label || 'button';
|
||||
|
@ -320,7 +372,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.click_action = options.click;
|
||||
if(options.icon){
|
||||
this.icon = options.icon;
|
||||
this.template = 'ActionButtonWidgetWithIcon';
|
||||
this.template = this.icon_template;
|
||||
}
|
||||
},
|
||||
renderElement: function(){
|
||||
|
@ -359,21 +411,25 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.button_list = [];
|
||||
return this;
|
||||
},
|
||||
get_button_count: function(){
|
||||
return this.button_list.length;
|
||||
},
|
||||
add_new_button: function(button_options){
|
||||
if(arguments.length == 1){
|
||||
var button = new module.ActionButtonWidget(this,button_options);
|
||||
this.button_list.push(button);
|
||||
button.appendTo($('.pos-actionbar-button-list'));
|
||||
return button;
|
||||
}else{
|
||||
for(var i = 0; i < arguments.length; i++){
|
||||
this.add_new_button(arguments[i]);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
var button = new module.ActionButtonWidget(this,button_options);
|
||||
this.button_list.push(button);
|
||||
button.appendTo(this.$('.pos-actionbar-button-list'));
|
||||
return button;
|
||||
},
|
||||
show:function(){
|
||||
this.$element.show();
|
||||
},
|
||||
hide:function(){
|
||||
this.$element.hide();
|
||||
},
|
||||
});
|
||||
|
||||
module.CategoryButton = module.PosBaseWidget.extend({
|
||||
});
|
||||
module.ProductCategoriesWidget = module.PosBaseWidget.extend({
|
||||
template: 'ProductCategoriesWidget',
|
||||
init: function(parent, options){
|
||||
|
@ -389,41 +445,53 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
// changes the category. if undefined, sets to root category
|
||||
set_category : function(category){
|
||||
var db = this.pos.db;
|
||||
if(!category){
|
||||
this.category = this.pos.root_category;
|
||||
this.category = db.get_category_by_id(db.root_category_id);
|
||||
}else{
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
this.breadcrumb = [];
|
||||
for(var i = 1; i < this.category.ancestors.length; i++){
|
||||
this.breadcrumb.push(this.category.ancestors[i]);
|
||||
var ancestors_ids = db.get_category_ancestors_ids(this.category.id);
|
||||
for(var i = 1; i < ancestors_ids.length; i++){
|
||||
this.breadcrumb.push(db.get_category_by_id(ancestors_ids[i]));
|
||||
}
|
||||
if(this.category !== this.pos.root_category){
|
||||
if(this.category.id !== db.root_category_id){
|
||||
this.breadcrumb.push(this.category);
|
||||
}
|
||||
if(this.product_type === 'weightable'){
|
||||
this.subcategories = [];
|
||||
for(var i = 0; i < this.category.childrens.length; i++){
|
||||
if(this.category.childrens[i].weightable_product_list.length > 0){
|
||||
this.subcategories.push( this.category.childrens[i]);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
this.subcategories = this.category.childrens || [];
|
||||
}
|
||||
this.subcategories = db.get_category_by_id(db.get_category_childs_ids(this.category.id));
|
||||
},
|
||||
|
||||
get_image_url: function(category){
|
||||
return '/web/binary/image?session_id='+instance.session.session_id+'&model=pos.category&field=image&id='+category.id;
|
||||
},
|
||||
|
||||
renderElement: function(){
|
||||
var self = this;
|
||||
this._super();
|
||||
_.each(this.subcategories, function(category){
|
||||
var button = QWeb.render('CategoryButton',{category:category});
|
||||
button = _.str.trim(button);
|
||||
|
||||
$(button).appendTo(this.$('.category-list')).click(function(event){
|
||||
var hasimages = false; //if none of the subcategories have images, we don't display buttons with icons
|
||||
_.each(this.subcategories, function(category){
|
||||
if(category.image){
|
||||
hasimages = true;
|
||||
}
|
||||
});
|
||||
|
||||
_.each(this.subcategories, function(category){
|
||||
if(hasimages){
|
||||
var button = QWeb.render('CategoryButton',{category:category});
|
||||
var button = _.str.trim(button);
|
||||
var button = $(button);
|
||||
button.find('img').replaceWith(self.pos_widget.image_cache.get_image(self.get_image_url(category)));
|
||||
}else{
|
||||
var button = QWeb.render('CategorySimpleButton',{category:category});
|
||||
button = _.str.trim(button); // we remove whitespace between buttons to fix spacing
|
||||
var button = $(button);
|
||||
}
|
||||
|
||||
button.appendTo(this.$('.category-list')).click(function(event){
|
||||
var id = category.id;
|
||||
var cat = self.pos.categories_by_id[id];
|
||||
var cat = self.pos.db.get_category_by_id(id);
|
||||
self.set_category(cat);
|
||||
self.renderElement();
|
||||
self.search_and_categories(cat);
|
||||
|
@ -432,7 +500,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
// breadcrumb click actions
|
||||
this.$(".oe-pos-categories-list a").click(function(event){
|
||||
var id = $(event.target).data("category-id");
|
||||
var category = self.pos.categories_by_id[id];
|
||||
var category = self.pos.db.get_category_by_id(id);
|
||||
self.set_category(category);
|
||||
self.renderElement();
|
||||
self.search_and_categories(category);
|
||||
|
@ -455,47 +523,30 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
// filters the products, and sets up the search callbacks
|
||||
search_and_categories: function(category){
|
||||
var self = this;
|
||||
|
||||
var all_products = this.pos.get('product_list');
|
||||
var all_packages = this.pos.get('product.packaging');
|
||||
|
||||
// find all products belonging to the current category
|
||||
var products = [];
|
||||
if(this.product_type === 'weightable'){
|
||||
products = all_products.filter( function(product){
|
||||
return self.category.weightable_product_set[product.id];
|
||||
});
|
||||
}else{
|
||||
products = all_products.filter( function(product){
|
||||
return self.category.product_set[product.id];
|
||||
});
|
||||
}
|
||||
var products = this.pos.db.get_product_by_category(this.category.id);
|
||||
self.pos.get('products').reset(products);
|
||||
|
||||
// product lists watch for reset events on 'products' to re-render.
|
||||
// FIXME that means all productlist widget re-render... even the hidden ones !
|
||||
this.pos.get('products').reset(products);
|
||||
|
||||
// find all the products whose name match the query in the searchbox
|
||||
// filter the products according to the search string
|
||||
this.$('.searchbox input').keyup(function(){
|
||||
var results, search_str;
|
||||
search_str = $(this).val().toLowerCase();
|
||||
if(search_str){
|
||||
results = products.filter( function(p){
|
||||
return p.name.toLowerCase().indexOf(search_str) != -1 ||
|
||||
(p.ean13 && p.ean13.indexOf(search_str) != -1);
|
||||
});
|
||||
self.$element.find('.search-clear').fadeIn();
|
||||
query = $(this).val().toLowerCase();
|
||||
if(query){
|
||||
var products = self.pos.db.search_product_in_category(self.category.id, query);
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.search-clear').fadeIn();
|
||||
}else{
|
||||
results = products;
|
||||
self.$element.find('.search-clear').fadeOut();
|
||||
var products = self.pos.db.get_product_by_category(self.category.id);
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.search-clear').fadeOut();
|
||||
}
|
||||
self.pos.get('products').reset(results);
|
||||
});
|
||||
this.$('.searchbox input').click(function(){
|
||||
});
|
||||
|
||||
this.$('.searchbox input').click(function(){}); //Why ???
|
||||
|
||||
//reset the search when clicking on reset
|
||||
this.$('.search-clear').click(function(){
|
||||
var products = self.pos.db.get_product_by_category(self.category.id);
|
||||
self.pos.get('products').reset(products);
|
||||
self.$('.searchbox input').val('').focus();
|
||||
self.$('.search-clear').fadeOut();
|
||||
|
@ -519,11 +570,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.renderElement();
|
||||
});
|
||||
},
|
||||
set_weight: function(weight){
|
||||
for(var i = 0; i < this.product_list.length; i++){
|
||||
this.product_list[i].set_weight(weight);
|
||||
}
|
||||
},
|
||||
renderElement: function() {
|
||||
var self = this;
|
||||
this._super();
|
||||
|
@ -586,14 +632,35 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
});
|
||||
|
||||
module.HeaderButtonWidget = module.PosBaseWidget.extend({
|
||||
template: 'HeaderButtonWidget',
|
||||
init: function(parent, options){
|
||||
options = options || {};
|
||||
this._super(parent, options);
|
||||
this.action = options.action;
|
||||
this.label = options.label;
|
||||
},
|
||||
renderElement: function(){
|
||||
var self = this;
|
||||
this._super();
|
||||
if(this.action){
|
||||
this.$element.click(function(){ self.action(); });
|
||||
}
|
||||
},
|
||||
show: function(){ this.$element.show(); },
|
||||
hide: function(){ this.$element.hide(); },
|
||||
|
||||
});
|
||||
|
||||
|
||||
// ---------- Main Point of Sale Widget ----------
|
||||
|
||||
// this is used to notify the user that data is being synchronized on the network
|
||||
module.SynchNotificationWidget = module.PosBaseWidget.extend({
|
||||
template: "SynchNotificationWidget",
|
||||
init: function(parent,options) {
|
||||
init: function(parent, options){
|
||||
options = options || {};
|
||||
this._super(parent,options);
|
||||
this._super(parent, options);
|
||||
},
|
||||
renderElement: function() {
|
||||
var self = this;
|
||||
|
@ -632,9 +699,19 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
this.pos_widget = this; //So that pos_widget's childs have pos_widget set automatically
|
||||
|
||||
this.numpad_visible = true;
|
||||
this.left_action_bar_visible = true;
|
||||
this.leftpane_visible = true;
|
||||
this.leftpane_width = '440px';
|
||||
this.cashier_controls_visible = true;
|
||||
this.image_cache = new module.ImageCache(); // for faster products image display
|
||||
|
||||
/*
|
||||
//Epileptic mode
|
||||
setInterval(function(){
|
||||
$('body').css({'-webkit-filter':'hue-rotate('+Math.random()*360+'deg)' });
|
||||
},100);
|
||||
*/
|
||||
|
||||
},
|
||||
|
||||
start: function() {
|
||||
|
@ -643,7 +720,9 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.build_currency_template();
|
||||
self.renderElement();
|
||||
|
||||
self.$('.neworder-button').click(_.bind(self.create_new_order, self));
|
||||
self.$('.neworder-button').click(function(){
|
||||
self.pos.add_new_order();
|
||||
});
|
||||
|
||||
//when a new order is created, add an order button widget
|
||||
self.pos.get('orders').bind('add', function(new_order){
|
||||
|
@ -659,6 +738,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
|
||||
self.build_widgets();
|
||||
|
||||
self.screen_selector.set_default_screen();
|
||||
|
||||
self.pos.barcode_reader.connect();
|
||||
|
||||
instance.webclient.set_content_full_screen(true);
|
||||
|
||||
if (!self.pos.get('pos_session')) {
|
||||
|
@ -667,9 +750,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
self.screen_selector.show_popup('error', 'Sorry, we could not find any PoS Configuration for this session');
|
||||
}
|
||||
|
||||
self.$('.loader').animate({opacity:0},3000,'swing',function(){$('.loader').hide();});
|
||||
self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();});
|
||||
self.$('.loader img').hide();
|
||||
|
||||
if(jQuery.deparam(jQuery.param.querystring()).debug !== undefined){
|
||||
window.pos = self.pos;
|
||||
window.pos_widget = self.pos_widget;
|
||||
}
|
||||
|
||||
},function(){ // error when loading models data from the backend
|
||||
self.$('.loader img').hide();
|
||||
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id'])
|
||||
|
@ -682,8 +770,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
}, self));
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// This method instantiates all the screens, widgets, etc. If you want to add new screens change the
|
||||
// startup screen, etc, override this method.
|
||||
build_widgets: function() {
|
||||
var self = this;
|
||||
|
||||
// -------- Screens ---------
|
||||
|
||||
|
@ -725,13 +816,16 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
// -------- Misc ---------
|
||||
|
||||
this.notification = new module.SynchNotificationWidget(this,{});
|
||||
this.notification.replace(this.$('.placeholder-SynchNotificationWidget'));
|
||||
this.notification.appendTo(this.$('#rightheader'));
|
||||
|
||||
this.username = new module.UsernameWidget(this,{});
|
||||
this.username.replace(this.$('.placeholder-UsernameWidget'));
|
||||
|
||||
this.action_bar = new module.ActionBarWidget(this);
|
||||
this.action_bar.appendTo($(".point-of-sale #content"));
|
||||
this.action_bar.appendTo($(".point-of-sale #rightpane"));
|
||||
|
||||
this.left_action_bar = new module.ActionBarWidget(this);
|
||||
this.left_action_bar.appendTo($(".point-of-sale #leftpane"));
|
||||
|
||||
this.paypad = new module.PaypadWidget(this, {});
|
||||
this.paypad.replace($('#placeholder-PaypadWidget'));
|
||||
|
@ -746,6 +840,19 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
'keyboard_model': 'simple'
|
||||
});
|
||||
this.onscreen_keyboard.appendTo($(".point-of-sale #content"));
|
||||
|
||||
this.close_button = new module.HeaderButtonWidget(this,{
|
||||
label:'Close',
|
||||
action: function(){ self.try_close(); },
|
||||
});
|
||||
this.close_button.appendTo(this.$('#rightheader'));
|
||||
|
||||
this.client_button = new module.HeaderButtonWidget(this,{
|
||||
label:'Self-Checkout',
|
||||
action: function(){ self.screen_selector.set_user_mode('client'); },
|
||||
});
|
||||
this.client_button.appendTo(this.$('#rightheader'));
|
||||
|
||||
|
||||
// -------- Screen Selector ---------
|
||||
|
||||
|
@ -768,59 +875,11 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
},
|
||||
default_client_screen: 'welcome',
|
||||
default_cashier_screen: 'products',
|
||||
default_mode: this.pos.use_selfcheckout ? 'client' : 'cashier',
|
||||
default_mode: this.pos.iface_self_checkout ? 'client' : 'cashier',
|
||||
});
|
||||
|
||||
this.screen_selector.set_default_screen();
|
||||
|
||||
this.pos.barcode_reader.connect();
|
||||
},
|
||||
|
||||
//FIXME this method is probably not at the right place ...
|
||||
scan_product: function(parsed_ean){
|
||||
var selectedOrder = this.pos.get('selectedOrder');
|
||||
var scannedProductModel = this.get_product_by_ean(parsed_ean);
|
||||
if (!scannedProductModel){
|
||||
return false;
|
||||
} else {
|
||||
if(parsed_ean.type === 'price'){
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel), { price:parsed_ean.value});
|
||||
}else if(parsed_ean.type === 'weight'){
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel), { quantity:parsed_ean.value, merge:false});
|
||||
}else{
|
||||
selectedOrder.addProduct(new module.Product(scannedProductModel));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
get_product_by_ean: function(parsed_ean) {
|
||||
var allProducts = this.pos.get('product_list');
|
||||
var allPackages = this.pos.get('product.packaging');
|
||||
var scannedProductModel = undefined;
|
||||
|
||||
if (parsed_ean.type === 'price' || parsed_ean.type === 'weight') {
|
||||
var itemCode = parsed_ean.id;
|
||||
var scannedPackaging = _.detect(allPackages, function(pack) {
|
||||
return pack.ean && pack.ean.substring(0,7) === itemCode;
|
||||
});
|
||||
if (scannedPackaging) {
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];});
|
||||
}else{
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 && (pc.ean13.substring(0,7) === parsed_ean.id);});
|
||||
}
|
||||
} else if(parsed_ean.type === 'unit'){
|
||||
scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === parsed_ean.ean;}); //TODO DOES NOT SCALE
|
||||
}
|
||||
return scannedProductModel;
|
||||
},
|
||||
// creates a new order, and add it to the list of orders.
|
||||
create_new_order: function() {
|
||||
var new_order;
|
||||
new_order = new module.Order({ pos: this.pos });
|
||||
this.pos.get('orders').add(new_order);
|
||||
this.pos.set({ selectedOrder: new_order });
|
||||
},
|
||||
changed_pending_operations: function () {
|
||||
var self = this;
|
||||
this.synch_notification.on_change_nbr_pending(self.pos.get('nbr_pending_operations').length);
|
||||
|
@ -830,16 +889,35 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
if(visible !== this.numpad_visible){
|
||||
this.numpad_visible = visible;
|
||||
if(visible){
|
||||
this.set_left_action_bar_visible(false);
|
||||
this.numpad.show();
|
||||
this.paypad.show();
|
||||
this.order_widget.set_compact(true);
|
||||
this.order_widget.set_display_mode('numpad');
|
||||
}else{
|
||||
this.numpad.hide();
|
||||
this.paypad.hide();
|
||||
this.order_widget.set_compact(false);
|
||||
if(this.order_widget.display_mode === 'numpad'){
|
||||
this.order_widget.set_display_mode('maximized');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
set_left_action_bar_visible: function(visible){
|
||||
if(visible !== this.left_action_bar_visible){
|
||||
this.left_action_bar_visible = visible;
|
||||
if(visible){
|
||||
this.set_numpad_visible(false);
|
||||
this.left_action_bar.show();
|
||||
this.order_widget.set_display_mode('actionbar');
|
||||
}else{
|
||||
this.left_action_bar.hide();
|
||||
if(this.order_widget.display_mode === 'actionbar'){
|
||||
this.order_widget.set_display_mode('maximized');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//shows or hide the leftpane (contains the list of orderlines, the numpad, the paypad, etc.)
|
||||
set_leftpane_visible: function(visible){
|
||||
if(visible !== this.leftpane_visible){
|
||||
|
@ -874,12 +952,14 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
|||
});
|
||||
},
|
||||
close: function() {
|
||||
var self = this;
|
||||
this.pos.barcode_reader.disconnect();
|
||||
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_client_pos_menu']], ['res_id']).pipe(
|
||||
_.bind(function(res) {
|
||||
return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) {
|
||||
var action = result.result;
|
||||
action.context = _.extend(action.context || {}, {'cancel_action': {type: 'ir.actions.client', tag: 'reload'}});
|
||||
//self.destroy();
|
||||
this.do_action(action);
|
||||
}, this));
|
||||
}, this));
|
|
@ -15,7 +15,7 @@
|
|||
<button class="neworder-button">+</button>
|
||||
<ol id="orders"></ol>
|
||||
</div>
|
||||
<span class="placeholder-SynchNotificationWidget"></span>
|
||||
<!-- here goes header buttons -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="content">
|
||||
|
@ -44,6 +44,12 @@
|
|||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="HeaderButtonWidget">
|
||||
<div class="header-button">
|
||||
<t t-esc="widget.label" />
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="PosCloseWarning">
|
||||
<div>There are pending operations that could not be saved into the database, are you sure you want to exit?</div>
|
||||
</t>
|
||||
|
@ -83,7 +89,7 @@
|
|||
<t t-name="CategoryButton">
|
||||
<li class='category-button'>
|
||||
<div class="category-img">
|
||||
<img t-att-src="'data:image/gif;base64,'+ category.image_medium" />
|
||||
<img src="" />
|
||||
</div>
|
||||
<div class="category-name">
|
||||
<t t-esc="category.name"/>
|
||||
|
@ -91,6 +97,12 @@
|
|||
</li>
|
||||
</t>
|
||||
|
||||
<t t-name="CategorySimpleButton">
|
||||
<li class='category-simple-button'>
|
||||
<t t-esc="category.name"/>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
<t t-name="ProductCategoriesWidget">
|
||||
<header>
|
||||
<ol class="breadcrumb">
|
||||
|
@ -220,7 +232,7 @@
|
|||
<t t-if="widget.currency.position == 'after'" t-esc="widget.currency.symbol"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="infoline">
|
||||
<div class="infoline" >
|
||||
<span class='left-block'>
|
||||
Change:
|
||||
</span>
|
||||
|
@ -252,6 +264,9 @@
|
|||
<img src="/point_of_sale/static/src/img/scan.png" />
|
||||
<p> Please scan an item or your member card </p>
|
||||
</div>
|
||||
<div class="goodbye-message">
|
||||
<p>Thank you for shopping with us.</p>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
|
@ -342,7 +357,7 @@
|
|||
<li class='product'>
|
||||
<a href="#">
|
||||
<div class="product-img">
|
||||
<img t-att-src="'data:image/gif;base64,'+ widget.model.get('image_medium')" />
|
||||
<img src='' /> <!-- the product thumbnail -->
|
||||
<t t-if="!widget.model.get('to_weight')">
|
||||
<span class="price-tag">
|
||||
<t t-esc="widget.format_currency(widget.model.get('list_price'))"/>
|
||||
|
@ -493,7 +508,7 @@
|
|||
<tr><td>Tax:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTax().toFixed(2))"/>
|
||||
</td></tr>
|
||||
<tr><td>Total:</td><td class="pos-right-align">
|
||||
<tr class="emph"><td>Total:</td><td class="pos-right-align">
|
||||
<t t-esc="widget.format_currency(widget.currentOrder.getTotal().toFixed(2))"/>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
@ -519,30 +534,7 @@
|
|||
|
||||
<t t-name="ActionBarWidget">
|
||||
<div class="pos-actionbar">
|
||||
<div class="pos-actionbar-left-pane">
|
||||
<div class="button help-button">
|
||||
<div class='icon'>
|
||||
<img src="/point_of_sale/static/src/img/icons/png48/help.png" />
|
||||
<div class='iconlabel'>Help</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button close-button">
|
||||
<div class='icon'>
|
||||
<img src="/point_of_sale/static/src/img/icons/png48/shut-down.png" />
|
||||
<div class='iconlabel'>Close</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button logout-button">
|
||||
<div class='icon'>
|
||||
<img src="/point_of_sale/static/src/img/icons/png48/system-log-out.png" />
|
||||
<div class='iconlabel'>Client Mode</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="pos-actionbar-button-list">
|
||||
<!-- <li class="button">BUTTOOON</li>
|
||||
<li class="button">JEEENKIINS</li>
|
||||
<li class="button rightalign">ARGH</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>JSON</title>
|
||||
|
||||
<script type="text/javascript" src="http://localhost:8069/web/webclient/js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>JSON</h1>
|
||||
|
||||
<p id="response"></p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var c = new openerp.init(['web', 'point_of_sale']);
|
||||
c.connection.session_bind('http://localhost:8069').then(function() {
|
||||
var w = new c.point_of_sale.test();
|
||||
w.appendTo($("#response"));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -9,9 +9,3 @@
|
|||
-
|
||||
!python {model: pos.open.statement}: |
|
||||
self.open_statement(cr, uid, [ref('new_statement_open')], context={})
|
||||
-
|
||||
I check that I have some bank statements open for the admin user
|
||||
-
|
||||
!python {model: account.bank.statement}: |
|
||||
ids = self.search(cr, uid, [('state', 'in', ('open','new')), ('user_id', '=', 1)])
|
||||
assert (len(ids)>0), 'No statement open for the admin user!'
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
import re
|
||||
import math
|
||||
|
||||
def ean_checksum(eancode):
|
||||
"""returns the checksum of an ean string of length 13, returns -1 if the string has the wrong length"""
|
||||
if len(eancode) <> 13:
|
||||
return -1
|
||||
oddsum=0
|
||||
evensum=0
|
||||
total=0
|
||||
eanvalue=eancode
|
||||
reversevalue = eanvalue[::-1]
|
||||
finalean=reversevalue[1:]
|
||||
|
||||
for i in range(len(finalean)):
|
||||
if i % 2 == 0:
|
||||
oddsum += int(finalean[i])
|
||||
else:
|
||||
evensum += int(finalean[i])
|
||||
total=(oddsum * 3) + evensum
|
||||
|
||||
check = int(10 - math.ceil(total % 10.0)) %10
|
||||
return check
|
||||
|
||||
def check_ean(eancode):
|
||||
"""returns True if eancode is a valid ean13 string, or null"""
|
||||
if not eancode:
|
||||
return True
|
||||
if len(eancode) <> 13:
|
||||
return False
|
||||
try:
|
||||
int(eancode)
|
||||
except:
|
||||
return False
|
||||
return ean_checksum(eancode) == int(eancode[-1])
|
||||
|
||||
def sanitize_ean13(ean13):
|
||||
"""Creates and returns a valid ean13 from an invalid one"""
|
||||
if not ean13:
|
||||
return "0000000000000"
|
||||
ean13 = re.sub("[A-Za-z]","0",ean13);
|
||||
ean13 = re.sub("[^0-9]","",ean13);
|
||||
ean13 = ean13[:13]
|
||||
if len(ean13) < 13:
|
||||
ean13 = ean13 + '0' * (13-len(ean13))
|
||||
return ean13[:-1] + str(ean_checksum(ean13))
|
||||
|
||||
def main():
|
||||
for arg in sys.argv[1:]:
|
||||
print sanitize_ean13(arg)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -4,13 +4,17 @@ from osv import osv, fields
|
|||
from tools.translate import _
|
||||
import netsvc
|
||||
|
||||
from openerp.addons.point_of_sale.point_of_sale import pos_session
|
||||
|
||||
class pos_session_opening(osv.osv_memory):
|
||||
_name = 'pos.session.opening'
|
||||
|
||||
_columns = {
|
||||
'pos_config_id' : fields.many2one('pos.config', 'Point of Sale', required=True),
|
||||
'pos_session_id' : fields.many2one('pos.session', 'PoS Session'),
|
||||
'pos_state' : fields.char('Session State'),
|
||||
'pos_state' : fields.selection(pos_session.POS_SESSION_STATE,
|
||||
'Session State', readonly=True),
|
||||
'show_config' : fields.boolean('Show Config', readonly=True),
|
||||
}
|
||||
|
||||
def open_ui(self, cr, uid, ids, context=None):
|
||||
|
@ -19,7 +23,7 @@ class pos_session_opening(osv.osv_memory):
|
|||
context['active_id'] = data.pos_session_id.id
|
||||
return {
|
||||
'type' : 'ir.actions.client',
|
||||
'name' : 'Start Point Of Sale',
|
||||
'name' : _('Start Point Of Sale'),
|
||||
'tag' : 'pos.ui',
|
||||
'context' : context
|
||||
}
|
||||
|
@ -87,7 +91,11 @@ class pos_session_opening(osv.osv_memory):
|
|||
if not result:
|
||||
r = self.pool.get('pos.config').search(cr, uid, [], context=context)
|
||||
result = r and r[0] or False
|
||||
|
||||
count = self.pool.get('pos.config').search_count(cr, uid, [('state', '=', 'active')], context=context)
|
||||
show_config = bool(count > 1)
|
||||
return {
|
||||
'pos_config_id' : result
|
||||
'pos_config_id' : result,
|
||||
'show_config' : show_config,
|
||||
}
|
||||
pos_session_opening()
|
||||
|
|
|
@ -6,14 +6,15 @@
|
|||
<field name="model">pos.session.opening</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="PoS Session Opening" version="7.0">
|
||||
<separator string="Select your Point of Sale" colspan="4" />
|
||||
<group>
|
||||
<field name="show_config" invisible="1" />
|
||||
<separator string="Select your Point of Sale" colspan="4" attrs="{'invisible' : [('show_config', '=', False)]}" />
|
||||
<group attrs="{'invisible' : [('show_config', '=', False)]}">
|
||||
<field name="pos_config_id" on_change="on_change_config(pos_config_id)"
|
||||
widget="selection" domain="[('state','=','active')]"
|
||||
class="oe_inline"/>
|
||||
<field name="pos_state" class="oe_inline" attrs="{'invisible' : [('pos_state', '=', False)]}" />
|
||||
</group>
|
||||
<field name="pos_session_id" invisible="1"/>
|
||||
<field name="pos_state" invisible="1"/>
|
||||
<button name="open_ui" type="object" string="Start Selling"
|
||||
attrs="{'invisible' : [('pos_state', 'not in', ('opened',))]}"
|
||||
class="oe_highlight"
|
||||
|
|
|
@ -28,18 +28,10 @@ import re
|
|||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
def is_pair(x):
|
||||
return not x%2
|
||||
|
||||
def check_ean(eancode):
|
||||
if not eancode:
|
||||
return True
|
||||
def ean_checksum(eancode):
|
||||
"""returns the checksum of an ean string of length 13, returns -1 if the string has the wrong length"""
|
||||
if len(eancode) <> 13:
|
||||
return False
|
||||
try:
|
||||
int(eancode)
|
||||
except:
|
||||
return False
|
||||
return -1
|
||||
oddsum=0
|
||||
evensum=0
|
||||
total=0
|
||||
|
@ -48,17 +40,38 @@ def check_ean(eancode):
|
|||
finalean=reversevalue[1:]
|
||||
|
||||
for i in range(len(finalean)):
|
||||
if is_pair(i):
|
||||
if i % 2 == 0:
|
||||
oddsum += int(finalean[i])
|
||||
else:
|
||||
evensum += int(finalean[i])
|
||||
total=(oddsum * 3) + evensum
|
||||
|
||||
check = int(10 - math.ceil(total % 10.0)) %10
|
||||
return check
|
||||
|
||||
if check != int(eancode[-1]):
|
||||
def check_ean(eancode):
|
||||
"""returns True if eancode is a valid ean13 string, or null"""
|
||||
if not eancode:
|
||||
return True
|
||||
if len(eancode) <> 13:
|
||||
return False
|
||||
return True
|
||||
try:
|
||||
int(eancode)
|
||||
except:
|
||||
return False
|
||||
return ean_checksum(eancode) == int(eancode[-1])
|
||||
|
||||
def sanitize_ean13(ean13):
|
||||
"""Creates and returns a valid ean13 from an invalid one"""
|
||||
if not ean13:
|
||||
return "0000000000000"
|
||||
ean13 = re.sub("[A-Za-z]","0",ean13);
|
||||
ean13 = re.sub("[^0-9]","",ean13);
|
||||
ean13 = ean13[:13]
|
||||
if len(ean13) < 13:
|
||||
ean13 = ean13 + '0' * (13-len(ean13))
|
||||
return ean13[:-1] + str(ean_checksum(ean13))
|
||||
|
||||
#----------------------------------------------------------
|
||||
# UOM
|
||||
#----------------------------------------------------------
|
||||
|
@ -195,8 +208,10 @@ product_ul()
|
|||
class product_category(osv.osv):
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not len(ids):
|
||||
if isinstance(ids, (list, tuple)) and not len(ids):
|
||||
return []
|
||||
if isinstance(ids, (long, int)):
|
||||
ids = [ids]
|
||||
reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
|
||||
res = []
|
||||
for record in reads:
|
||||
|
@ -594,6 +609,7 @@ class product_product(osv.osv):
|
|||
res = check_ean(product['ean13'])
|
||||
return res
|
||||
|
||||
|
||||
_constraints = [(_check_ean_key, 'Error: Invalid ean code', ['ean13'])]
|
||||
|
||||
def on_order(self, cr, uid, ids, orderline, quantity):
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,167 +0,0 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_crm
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0.2\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2011-07-05 15:46+0000\n"
|
||||
"PO-Revision-Date: 2011-07-05 15:46+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: sale_crm
|
||||
#: field:crm.make.sale,partner_id:0
|
||||
msgid "Customer"
|
||||
msgstr "Cliente"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:crm.make.sale:0
|
||||
msgid "Convert to Quotation"
|
||||
msgstr "Convertir a presupuesto"
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:108
|
||||
#, python-format
|
||||
msgid "is converted to Quotation."
|
||||
msgstr "se ha convertido a presupuesto."
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:89
|
||||
#, python-format
|
||||
msgid "Data Insufficient!"
|
||||
msgstr "¡Datos insuficientes!"
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:89
|
||||
#, python-format
|
||||
msgid "Customer has no addresses defined!"
|
||||
msgstr "¡El cliente no tiene definidas direcciones!"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.model,name:sale_crm.model_crm_make_sale
|
||||
msgid "Make sales"
|
||||
msgstr "Crear ventas"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.module.module,description:sale_crm.module_meta_information
|
||||
msgid "\n"
|
||||
"This module adds a shortcut on one or several opportunity cases in the CRM.\n"
|
||||
"This shortcut allows you to generate a sales order based on the selected case.\n"
|
||||
"If different cases are open (a list), it generates one sale order by\n"
|
||||
"case.\n"
|
||||
"The case is then closed and linked to the generated sales order.\n"
|
||||
"\n"
|
||||
"We suggest you to install this module if you installed both the sale and the\n"
|
||||
"crm modules.\n"
|
||||
" "
|
||||
msgstr "\n"
|
||||
"Este módulo añade un acceso directo a uno o varios casos de oportunidades en el CRM.\n"
|
||||
"Este acceso directo le permite generar un pedido de venta a partir del caso seleccionado.\n"
|
||||
"Si están abiertos distintos casos (una lista), genera un pedido de venta por\n"
|
||||
"caso.\n"
|
||||
"El caso se cierra y es enlazado al pedido ventas generado.\n"
|
||||
"\n"
|
||||
"Le sugerimos que instale este módulo si ha instalado ambos módulos sale y crm.\n"
|
||||
" "
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:crm.make.sale:0
|
||||
msgid "_Create"
|
||||
msgstr "_Crear"
|
||||
|
||||
#. module: sale_crm
|
||||
#: sql_constraint:sale.order:0
|
||||
msgid "Order Reference must be unique !"
|
||||
msgstr "¡La referencia del pedido debe ser única!"
|
||||
|
||||
#. module: sale_crm
|
||||
#: help:crm.make.sale,close:0
|
||||
msgid "Check this to close the opportunity after having created the sale order."
|
||||
msgstr "Marque esta opción para cerrar la oportunidad después de haber creado el pedido de venta."
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:crm.lead:0
|
||||
msgid "Convert to Quote"
|
||||
msgstr "Convertir a presupuesto"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:account.invoice.report:0
|
||||
#: view:board.board:0
|
||||
msgid "Monthly Turnover"
|
||||
msgstr "Volumen mensual"
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:110
|
||||
#, python-format
|
||||
msgid "Converted to Sales Quotation(id: %s)."
|
||||
msgstr "Convertido a presupuesto de venta (id: %s)."
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:108
|
||||
#, python-format
|
||||
msgid "Opportunity "
|
||||
msgstr "Oportunidad "
|
||||
|
||||
#. module: sale_crm
|
||||
#: code:addons/sale_crm/wizard/crm_make_sale.py:92
|
||||
#, python-format
|
||||
msgid "Opportunity: %s"
|
||||
msgstr "Oportunidad: %s"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.module.module,shortdesc:sale_crm.module_meta_information
|
||||
msgid "Creates Sales order from Opportunity"
|
||||
msgstr "Crea pedido de venta desde oportunidad"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.actions.act_window,name:sale_crm.action_quotation_for_sale_crm
|
||||
msgid "Quotations"
|
||||
msgstr "Presupuestos"
|
||||
|
||||
#. module: sale_crm
|
||||
#: field:crm.make.sale,shop_id:0
|
||||
msgid "Shop"
|
||||
msgstr "Tienda"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:board.board:0
|
||||
msgid "Opportunities by Stage"
|
||||
msgstr "Oportunidades por etapa"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:board.board:0
|
||||
msgid "My Quotations"
|
||||
msgstr "Mis presupuestos"
|
||||
|
||||
#. module: sale_crm
|
||||
#: field:crm.make.sale,close:0
|
||||
msgid "Close Opportunity"
|
||||
msgstr "Cerrar oportunidad"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:sale.order:0
|
||||
#: field:sale.order,section_id:0
|
||||
msgid "Sales Team"
|
||||
msgstr "Equipo de ventas"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.actions.act_window,name:sale_crm.action_crm_make_sale
|
||||
msgid "Make Quotation"
|
||||
msgstr "Realizar un presupuesto"
|
||||
|
||||
#. module: sale_crm
|
||||
#: view:crm.make.sale:0
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#. module: sale_crm
|
||||
#: model:ir.model,name:sale_crm.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_margin
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0.2\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2011-07-05 15:57+0000\n"
|
||||
"PO-Revision-Date: 2011-07-05 15:57+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Category"
|
||||
msgstr "Categoría"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,type:0
|
||||
msgid "Customer Refund"
|
||||
msgstr "Factura de abono de cliente"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,type:0
|
||||
msgid "Customer Invoice"
|
||||
msgstr "Factura de cliente"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "February"
|
||||
msgstr "Febrero"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Current"
|
||||
msgstr "Actual"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Group By..."
|
||||
msgstr "Agrupar por..."
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,state:0
|
||||
msgid "State"
|
||||
msgstr "Estado"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.module.module,description:sale_margin.module_meta_information
|
||||
msgid " \n"
|
||||
" This module adds the 'Margin' on sales order,\n"
|
||||
" which gives the profitability by calculating the difference between the Unit Price and Cost Price\n"
|
||||
" "
|
||||
msgstr " \n"
|
||||
" Este módulo añade el 'Margen' en el pedido de venta,\n"
|
||||
" que proporciona la rentabilidad calculando la diferencia entre el precio unidad y el precio de coste\n"
|
||||
" "
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: selection:report.account.invoice.product,state:0
|
||||
msgid "Draft"
|
||||
msgstr "Borrador"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,state:0
|
||||
msgid "Paid"
|
||||
msgstr "Pagado"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.model,name:sale_margin.model_stock_picking
|
||||
msgid "Picking List"
|
||||
msgstr "Lista de Empaque"
|
||||
|
||||
#. module: sale_margin
|
||||
#: help:sale.order,margin:0
|
||||
msgid "It gives profitability by calculating the difference between the Unit Price and Cost Price."
|
||||
msgstr "Proporciona la rentabilidad calculando la diferencia entre el precio unidad y el precio de coste."
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,type:0
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.model,name:sale_margin.model_report_account_invoice_product
|
||||
msgid "Invoice Statistics"
|
||||
msgstr "Estadísticas de facturas"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,product_id:0
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: sale_margin
|
||||
#: sql_constraint:sale.order:0
|
||||
msgid "Order Reference must be unique !"
|
||||
msgstr "¡La referencia del pedido debe ser única!"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Invoice by Partner"
|
||||
msgstr "Facturas por empresa"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "August"
|
||||
msgstr "Agosto"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: selection:report.account.invoice.product,state:0
|
||||
msgid "Pro-forma"
|
||||
msgstr "Pro-forma"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "May"
|
||||
msgstr "Mayo"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "June"
|
||||
msgstr "Junio"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Date Invoiced"
|
||||
msgstr "Fecha de facturación"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.module.module,shortdesc:sale_margin.module_meta_information
|
||||
msgid "Margins in Sales Order"
|
||||
msgstr "Márgenes en pedidos de venta"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Search Margin"
|
||||
msgstr "Buscar margen"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "This Year"
|
||||
msgstr "Este año"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,date:0
|
||||
msgid "Date"
|
||||
msgstr "Fecha"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "July"
|
||||
msgstr "Julio"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Extended Filters..."
|
||||
msgstr "Filtros extendidos..."
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "This Month"
|
||||
msgstr "Este Mes"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,day:0
|
||||
msgid "Day"
|
||||
msgstr "Día"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,categ_id:0
|
||||
msgid "Categories"
|
||||
msgstr "Categorias"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:account.invoice.line,cost_price:0
|
||||
#: field:report.account.invoice.product,cost_price:0
|
||||
#: field:sale.order.line,purchase_price:0
|
||||
msgid "Cost Price"
|
||||
msgstr "Precio coste"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "October"
|
||||
msgstr "Octubre"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "January"
|
||||
msgstr "Enero"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,year:0
|
||||
msgid "Year"
|
||||
msgstr "Año"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "September"
|
||||
msgstr "Septiembre"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "April"
|
||||
msgstr "Abril"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,amount:0
|
||||
msgid "Amount"
|
||||
msgstr "Importe"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,type:0
|
||||
msgid "Supplier Refund"
|
||||
msgstr "Factura de abono de proveedor"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "March"
|
||||
msgstr "Marzo"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,margin:0
|
||||
#: field:sale.order,margin:0
|
||||
#: field:sale.order.line,margin:0
|
||||
msgid "Margin"
|
||||
msgstr "Margen"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "November"
|
||||
msgstr "Noviembre"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:report.account.invoice.product,quantity:0
|
||||
msgid "Quantity"
|
||||
msgstr "Cantidad"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Invoices by product"
|
||||
msgstr "Facturas por producto"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,type:0
|
||||
msgid "Supplier Invoice"
|
||||
msgstr "Factura de proveedor"
|
||||
|
||||
#. module: sale_margin
|
||||
#: field:stock.picking,invoice_ids:0
|
||||
msgid "Invoices"
|
||||
msgstr "Facturas"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,month:0
|
||||
msgid "December"
|
||||
msgstr "Diciembre"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.model,name:sale_margin.model_account_invoice_line
|
||||
msgid "Invoice Line"
|
||||
msgstr "Línea de factura"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,month:0
|
||||
msgid "Month"
|
||||
msgstr "Mes"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,state:0
|
||||
msgid "Canceled"
|
||||
msgstr "Cancelada"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.actions.act_window,help:sale_margin.action_report_account_invoice_report
|
||||
msgid "This report gives you an overview of all the invoices generated by the system. You can sort and group your results by specific selection criteria to quickly find what you are looking for."
|
||||
msgstr "Este informe ofrece una visión general de todas las facturas generadas por el sistema. Puede ordenar y agrupar los resultados por criterios específicos de selección para encontrar rápidamente lo que busca."
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.ui.menu,name:sale_margin.menu_report_account_invoice_product
|
||||
msgid "Invoice Report"
|
||||
msgstr "Informe de factura"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
msgid "Done"
|
||||
msgstr "Realizado"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.ui.menu,name:sale_margin.menu_report_account_invoice_reoirt
|
||||
msgid "Invoice"
|
||||
msgstr "Factura"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:stock.picking:0
|
||||
msgid "Customer Invoices"
|
||||
msgstr "Facturas de cliente"
|
||||
|
||||
#. module: sale_margin
|
||||
#: view:report.account.invoice.product:0
|
||||
#: field:report.account.invoice.product,partner_id:0
|
||||
msgid "Partner"
|
||||
msgstr "Socio"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.model,name:sale_margin.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
||||
#. module: sale_margin
|
||||
#: selection:report.account.invoice.product,state:0
|
||||
msgid "Open"
|
||||
msgstr "Abierta"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.actions.act_window,name:sale_margin.action_report_account_invoice_report
|
||||
msgid "Invoice Analysis"
|
||||
msgstr "Análisis de facturas"
|
||||
|
||||
#. module: sale_margin
|
||||
#: model:ir.model,name:sale_margin.model_sale_order_line
|
||||
msgid "Sales Order Line"
|
||||
msgstr "Línea pedido de venta"
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_order_dates
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0.2\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2011-07-05 16:02+0000\n"
|
||||
"PO-Revision-Date: 2011-07-05 16:02+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: sql_constraint:sale.order:0
|
||||
msgid "Order Reference must be unique !"
|
||||
msgstr "¡La referencia del pedido debe ser única!"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: help:sale.order,requested_date:0
|
||||
msgid "Date on which customer has requested for sales."
|
||||
msgstr "Fecha en que el cliente ha solicitado la venta."
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: field:sale.order,commitment_date:0
|
||||
msgid "Commitment Date"
|
||||
msgstr "Fecha compromiso"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: field:sale.order,effective_date:0
|
||||
msgid "Effective Date"
|
||||
msgstr "Fecha efectiva"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: model:ir.module.module,shortdesc:sale_order_dates.module_meta_information
|
||||
msgid "Sales Order Dates"
|
||||
msgstr "Fechas en pedidos de venta"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: help:sale.order,effective_date:0
|
||||
msgid "Date on which picking is created."
|
||||
msgstr "Fecha en que la orden ha sido creada."
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: field:sale.order,requested_date:0
|
||||
msgid "Requested Date"
|
||||
msgstr "Fecha solicitud"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: model:ir.model,name:sale_order_dates.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: model:ir.module.module,description:sale_order_dates.module_meta_information
|
||||
msgid "\n"
|
||||
"Add commitment, requested and effective dates on the sales order.\n"
|
||||
""
|
||||
msgstr "\n"
|
||||
"Añade las fechas de compromiso, solicitada y efectiva en el pedido de venta.\n"
|
||||
""
|
||||
|
||||
#. module: sale_order_dates
|
||||
#: help:sale.order,commitment_date:0
|
||||
msgid "Date on which delivery of products is to be made."
|
||||
msgstr "Fecha en que la entrega de productos se va a realizar."
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue