From dc64142141aa36e8a0b2330954fa292e101675db Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Thu, 19 Nov 2015 14:57:23 +0100 Subject: [PATCH] Spinner, filtros catalogo --- lib/vn/hedera/web.php | 4 +- web/forms/admin/shelves/shelves.js | 391 +------------------ web/forms/ecomerce/catalog/catalog.js | 174 +++++---- web/forms/ecomerce/catalog/style.css | 39 +- web/forms/ecomerce/catalog/ui.xml | 153 +++++--- web/forms/ecomerce/invoices/ui.xml | 12 +- web/forms/ecomerce/ticket/ticket.js | 16 +- web/forms/ecomerce/ticket/ui.xml | 18 +- web/image/dark/info.svg | 143 ++----- web/image/info.svg | 143 ++----- web/image/unknown.svg | 123 ++++++ web/js/hedera/app.js | 2 +- web/js/hedera/form.js | 1 + web/js/hedera/gui.css | 10 +- web/js/hedera/gui.js | 4 +- web/js/hedera/gui.xml | 4 +- web/js/hedera/report.js | 77 ++-- web/js/htk/field.js | 2 +- web/js/htk/field/search-entry.js | 52 +++ web/js/htk/field/select.js | 8 +- web/js/htk/grid.js | 28 +- web/js/htk/loader.css | 74 ---- web/js/htk/loader.js | 13 - web/js/htk/main.js | 3 +- web/js/htk/repeater.js | 34 +- web/js/htk/spinner.js | 27 ++ web/js/htk/style.css | 88 ++++- web/js/sql/batch.js | 10 + web/js/sql/filter-item.js | 6 + web/js/sql/filter.js | 2 +- web/js/vn/builder.js | 30 +- web/js/vn/locale.js | 2 +- web/locale/ca/forms/ecomerce/catalog.json | 2 +- web/locale/ca/forms/ecomerce/ticket.json | 2 +- web/locale/ca/js/htk.js | 2 + web/locale/en/forms/ecomerce/catalog.json | 2 +- web/locale/en/forms/ecomerce/confirm.json | 2 +- web/locale/en/forms/ecomerce/ticket.json | 2 +- web/locale/en/js/hedera.js | 4 +- web/locale/en/js/htk.js | 2 + web/locale/es/forms/ecomerce/catalog.json | 2 +- web/locale/es/forms/ecomerce/ticket.json | 2 +- web/locale/es/js/htk.js | 2 + web/locale/fr/forms/ecomerce/catalog.json | 2 +- web/locale/fr/forms/ecomerce/ticket.json | 2 +- web/locale/fr/js/htk.js | 2 + web/locale/mn/forms/ecomerce/catalog.json | 2 +- web/locale/mn/forms/ecomerce/ticket.json | 2 +- web/locale/mn/js/htk.js | 2 + web/reports/delivery-note/delivery-note.js | 21 + web/reports/delivery-note/style.css | 45 +++ web/reports/delivery-note/ui.xml | 97 +++++ web/reports/shelves-report/shelves-report.js | 360 +++++++++++++++++ 53 files changed, 1304 insertions(+), 948 deletions(-) create mode 100644 web/image/unknown.svg create mode 100755 web/js/htk/field/search-entry.js delete mode 100644 web/js/htk/loader.css delete mode 100755 web/js/htk/loader.js create mode 100755 web/js/htk/spinner.js create mode 100755 web/reports/delivery-note/delivery-note.js create mode 100644 web/reports/delivery-note/style.css create mode 100755 web/reports/delivery-note/ui.xml diff --git a/lib/vn/hedera/web.php b/lib/vn/hedera/web.php index 9b5b72b2..0b7cca4d 100755 --- a/lib/vn/hedera/web.php +++ b/lib/vn/hedera/web.php @@ -141,8 +141,8 @@ class Web ,$conf['db']['schema'] ,$conf['db']['port'] ); - self::$conn->query ('CALL user_session_start (#)', - [session_id ()]); + self::$conn->query ('CALL user_session_start (#)', [session_id ()]); + self::$conn->query ('SET @lang = #', [\Vn\Lib\Locale::get ()]); Auth::login ($useCookies); } diff --git a/web/forms/admin/shelves/shelves.js b/web/forms/admin/shelves/shelves.js index 494282d8..0d97dfc2 100755 --- a/web/forms/admin/shelves/shelves.js +++ b/web/forms/admin/shelves/shelves.js @@ -25,387 +25,18 @@ Vn.Shelves = new Class ,onPreviewClick: function () { var batch = new Sql.Batch (); - batch.addParams ({ - 'shelf': this.$('shelf'), - 'wh': this.$('warehouse'), - 'date': this.$('date'), - 'family': this.$('family'), - 'filter': this.$('filter') + batch.addValues ({ + 'shelf': this.$('shelf').value, + 'wh': this.$('warehouse').value, + 'date': this.$('date').value, + 'family': this.$('family').value, + 'filter': this.$('filter').value, + 'title': this.$('report-title').value, + 'max-amount': this.$('max-amount').value, + 'show-packing': this.$('show-packing').value, + 'stack': this.$('stack').value, }); - - var report = new Vn.ShelvesReport ({conn: this.conn}); - report.setParams ( - this.$('report-title').value, - this.$('max-amount').value, - this.$('show-packing').value, - this.$('stack').value, - batch - ); - report.open (); + this.gui.openReport ('shelves-report', batch); } }); -Vn.ShelvesReport = new Class -({ - Extends: Vn.Report - - ,nItem: -1 - ,nColors: 5 - - ,setParams: function (title, maxAmount, showPacking, stack, batch) - { - this.title = title; - this.maxAmount = maxAmount; - this.batch = batch; - this.showPacking = showPacking; - this.stack = stack; - } - - ,open: function () - { - var query = - 'SELECT id, name, width, height, depth, max_height, tray_height, '+ - 'first_tray_elevation, tray_density, vspacing, hspacing '+ - 'FROM shelf WHERE id = #shelf; '+ - 'CALL item_organizer (#wh, #date, #family, #filter)'; - - this.conn.execQuery (query, this.onQueryExec.bind (this), this.batch); - } - - ,onQueryExec: function (resultSet) - { - // Fetch query data - - var res = resultSet.fetchResult (); - res.next (); - - var maxWidth = 170; - var maxHeight = 200; - - var scale = maxWidth / res.get ('width'); - - if (res.get ('max_height') * scale > maxHeight) - scale = maxHeight / res.get ('max_height'); - - var shelf = this.shelf = - { - width: res.get ('width') * scale - ,height: res.get ('height') * scale - ,depth: res.get ('depth') * scale - ,maxHeight: res.get ('max_height') * scale - ,trayHeight: res.get ('tray_height') * scale - ,firstTrayElevation: res.get ('first_tray_elevation') * scale - ,trayDensity: res.get ('tray_density') * scale - ,vspacing: res.get ('vspacing') * scale - ,hspacing: res.get ('hspacing') * scale - }; - - var items = []; - var remainings = []; - var res = resultSet.fetchResult (); - - if (res.data.length == 0) - { - Htk.Toast.showError (_('No items found, check that all fields are correct')); - return; - } - - var boxScale = scale * 10; - - while (res.next ()) - if (!this.maxAmount || res.get ('etiquetas') <= this.maxAmount) - { - items.push ({ - id: res.get ('Id_Article') - ,name: res.get ('Article') - ,packing: res.get ('packing') - ,amount: res.get ('etiquetas') - ,boxHeight: res.get ('z') * boxScale - ,boxWidth: res.get ('x') * boxScale - ,boxDepth: res.get ('y') * boxScale - }); - } - else - { - remainings.push ({ - id: res.get ('Id_Article') - ,name: res.get ('Article') - ,packing: res.get ('packing') - ,amount: res.get ('etiquetas') - }); - } - - // Intializes the allocator - - alloc = new Vn.Allocator (); - alloc.items = items; - alloc.shelfFunc = this.drawShelf.bind (this); - alloc.boxFunc = this.drawBox.bind (this); - alloc.stack = this.stack; - alloc.nTrays = Math.ceil ( - (shelf.height - shelf.firstTrayElevation) / - (shelf.trayHeight + shelf.trayDensity) - ); - alloc.width = shelf.width - shelf.hspacing * 2; - alloc.depth = shelf.depth; - alloc.trayHeight = shelf.trayHeight - shelf.vspacing; - alloc.topTrayHeight = shelf.maxHeight - shelf.vspacing - - shelf.firstTrayElevation - (alloc.nTrays - 1) * shelf.trayHeight; - - // Opens the report - - if (!this.createWindow ('shelves')) - return; - - // Remaining amount - - if (remainings.length > 0) - { - var sheet = this.doc.createElement ('div'); - sheet.className = 'sheet'; - this.doc.body.appendChild (sheet); - - var title = this.doc.createElement ('h1'); - title.className = 'title'; - title.appendChild (this.doc.createTextNode (this.title)); - sheet.appendChild (title); - - var subtitle = this.doc.createElement ('h2'); - subtitle.className = 'subtitle'; - subtitle.appendChild (this.doc.createTextNode (_('Pallets'))); - sheet.appendChild (subtitle); - - var ul = this.doc.createElement ('ul'); - sheet.appendChild (ul); - - for (var i = 0; i < remainings.length; i++) - { - var li = this.doc.createElement ('li'); - ul.appendChild (li); - - var span = this.doc.createElement ('span'); - span.className = 'item-id'; - span.appendChild (this.doc.createTextNode (remainings[i].id.toLocaleString ())); - li.appendChild (span); - - var span = this.doc.createElement ('span'); - span.className = 'item'; - span.appendChild (this.doc.createTextNode (remainings[i].name)); - li.appendChild (span); - - if (this.showPacking) - span.appendChild (this.doc.createTextNode (' '+ remainings[i].packing)); - - var span = this.doc.createElement ('span'); - span.className = 'amount'; - span.appendChild (this.doc.createTextNode (remainings[i].amount)); - li.appendChild (span); - } - } - - // Draws the shelves - - alloc.run (); - this.drawShelfEnding (); - } - - ,drawShelf: function (allocator, item) - { - var shelf = this.shelf; - - var sheet = this.doc.createElement ('div'); - sheet.className = 'sheet'; - this.doc.body.appendChild (sheet); - - // Draws the title - - var pageNumber = this.doc.createElement ('h1'); - pageNumber.className = 'page-number'; - pageNumber.appendChild (this.doc.createTextNode (allocator.currentShelf + 1)); - sheet.appendChild (pageNumber); - - var title = this.doc.createElement ('h1'); - title.className = 'title'; - title.appendChild (this.doc.createTextNode (this.title)); - sheet.appendChild (title); - - var subtitle = this.doc.createElement ('h2'); - subtitle.className = 'subtitle'; - subtitle.appendChild (this.doc.createTextNode (item.id.toLocaleString ())); - sheet.appendChild (subtitle); - - this.drawShelfEnding (); - this.lastSubtitle = subtitle; - - // Draws the shelf - - var shelfDiv = this.shelfDiv = this.doc.createElement ('div'); - shelfDiv.className = 'shelf'; - shelfDiv.style.width = this.mm (shelf.width); - shelfDiv.style.height = this.mm (shelf.maxHeight); - sheet.appendChild (shelfDiv); - - // Draws trays - - var lastTrayY = shelf.firstTrayElevation; - - if (shelf.trayHeight > 0) - while (lastTrayY + shelf.trayDensity < shelf.height) - { - var tray = this.doc.createElement ('div'); - tray.className = 'tray'; - tray.style.width = this.mm (shelf.width); - tray.style.height = this.mm (shelf.trayDensity); - tray.style.bottom = this.mm (lastTrayY); - shelfDiv.appendChild (tray); - - lastTrayY += shelf.trayHeight + shelf.trayDensity; - } - } - - ,drawShelfEnding: function () - { - if (this.lastSubtitle) - this.lastSubtitle.appendChild ( - this.doc.createTextNode (' - '+ this.lastItem.id.toLocaleString ())); - } - - ,mm: function (size) - { - return size.toFixed (2) +'mm'; - } - - ,drawBox: function (allocator, item, amount) - { - if (item.boxWidth == 0 || item.boxHeight == 0) - return; - - var shelf = this.shelf; - - var x = allocator.trayX + shelf.hspacing; - var y = allocator.trayY - + shelf.firstTrayElevation + shelf.trayDensity - + allocator.currentTray * (shelf.trayHeight + shelf.trayDensity); - - var box = this.doc.createElement ('div'); - box.className = 'box'; - this.shelfDiv.appendChild (box); - - box.style.left = this.mm (x); - box.style.bottom = this.mm (y); - box.style.width = this.mm (item.boxWidth); - box.style.height = this.mm (item.boxHeight); - - if (amount == 0) - this.nItem++; - - var nColor = this.nItem % this.nColors; - Vn.Node.addClass (box, 'color'+ nColor); - - if (amount == 0 || allocator.firstShelfBox) - { - var fontSize = item.boxWidth / 5.2; - - if (fontSize > item.boxHeight - 1) - fontSize = item.boxHeight - 1; - - var boxLabel = this.doc.createElement ('div'); - boxLabel.className = 'box-label'; - boxLabel.style.fontSize = this.mm (fontSize); - boxLabel.appendChild (this.doc.createTextNode (item.id.toLocaleString ())); - box.appendChild (boxLabel); - } - - this.lastItem = item; - } -}); - -Vn.Allocator = new Class -({ - addShelf: function (item) - { - this.currentShelf++; - this.firstShelfBox = true; - - if (this.shelfFunc) - this.shelfFunc (this, item); - } - - ,addTray: function (item) - { - if (this.currentTray <= 0) - { - this.addShelf (item); - this.currentTray = this.nTrays - 1; - } - else - this.currentTray--; - - this.trayX = 0; - } - - ,addColumn: function (item) - { - if (this.trayX + this.columnWidth + item.boxWidth > this.width - || this.currentTray == -1) - this.addTray (item); - else - this.trayX += this.columnWidth; - - this.trayY = 0; - this.columnWidth = item.boxWidth; - this.lastBoxWidth = item.boxWidth; - } - - ,addBox: function (item, amount) - { - var trayHeight = this.trayHeight; - - if (this.currentTray == this.nTrays - 1) - trayHeight = this.topTrayHeight; - - if (this.trayY + item.boxHeight > trayHeight - || item.boxWidth > this.lastBoxWidth - || (!this.stack && amount == 0)) - this.addColumn (item); - - if (this.boxFunc) - this.boxFunc (this, item, amount); - - this.trayY += item.boxHeight; - - if (item.boxWidth < this.lastBoxWidth) - this.lastBoxWidth = item.boxWidth; - } - - ,run: function () - { - this.firstShelfBox = false; - this.currentShelf = -1; - this.currentTray = -1; - this.columnWidth = 0; - this.lastBoxWidth = 0; - this.trayX = 0; - this.trayY = 0; - this.remaining = false; - - for (var i = 0; i < this.items.length; i++) - { - var item = this.items[i]; - var boxIncrement = Math.floor (this.depth / item.boxDepth); - - if (boxIncrement < 1) - boxIncrement = 1; - - for (var amount = 0; amount < item.amount; amount += boxIncrement) - { - this.addBox (item, amount); - this.firstShelfBox = false; - } - } - - return this.currentShelf + 1; - } - -}); - diff --git a/web/forms/ecomerce/catalog/catalog.js b/web/forms/ecomerce/catalog/catalog.js index 08340383..220ef287 100755 --- a/web/forms/ecomerce/catalog/catalog.js +++ b/web/forms/ecomerce/catalog/catalog.js @@ -150,32 +150,12 @@ Vn.Catalog = new Class if (row != -1) title = types.get (row, 'Tipo'); } - else if (this.$('search-entry').value) + else if (this.$('search').value) title = _('SearchResults'); Vn.Node.setText (this.$('title-text'), title); } - ,onSearch: function (event) - { - var searchTags = this.$('search-entry').value; - searchTags = searchTags != '' ? searchTags : undefined; - - var batch = this.$('filter-batch'); - batch.block (); - - this.$('search').value = searchTags; - - if (searchTags) - { - this.$('type').value = undefined; - this.$('realm').value = undefined; - } - - batch.unblock (); - batch.changed (); - } - ,onRightPanelClick: function (event) { event.stopPropagation (); @@ -247,6 +227,23 @@ Vn.Catalog = new Class } } + ,onInfoClick: function (button, form) + { + var descNode = this.$('desc-popup'); + Vn.Node.removeChilds (descNode); + + var desc = this.$('items-model').get (form.row, 'description'); + + if (!desc) + desc = _('No info available'); + + descNode.appendChild (document.createTextNode (desc)); + + var popup = new Htk.Popup (); + popup.setChildNode (descNode); + popup.show (button.getNode ()); + } + ,onGridAddItemClick: function (button, form) { this.showAmountPopup (button.getNode (), form.row); @@ -270,7 +267,7 @@ Vn.Catalog = new Class this.itemRow = row; this.onEraseClick (); - this.popup.show (button); + this.popup.show (button); } ,onAddLotClick: function (column, value, row, button) @@ -367,6 +364,15 @@ Vn.Catalog = new Class batch.unblock (); batch.changed (); } + + ,gridRenderer: function (res, form) + { + if (!form.get ('description')) + { + var button = res.$('info-button').getNode (); + button.style.display = 'none'; + } + } }); Vn.Filter = new Class @@ -382,8 +388,8 @@ Vn.Filter = new Class ,set: function (x) { x.batch = this._batch; - this._select.model = x; this._model = x; + this._select.model = x; } ,get: function () { @@ -428,21 +434,10 @@ Vn.Filter = new Class return this._filter; } }, - disableOperation: - { - type: Sql.FilterItem - ,set: function (x) - { - this._disableFilter = x; - } - ,get: function () - { - return this._disableFilter; - } - } } - ,_columnIndex: 1 + ,_valueColumnIndex: 0 + ,_showColumnIndex: 1 ,initialize: function (props) { @@ -452,6 +447,7 @@ Vn.Filter = new Class this._select = new Htk.Select (); this._select.on ('mousedown', this._onClick, this); this._select.on ('changed', this._onChange, this); + this._select.on ('ready', this._onReady, this); this.node.appendChild (this._select.getNode ()); this._ul = document.createElement ('ul'); @@ -464,51 +460,38 @@ Vn.Filter = new Class ,_onClick: function () { if (this._model && this._model.status === Db.Model.Status.CLEAN) - { - this._filter.alwaysReady = true; - this._disableFilter.disabled = true; - this._model.refresh (); - - this._disableFilter.disabled = false; - this._filter.alwaysReady = false; - } } ,_onCloseClick: function (li) { - Vn.Node.remove (li); + this._removeSelectionNode (); this._changeValue (undefined); } + ,_removeSelectionNode: function () + { + if (this._lastLi) + { + Vn.Node.remove (this._lastLi); + this._lastLi = null; + this._label = null; + } + } + ,_onChange: function () - { + { if (this._select.value === null || this._select.value === undefined) return; - - if (this._lastLi) - Vn.Node.remove (this._lastLi); - - var li = this._lastLi = document.createElement ('li'); - this._ul.appendChild (li); - var button = document.createElement ('button'); - button.addEventListener ('click', - this._onCloseClick.bind (this, li)); - li.appendChild (button); - - var img = document.createElement ('img'); - img.src = 'image/close.svg'; - button.appendChild (img); + this._realSetValue (this._select.value); + } - var label = this._select.getByIndex (this._columnIndex); - var text = document.createTextNode (label); - li.appendChild (text); - - setTimeout (this._onTimeout.bind (this)); - - this._changeValue (this._select.value); + ,_onReady: function () + { + if (this._emptyLabel) + this._refreshLabel (); } ,_changeValue: function (newValue) @@ -522,6 +505,63 @@ Vn.Filter = new Class { this._select.value = null; } + + ,putValue: function (value) + { + this._onClick (); + this._realSetValue (value); + } + + ,_realSetValue: function (value) + { + this._removeSelectionNode (); + + if (value === null || value === undefined) + return; + + var li = this._lastLi = document.createElement ('li'); + this._ul.appendChild (li); + + var button = document.createElement ('button'); + button.addEventListener ('click', + this._onCloseClick.bind (this, li)); + li.appendChild (button); + + var img = document.createElement ('img'); + img.src = 'image/close.svg'; + button.appendChild (img); + + var text = this._label = document.createTextNode (''); + li.appendChild (text); + + setTimeout (this._onTimeout.bind (this)); + + this._changeValue (value); + this._refreshLabel (); + } + + ,_refreshLabel: function () + { + if (!this._label) + return; + + var row = -1; + + if (this._model.ready) + row = this._model.searchByIndex (this._valueColumnIndex, this._value); + + if (row != -1) + { + var label = this._model.getByIndex (row, this._showColumnIndex); + this._label.nodeValue = label; + this._emptyLabel = false; + } + else + { + this._emptyLabel = true; + this._label.nodeValue = _('Loading...'); + } + } }); Vn.ColumnItem = new Class diff --git a/web/forms/ecomerce/catalog/style.css b/web/forms/ecomerce/catalog/style.css index 7910e8ac..391d48e0 100755 --- a/web/forms/ecomerce/catalog/style.css +++ b/web/forms/ecomerce/catalog/style.css @@ -33,28 +33,9 @@ /* Topbar */ -.action-bar > div > .search +.catalog-actions > .htk-search-entry { margin-top: .8em; - background-color: white; - height: 2.3em; -} -.search > input -{ - margin: 0; - border: none; - width: 8em; - box-shadow: none; -} -.search > input:focus -{ - background-color: initial; -} -.search > img -{ - margin: 0; - margin-left: .4em; - vertical-align: middle; } /* Right panel */ @@ -177,6 +158,14 @@ button.basket:hover background-color: rgba(1, 1, 1, .1); } +/* Item description */ + +.desc-popup +{ + padding: 1em; + max-width: 15em; +} + /* Lots popup*/ div.amount @@ -317,6 +306,10 @@ td.third-category bottom: .5em; right: .5em; } +.item-box > .info-button +{ + float: right; +} /* Transitions */ @@ -327,18 +320,18 @@ td.third-category /* Mobile */ -.catalog-actions button.menu +.catalog-actions > button.menu { display: none; } -.catalog-actions button.menu > img +.catalog-actions > button.menu > img { height: 1.8em; } @media (max-width: 950px) { - .catalog-actions button.menu + .catalog-actions > button.menu { display: block; } diff --git a/web/forms/ecomerce/catalog/ui.xml b/web/forms/ecomerce/catalog/ui.xml index da7dc0c0..ba2bfab4 100755 --- a/web/forms/ecomerce/catalog/ui.xml +++ b/web/forms/ecomerce/catalog/ui.xml @@ -10,16 +10,16 @@ + + + + - - - - - + @@ -39,11 +39,6 @@ - - - - - @@ -55,26 +50,32 @@ GROUP BY warehouse_id - + CREATE TEMPORARY TABLE tmp.bionic_calc (INDEX (item_id)) ENGINE=MEMORY - SELECT Id_Article item_id FROM vn2008.Articles + SELECT a.Id_Article item_id FROM vn2008.Articles a + JOIN vn2008.Tipos t ON t.tipo_id = a.tipo_id WHERE #filter; CALL bionic_calc (); - SELECT a.Id_Article item_id, a.description, t.available, t.price, + SELECT a.Id_Article item_id, a.description, b.available, b.price, p.name producer, a.Foto, a.Article, a.Categoria, a.Medida, - a.Tallos, i.name color, o.Abreviatura, o.Origen - FROM tmp.bionic_item t - JOIN vn2008.Articles a ON a.Id_Article = t.item_id + a.Tallos, c.str color, o.str origin + FROM tmp.bionic_item b + JOIN vn2008.Articles a ON a.Id_Article = b.item_id LEFT JOIN vn2008.producer p ON p.producer_id = a.producer_id - LEFT JOIN vn2008.Tintas i ON i.Id_Tinta = a.Color - LEFT JOIN vn2008.Origen o ON a.id_origen = o.id - WHERE t.available > 0 + LEFT JOIN vn_locale.color_view c ON c.color_id = a.Color + LEFT JOIN vn_locale.origin_view o ON o.origin_id = a.id_origen + WHERE b.available > 0 ORDER BY a.Article, a.Medida LIMIT 400; + + + + + @@ -92,10 +93,8 @@

Catalog

- +
- +
- +
@@ -169,6 +177,14 @@ show-full="true" full-dir="900x900"/>
+

@@ -181,7 +197,7 @@

- +

@@ -241,55 +257,73 @@ property="model" on-status-changed="onTypeChange"> - SELECT id, reino, color FROM vn2008.reinos - WHERE display != FALSE ORDER BY reino + SELECT r.id, l.str name, r.color + FROM vn2008.reinos r + LEFT JOIN vn_locale.realm_view l ON l.realm_id = r.id + WHERE r.display != FALSE + ORDER BY name + param="type"> CALL item_available (); - SELECT DISTINCT t.tipo_id, t.Tipo type + SELECT DISTINCT t.tipo_id, l.str name FROM vn2008.Tipos t JOIN vn2008.Articles a ON a.tipo_id = t.tipo_id + LEFT JOIN vn_locale.family_view l ON l.family_id = t.tipo_id JOIN tmp.item_available i ON i.item_id = a.Id_Article WHERE #filter - ORDER BY t.Tipo + ORDER BY name + + + + + + + + + + + + param="color"> CALL item_available (); - SELECT DISTINCT c.Id_Tinta, c.name + SELECT DISTINCT c.Id_Tinta, l.str name FROM vn2008.Tintas c JOIN vn2008.Articles a ON a.Color = c.Id_Tinta + LEFT JOIN vn_locale.color_view l ON l.color_id = c.Id_Tinta JOIN tmp.item_available i ON i.item_id = a.Id_Article WHERE #filter - ORDER BY c.name + ORDER BY name + + + + + + + + param="producer"> CALL item_available (); @@ -298,32 +332,43 @@ JOIN vn2008.Articles a ON a.producer_id = p.producer_id JOIN tmp.item_available i ON i.item_id = a.Id_Article WHERE #filter - ORDER BY p.name + ORDER BY name + + + + + + + + param="origin"> CALL item_available (); - SELECT DISTINCT o.id, o.Origen, o.Abreviatura + SELECT DISTINCT o.id, l.str name, o.Abreviatura FROM vn2008.Origen o JOIN vn2008.Articles a ON a.id_origen = o.id + LEFT JOIN vn_locale.origin_view l ON l.origin_id = o.id JOIN tmp.item_available i ON i.item_id = a.Id_Article WHERE #filter - ORDER BY o.Origen + ORDER BY name + + + + + + + + param="category"> CALL item_available (); @@ -334,6 +379,13 @@ ORDER BY a.Categoria + + + + + + +
+
diff --git a/web/forms/ecomerce/invoices/ui.xml b/web/forms/ecomerce/invoices/ui.xml index 7a257509..5f50c1b6 100755 --- a/web/forms/ecomerce/invoices/ui.xml +++ b/web/forms/ecomerce/invoices/ui.xml @@ -6,11 +6,13 @@
- - SELECT invoice_id, serial_num, issued, amount - FROM invoice_view - ORDER BY issued DESC - LIMIT 100 + + + SELECT invoice_id, serial_num, issued, amount + FROM invoice_view + ORDER BY issued DESC + LIMIT 100 + diff --git a/web/forms/ecomerce/ticket/ticket.js b/web/forms/ecomerce/ticket/ticket.js index daf4edb4..979b126c 100755 --- a/web/forms/ecomerce/ticket/ticket.js +++ b/web/forms/ecomerce/ticket/ticket.js @@ -3,19 +3,11 @@ Vn.Ticket = new Class ({ Extends: Vn.Form - ,activate: function () + ,onPrintClick: function (event) { - this.$('print').addEventListener ('click', this.printClicked.bind (this)); - this.$('subtotal').renderer = this.subtotalRenderer.bind (this); - this.$('ticket-subtotal').func = this.subtotal; - } - - ,printClicked: function (event) - { - var report = window.open ('', 'report', - 'resizable=yes,height=600,width=750,scrollbars=yes,menubar=no'); - report.document.body.innerHTML = this.$('report').innerHTML; - report.print (); + var batch = new Sql.Batch (); + batch.addValue ('ticket', this.$('ticket-id').value); + this.gui.openReport ('delivery-note', batch); } ,subtotalRenderer: function (column, form) diff --git a/web/forms/ecomerce/ticket/ui.xml b/web/forms/ecomerce/ticket/ui.xml index 0b907c0f..28367139 100755 --- a/web/forms/ecomerce/ticket/ui.xml +++ b/web/forms/ecomerce/ticket/ui.xml @@ -1,8 +1,7 @@ - - - + + @@ -26,10 +25,11 @@

OrderDetail

- +
@@ -74,7 +74,7 @@ - + @@ -115,7 +115,7 @@ - +
diff --git a/web/image/dark/info.svg b/web/image/dark/info.svg index 54837200..97a12573 100644 --- a/web/image/dark/info.svg +++ b/web/image/dark/info.svg @@ -1,5 +1,6 @@ - + - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - image/svg+xml - - - Gnome Symbolic Icon Theme - - - - - - - - - - - - + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1016" + id="namedview5" + showgrid="false" + inkscape:zoom="51.6875" + inkscape:cx="7.2631221" + inkscape:cy="7.9613059" + inkscape:window-x="1920" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /> \ No newline at end of file diff --git a/web/image/info.svg b/web/image/info.svg index f9ffc299..c0803073 100644 --- a/web/image/info.svg +++ b/web/image/info.svg @@ -1,5 +1,6 @@ - + - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - image/svg+xml - - - Gnome Symbolic Icon Theme - - - - - - - - - - - - + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1016" + id="namedview5" + showgrid="false" + inkscape:zoom="51.6875" + inkscape:cx="7.2631221" + inkscape:cy="7.9613059" + inkscape:window-x="1920" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /> \ No newline at end of file diff --git a/web/image/unknown.svg b/web/image/unknown.svg new file mode 100644 index 00000000..f9ffc299 --- /dev/null +++ b/web/image/unknown.svg @@ -0,0 +1,123 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + + + diff --git a/web/js/hedera/app.js b/web/js/hedera/app.js index 0d64ff29..1681cf96 100644 --- a/web/js/hedera/app.js +++ b/web/js/hedera/app.js @@ -61,7 +61,7 @@ Vn.App = new Class error.fileName = file; error.lineNumber = line; - Htk.Toast.showError (_('InternalError')); + Htk.Toast.showError (_('There was an internal error')); this.notifyError (error); } diff --git a/web/js/hedera/form.js b/web/js/hedera/form.js index 6399d153..790786be 100755 --- a/web/js/hedera/form.js +++ b/web/js/hedera/form.js @@ -34,6 +34,7 @@ Vn.Form = new Class var builder = new Vn.Builder (); builder.signalData = this; + builder.add ('conn', this.conn); builder.loadXml ('forms/'+ this.formInfo.path +'/ui.xml'); var res = this.builder = builder.load (); diff --git a/web/js/hedera/gui.css b/web/js/hedera/gui.css index ded5209c..3338aa6f 100755 --- a/web/js/hedera/gui.css +++ b/web/js/hedera/gui.css @@ -65,14 +65,13 @@ font-weight: normal; font-size: 1.4em; padding: .7em .6em; + padding-right: 0; margin: 0; } -.vn-gui .top-bar > .loader +.vn-gui .top-bar > .htk-spinner { - float: right; - margin: 5% 1em; - visibility: hidden; - height: 90%; + float: left; + margin: 1.05em .8em; } .vn-gui .exit { @@ -110,7 +109,6 @@ { float: left; padding: 0; - margin: 1.3em .5em; } .vn-gui .action-bar button { diff --git a/web/js/hedera/gui.js b/web/js/hedera/gui.js index 65b25f94..dbc0a588 100755 --- a/web/js/hedera/gui.js +++ b/web/js/hedera/gui.js @@ -253,7 +253,7 @@ Vn.Gui = new Class this.loadingCount++; if (this.loadingCount == 1) - this.$('loader').style.visibility = 'visible'; + this.$('loader').start (); } ,loaderPop: function () @@ -264,7 +264,7 @@ Vn.Gui = new Class this.loadingCount--; if (this.loadingCount == 0) - this.$('loader').style.visibility = 'hidden'; + this.$('loader').stop (); } ,newVersion: function (error) diff --git a/web/js/hedera/gui.xml b/web/js/hedera/gui.xml index e152d7ed..630171f8 100755 --- a/web/js/hedera/gui.xml +++ b/web/js/hedera/gui.xml @@ -35,10 +35,8 @@ _Exit
-
- -
+
diff --git a/web/js/hedera/report.js b/web/js/hedera/report.js index 0853b69c..e49035a5 100755 --- a/web/js/hedera/report.js +++ b/web/js/hedera/report.js @@ -28,33 +28,7 @@ Vn.Report = new Class ,open: function (batch) { this.batch = batch; - this.createWindow (this._onWindowLoad.bind (this)); - } - - ,_onWindowLoad: function () - { - this.doc = this.window.document - - var path = this.info.path; - - this.includeCss ('reports/'+ path +'/style.css'); - - var printButton = this.doc.createElement ('button'); - printButton.className = 'print-button'; - printButton.appendChild (this.doc.createTextNode (_('Print'))); - printButton.addEventListener ('click', this.print.bind (this)); - this.doc.body.appendChild (printButton); - - var builder = new Vn.Builder (); - builder.signalData = this; - builder.add ('batch', this.batch); - builder.add ('conn', this.conn); - builder.loadXml ('reports/'+ path +'/ui.xml'); - - var res = this.builderResult = builder.load (); - res.link (); - - this.doc.body.appendChild (res.$('report')); + this.createWindow (); } ,print: function () @@ -78,21 +52,58 @@ Vn.Report = new Class head.appendChild (link); } - ,createWindow: function (callback) + ,createWindow: function () { - var reportWindow = window.open ('js/hedera/report.html', '_blank'/*this.info.path*/, - 'resizable=yes,height=900,width=900,scrollbars=yes,menubar=false'); + var reportWindow = window.open ( + 'js/hedera/report.html', '_blank', + 'height=950, width=950, resizable=yes, fullscreen=no,'+ + 'titlebar=no, menubar=no, toolbar=no, location=no, scrollbars=yes' + ); if (!reportWindow) { Htk.Toast.showError ( _('Please unlock popups and try again')); - return null; + + if (callback) + callback (null); + + return false; } - reportWindow.addEventListener ('load', callback); + reportWindow.addEventListener ('load', + this._onWindowLoad.bind (this)); this.window = reportWindow; - return reportWindow; + return true; + } + + ,_onWindowLoad: function () + { + this.doc = this.window.document + + this.includeCss ('reports/'+ this.info.path +'/style.css'); + + var printButton = this.doc.createElement ('button'); + printButton.className = 'print-button'; + printButton.appendChild (this.doc.createTextNode (_('Print'))); + printButton.addEventListener ('click', this.print.bind (this)); + this.doc.body.appendChild (printButton); + + this.onWindowCreate (); + } + + ,onWindowCreate: function () + { + var builder = new Vn.Builder (); + builder.signalData = this; + builder.add ('batch', this.batch); + builder.add ('conn', this.conn); + builder.loadXml ('reports/'+ this.info.path +'/ui.xml'); + + var res = this.builderResult = builder.load (); + res.link (); + + this.doc.body.appendChild (res.$('report')); } }); diff --git a/web/js/htk/field.js b/web/js/htk/field.js index 498da991..3332de35 100755 --- a/web/js/htk/field.js +++ b/web/js/htk/field.js @@ -56,7 +56,7 @@ Htk.Field = new Class }, form: { - type: Vn.Object // Db.Iterator + type: Db.Iterator ,set: function (x) { this._form = x; diff --git a/web/js/htk/field/search-entry.js b/web/js/htk/field/search-entry.js new file mode 100755 index 00000000..d4e8fa51 --- /dev/null +++ b/web/js/htk/field/search-entry.js @@ -0,0 +1,52 @@ + +Htk.SearchEntry = new Class +({ + Extends: Htk.Field + ,Tag: 'htk-search-entry' + + ,initialize: function (props) + { + var div = this.createElement ('div'); + div.className = 'htk-search-entry'; + + var img = document.createElement ('img'); + img.alt = _('Search'); + img.src = 'image/search.svg'; + div.appendChild (img); + + var input = document.createElement ('input'); + input.className = 'entry'; + input.type = 'text'; + input.placeholder = _('Search'); + input.addEventListener ('change', this._onChange.bind (this)); + div.appendChild (input); + + this._input = input; + this.parent (props); + } + + ,_onChange: function (event) + { + var newValue; + + if (this._input.value === '') + newValue = undefined; + else + newValue = this._input.value; + + this.valueChanged (newValue); + } + + ,putValue: function (value) + { + if (!value) + this._input.value = ''; + else + this._input.value = value; + } + + ,setEditable: function (editable) + { + this.node.readOnly = !editable; + } +}); diff --git a/web/js/htk/field/select.js b/web/js/htk/field/select.js index 5a4944af..5658e48e 100755 --- a/web/js/htk/field/select.js +++ b/web/js/htk/field/select.js @@ -13,8 +13,8 @@ Htk.Select = new Class type: Db.Model ,set: function (x) { - this.link ({_model: x}, {'status-changed': this.onModelChange}); - this.onModelChange (); + this.link ({_model: x}, {'status-changed': this._onModelChange}); + this._onModelChange (); } ,get: function () { @@ -64,7 +64,7 @@ Htk.Select = new Class type: Boolean ,get: function () { - return this._ready; + return this._model && this._model.ready; } }, /** @@ -196,7 +196,7 @@ Htk.Select = new Class this._placeholderNode = option; } - ,onModelChange: function () + ,_onModelChange: function () { var placeholder = null; var model = this._model; diff --git a/web/js/htk/grid.js b/web/js/htk/grid.js index 36a3d81a..bc3f566e 100755 --- a/web/js/htk/grid.js +++ b/web/js/htk/grid.js @@ -6,6 +6,9 @@ Htk.Grid = new Class ,Child: 'model' ,Properties: { + /** + * The source data model. + **/ model: { type: Db.Model @@ -31,11 +34,17 @@ Htk.Grid = new Class return this._model; } }, + /** + * Message that should be displayed when source model is not ready. + **/ emptyMessage: { type: String ,value: _('NoData') }, + /** + * Wether to display the header with column titles. + **/ showHeader: { type: Boolean @@ -200,7 +209,7 @@ Htk.Grid = new Class break; } case Db.Model.Status.LOADING: - this.showMessage (_('Loading'), 'loader-black.gif'); + this.showMessage (_('Loading'), null); break; case Db.Model.Status.CLEAN: this.showMessage (this.emptyMessage, 'refresh.svg'); @@ -232,10 +241,19 @@ Htk.Grid = new Class td.colSpan = this.columns.length; tr.appendChild (td); - var img = document.createElement ('img'); - img.alt = ''; - img.src = 'image/'+ src; - td.appendChild (img); + if (src) + { + var img = document.createElement ('img'); + img.alt = ''; + img.src = 'image/'+ src; + td.appendChild (img); + } + else + { + var spinner = new Htk.Spinner (); + spinner.start (); + td.appendChild (spinner.getNode ()); + } var message = document.createTextNode (message); td.appendChild (message); diff --git a/web/js/htk/loader.css b/web/js/htk/loader.css deleted file mode 100644 index d1fbb82e..00000000 --- a/web/js/htk/loader.css +++ /dev/null @@ -1,74 +0,0 @@ - -.htk-loader -{ - font-size: 10px; - margin: 50px auto; - text-indent: -9999em; - width: 11em; - height: 11em; - border-radius: 50%; - background: #ffffff; - background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%); - background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%); - background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%); - background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%); - background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%); - position: relative; - -webkit-animation: load3 1.4s infinite linear; - animation: load3 1.4s infinite linear; - -webkit-transform: translateZ(0); - -ms-transform: translateZ(0); - transform: translateZ(0); -} -.htk-loader:before -{ - width: 50%; - height: 50%; - background: #ffffff; - border-radius: 100% 0 0 0; - position: absolute; - top: 0; - left: 0; - content: ''; -} -.htk-loader:after -{ - background: #0dc5c1; - width: 75%; - height: 75%; - border-radius: 50%; - content: ''; - margin: auto; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; -} -@-webkit-keyframes load3 -{ - 0% - { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% - { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} -@keyframes load3 -{ - 0% - { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% - { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - diff --git a/web/js/htk/loader.js b/web/js/htk/loader.js deleted file mode 100755 index f2c26e9d..00000000 --- a/web/js/htk/loader.js +++ /dev/null @@ -1,13 +0,0 @@ -Htk.Loader = new Class -({ - Extends: Htk.Widget - ,Tag: 'htk-loader' - - ,initialize: function (props) - { - var loader = this.createElement ('div'); - loader.className = 'htk-loader'; - - this.parent (props); - } -}); diff --git a/web/js/htk/main.js b/web/js/htk/main.js index 64ea8fca..37f8eb6c 100755 --- a/web/js/htk/main.js +++ b/web/js/htk/main.js @@ -9,7 +9,7 @@ Vn.includeLib ('htk', ,'toast' ,'repeater' ,'grid' - ,'loader' + ,'spinner' ,'full-image' ,'image-editor' ,'assistant' @@ -30,6 +30,7 @@ Vn.includeLib ('htk', ,'field/image' ,'field/button' ,'field/table' + ,'field/search-entry' ,'column' ,'column/button' ,'column/link' diff --git a/web/js/htk/repeater.js b/web/js/htk/repeater.js index 91f312e0..bc78e34c 100755 --- a/web/js/htk/repeater.js +++ b/web/js/htk/repeater.js @@ -5,6 +5,9 @@ Htk.Repeater = new Class ,Child: 'model' ,Properties: { + /** + * The source data model. + **/ model: { type: Db.Model @@ -25,6 +28,9 @@ Htk.Repeater = new Class this._model; } } + /** + * The identifier for internal iterator. + **/ ,formId: { type: String @@ -37,6 +43,10 @@ Htk.Repeater = new Class this._formId; } } + /** + * {Function (Vn.BuilderResult, Db.Form)} Function to call after every + * box rendering. + **/ ,renderer: { type: Function @@ -49,6 +59,9 @@ Htk.Repeater = new Class this._renderer; } } + /** + * Message that should be displayed when source model is not ready. + **/ ,emptyMessage: { type: String @@ -140,7 +153,7 @@ Htk.Repeater = new Class break; } case Db.Model.Status.LOADING: - this._showMessage (_('Loading'), 'loader-black.gif'); + this._showMessage (_('Loading'), null); break; case Db.Model.Status.CLEAN: this._showMessage (this.emptyMessage, 'refresh.svg'); @@ -149,7 +162,7 @@ Htk.Repeater = new Class this._showMessage (_('ErrorLoadingData'), 'error.svg'); break; } - + this.node.appendChild (this._container); this.signalEmit ('change'); } @@ -166,10 +179,19 @@ Htk.Repeater = new Class div.className = 'message'; this._container.appendChild (div); - var img = document.createElement ('img'); - img.alt = ''; - img.src = 'image/'+ src; - div.appendChild (img); + if (src) + { + var img = document.createElement ('img'); + img.alt = ''; + img.src = 'image/'+ src; + div.appendChild (img); + } + else + { + var spinner = new Htk.Spinner (); + spinner.start (); + div.appendChild (spinner.getNode ()); + } div.appendChild (document.createTextNode (message)); } diff --git a/web/js/htk/spinner.js b/web/js/htk/spinner.js new file mode 100755 index 00000000..2ebc5d5f --- /dev/null +++ b/web/js/htk/spinner.js @@ -0,0 +1,27 @@ +Htk.Spinner = new Class +({ + Extends: Htk.Widget + ,Tag: 'htk-spinner' + + ,initialize: function (props) + { + var loader = this.createElement ('div'); + loader.className = 'htk-spinner'; + + var spin = document.createElement ('div'); + loader.appendChild (spin); + + this.spin = spin; + this.parent (props); + } + + ,start: function () + { + Vn.Node.addClass (this.spin, 'spinner'); + } + + ,stop: function () + { + Vn.Node.removeClass (this.spin, 'spinner'); + } +}); diff --git a/web/js/htk/style.css b/web/js/htk/style.css index 255f9ec7..00a10fa6 100755 --- a/web/js/htk/style.css +++ b/web/js/htk/style.css @@ -41,12 +41,14 @@ } .htk-grid .message { - height: 5em; + padding: 1.5em; } -.htk-grid .message img +.htk-grid .message > img, +.htk-grid .message > .htk-spinner { + display: inline-block; vertical-align: middle; - padding: 0.8em; + padding-right: 0.8em; height: 1.8em; } .htk-grid > tbody tr @@ -121,17 +123,18 @@ .htk-repeater > .message { - padding: 1em; + padding: 1.5em; text-align: center; } .htk-repeater > .message > * { vertical-align: middle; } -.htk-repeater > .message > img +.htk-repeater > .message > img, +.htk-repeater > .message > .htk-spinner { - padding: 0.8em; - padding-left: 0; + display: inline-block; + padding-right: .8em; height: 1.8em; } @@ -438,3 +441,74 @@ opacity: .7; } +/* Search entry */ + +.htk-search-entry +{ + background-color: white; + height: 2.2em; +} +.htk-search-entry > img +{ + margin: 0; + height: 1.5em; + margin-left: .4em; + vertical-align: middle; +} +.htk-search-entry > .entry +{ + margin: 0; + border: none; + width: 8em; + box-shadow: none; +} +.htk-search-entry > .entry:focus +{ + background-color: initial; +} + +/* Loader */ + +.htk-spinner +{ + position: relative; + display: inline-block; + box-sizing: border-box; +} +.htk-spinner > .spinner +{ + width: 1.8em; + height: 1.8em; +} +.htk-spinner > .spinner:before +{ + content: 'Loading…'; + position: absolute; + left: 0; + width: 1.2em; + height: 1.2em; +} +.htk-spinner > .spinner:not(:required):before +{ + content: ''; + border-radius: 50%; + border: .3em solid transparent; + border-top-color: #666; + border-left-color: #666; + animation: spinner 1s linear infinite; + -webkit-animation: spinner 1s linear infinite; +} +.htk-spinner.dark > .spinner:not(:required):before +{ + border-top-color: white; + border-left-color: white; +} +@keyframes spinner +{ + to {transform: rotate(360deg);} +} +@-webkit-keyframes spinner +{ + to {-webkit-transform: rotate(360deg);} +} + diff --git a/web/js/sql/batch.js b/web/js/sql/batch.js index 31225ec7..d3dcf170 100755 --- a/web/js/sql/batch.js +++ b/web/js/sql/batch.js @@ -91,6 +91,16 @@ Sql.Batch = new Class new Sql.Value ({param: param})); } + ,getValue: function (id) + { + var object = this.objects[id]; + + if (object instanceof Sql.Value) + return object.value; + + return null; + } + ,addParams: function (params) { for (var id in params) diff --git a/web/js/sql/filter-item.js b/web/js/sql/filter-item.js index 6867de68..c7dba4e0 100755 --- a/web/js/sql/filter-item.js +++ b/web/js/sql/filter-item.js @@ -18,9 +18,15 @@ Sql.FilterItem = new Class { return this._disabled; } + }, + primary: + { + type: Boolean } } + ,primary: true + ,isReady: function () { if (this._disabled) diff --git a/web/js/sql/filter.js b/web/js/sql/filter.js index de12f74d..d308465d 100755 --- a/web/js/sql/filter.js +++ b/web/js/sql/filter.js @@ -20,7 +20,7 @@ Sql.Filter = new Class var e = this.exprs.getArray (); for (var i = 0; i < e.length; i++) - if (e[i].isReady ()) + if (e[i].isReady () && e[i].primary) return true; return false; diff --git a/web/js/vn/builder.js b/web/js/vn/builder.js index ab0f8f9f..fa44974e 100755 --- a/web/js/vn/builder.js +++ b/web/js/vn/builder.js @@ -275,7 +275,6 @@ Vn.Builder = new Class var objectProps = {}; var childs = []; var events = {}; - var handler; var context = { klass: klass, @@ -293,9 +292,12 @@ Vn.Builder = new Class var attribute = a[i].nodeName; var value = a[i].nodeValue; - if (handler = this._getEventHandler (attribute, value)) + if (this._isEvent (attribute)) { - events[attribute.substr (3)] = handler; + var handler = this._getMethod (value) + + if (handler) + events[attribute.substr (3)] = handler; } else if (!/^(id|property)$/.test (attribute)) { @@ -432,8 +434,13 @@ Vn.Builder = new Class var attribute = a[i].nodeName; var value = a[i].nodeValue; - if (handler = this._getEventHandler (attribute, value)) - events[attribute.substr (3)] = handler; + if (this._isEvent (attribute)) + { + var handler = this._getMethod (value); + + if (handler) + events[attribute.substr (3)] = handler; + } else if (attribute !== 'id') attributes[attribute] = this._translateValue (value); } @@ -528,21 +535,18 @@ Vn.Builder = new Class } catch (e) { - method = null; + method = undefined; } - if (method === null) + if (method === undefined) this._showError ('Function \'%s\' not found', value); return method; } - ,_getEventHandler: function (attribute, value) - { - if (!(/^on-\w+/.test (attribute))) - return null; - - return this._getMethod (value); + ,_isEvent: function (attribute) + { + return /^on-\w+/.test (attribute); } ,_replaceFunc: function (token) diff --git a/web/js/vn/locale.js b/web/js/vn/locale.js index 19ffb550..ce298c3a 100755 --- a/web/js/vn/locale.js +++ b/web/js/vn/locale.js @@ -12,7 +12,7 @@ Vn.Locale = if (!this.language) { var language = navigator.language.substr (0, 2); - this.language = language ? language : 'es'; + this.language = language ? language : 'en'; } } diff --git a/web/locale/ca/forms/ecomerce/catalog.json b/web/locale/ca/forms/ecomerce/catalog.json index d976227e..9eaf8238 100755 --- a/web/locale/ca/forms/ecomerce/catalog.json +++ b/web/locale/ca/forms/ecomerce/catalog.json @@ -3,7 +3,7 @@ ,"SearchResults": "Resultats de cerca" ,"SelectFamily": "Selecciona una família" - ,"SelectSubtype": "Selecciona un subtipus en el menú de la dreta" + ,"Select filter from right menu": "Selecciona un filtre en el menú de la dreta" ,"ArticleNotFound": "Artcle no trobat" ,"ArticleNotAvailable": "Article no disponible" diff --git a/web/locale/ca/forms/ecomerce/ticket.json b/web/locale/ca/forms/ecomerce/ticket.json index 20681739..38507c12 100755 --- a/web/locale/ca/forms/ecomerce/ticket.json +++ b/web/locale/ca/forms/ecomerce/ticket.json @@ -1,7 +1,7 @@ { "OrderDetail": "Detall de l'encarrec" - ,"Print": "Imprimir albarà" + ,"Print delivery note": "Imprimir albarà" ,"TicketNumber:": "N ticket:" ,"DateExit:": "Data d'enviament:" diff --git a/web/locale/ca/js/htk.js b/web/locale/ca/js/htk.js index ac9f9338..5103c94b 100755 --- a/web/locale/ca/js/htk.js +++ b/web/locale/ca/js/htk.js @@ -26,4 +26,6 @@ Vn.Locale.add ,"Close": "Tancar" ,"Previous": "Anterior" ,"Next": "Següent" + ,"Search": "Cercar" + ,"Search...": "Cercar..." }); diff --git a/web/locale/en/forms/ecomerce/catalog.json b/web/locale/en/forms/ecomerce/catalog.json index 5b624961..d83185ae 100755 --- a/web/locale/en/forms/ecomerce/catalog.json +++ b/web/locale/en/forms/ecomerce/catalog.json @@ -3,7 +3,7 @@ ,"SearchResults": "Search results" ,"SelectFamily": "Select family" - ,"SelectSubtype": "Select a filter from the right menu" + ,"Select filter from right menu": "Select a filter from the right menu" ,"ArticleNotFound": "Item not found" ,"ArticleNotAvailable": "Item not available" diff --git a/web/locale/en/forms/ecomerce/confirm.json b/web/locale/en/forms/ecomerce/confirm.json index 04a7f490..29034f59 100755 --- a/web/locale/en/forms/ecomerce/confirm.json +++ b/web/locale/en/forms/ecomerce/confirm.json @@ -18,7 +18,7 @@ ,"Modify": "Modify" ,"Confirm": "Confirm" - ,"OrderPlacedSuccessfully": "Your order has been successfully completed" + ,"OrderPlacedSuccessfully": "Your order has been confirmed successfully" ,"OrderReserved": "We've booked your order but it seems that there have been problems with payment. Contact your sales." ,"Accept": "Accept" ,"PayNow": "Pay now" diff --git a/web/locale/en/forms/ecomerce/ticket.json b/web/locale/en/forms/ecomerce/ticket.json index 11ed2c30..a0937941 100755 --- a/web/locale/en/forms/ecomerce/ticket.json +++ b/web/locale/en/forms/ecomerce/ticket.json @@ -1,7 +1,7 @@ { "OrderDetail": "Order detail" - ,"Print": "Print delivery note" + ,"Print delivery note": "Print delivery note" ,"TicketNumber:": "Ticket number:" ,"DateExit:": "Delivery date:" diff --git a/web/locale/en/js/hedera.js b/web/locale/en/js/hedera.js index 23afb66c..8473f770 100755 --- a/web/locale/en/js/hedera.js +++ b/web/locale/en/js/hedera.js @@ -9,8 +9,8 @@ Vn.Locale.add ,"Login mail": "clientes@verdnatura.es" ,"Login phone": "+34 607 562 391" - ,"You've been too idle": "You've been too idle and session time has expired." - ,"Invalid login": "Username or password incorrect. Remember that case-sensitive." + ,"You've been too idle": "You have been idle too long and your session has expired." + ,"Invalid login": "Username or password incorrect. Remember that it is case-sensitive." ,"There was an internal error": "There was an internal error" ,"Menu": "Menu" diff --git a/web/locale/en/js/htk.js b/web/locale/en/js/htk.js index a40e636b..d468f283 100755 --- a/web/locale/en/js/htk.js +++ b/web/locale/en/js/htk.js @@ -26,4 +26,6 @@ Vn.Locale.add ,"Close": "Close" ,"Previous": "Previous" ,"Next": "Next" + ,"Search": "Search" + ,"Search...": "Search..." }); diff --git a/web/locale/es/forms/ecomerce/catalog.json b/web/locale/es/forms/ecomerce/catalog.json index 73dc56fb..8180d5fa 100755 --- a/web/locale/es/forms/ecomerce/catalog.json +++ b/web/locale/es/forms/ecomerce/catalog.json @@ -3,7 +3,7 @@ ,"SearchResults": "Resultados de búsqueda" ,"SelectFamily": "Selecciona una familia" - ,"SelectSubtype": "Selecciona un subtipo en el menú de la derecha" + ,"Select filter from right menu": "Selecciona un filtro en el menú de la derecha" ,"ArticleNotFound": "Artículo no encontrado" ,"ArticleNotAvailable": "Artículo no disponible" diff --git a/web/locale/es/forms/ecomerce/ticket.json b/web/locale/es/forms/ecomerce/ticket.json index f57b72fc..555129e8 100755 --- a/web/locale/es/forms/ecomerce/ticket.json +++ b/web/locale/es/forms/ecomerce/ticket.json @@ -1,7 +1,7 @@ { "OrderDetail": "Detalle del pedido" - ,"Print": "Imprimir albarán" + ,"Print delivery note": "Imprimir albarán" ,"TicketNumber:": "Nº ticket:" ,"DateExit:": "Fecha de envío:" diff --git a/web/locale/es/js/htk.js b/web/locale/es/js/htk.js index fad8c3a5..83d56af6 100755 --- a/web/locale/es/js/htk.js +++ b/web/locale/es/js/htk.js @@ -26,4 +26,6 @@ Vn.Locale.add ,"Close": "Cerrar" ,"Previous": "Anterior" ,"Next": "Siguiente" + ,"Search": "Buscar" + ,"Search...": "Buscar..." }); diff --git a/web/locale/fr/forms/ecomerce/catalog.json b/web/locale/fr/forms/ecomerce/catalog.json index 95e7adc9..86712ffb 100755 --- a/web/locale/fr/forms/ecomerce/catalog.json +++ b/web/locale/fr/forms/ecomerce/catalog.json @@ -3,7 +3,7 @@ ,"SearchResults": "Résultats de la recherche" ,"SelectFamily": "Choisissez une famille" - ,"SelectSubtype": "Sélectionnez le sous-menu sur la droite" + ,"Select filter from right menu": "Sélectionnez un filtre dans le menu de droite" ,"ArticleNotFound": "Article non trouvé" ,"ArticleNotAvailable": "Article non disponible" diff --git a/web/locale/fr/forms/ecomerce/ticket.json b/web/locale/fr/forms/ecomerce/ticket.json index 94114d44..e0692039 100755 --- a/web/locale/fr/forms/ecomerce/ticket.json +++ b/web/locale/fr/forms/ecomerce/ticket.json @@ -1,7 +1,7 @@ { "OrderDetail": "Détails de la commande" - ,"Print": "Imprimer bulletin de livraison" + ,"Print delivery note": "Imprimer bulletin de livraison" ,"TicketNumber:": "Num ticket:" ,"DateExit:": "Date d'envoi:" diff --git a/web/locale/fr/js/htk.js b/web/locale/fr/js/htk.js index 88d614b6..9b871c88 100755 --- a/web/locale/fr/js/htk.js +++ b/web/locale/fr/js/htk.js @@ -26,4 +26,6 @@ Vn.Locale.add ,"Close": "Croche" ,"Previous": "Précédent" ,"Next": "Suivant" + ,"Search": "Recherche" + ,"Search...": "Recherche..." }); diff --git a/web/locale/mn/forms/ecomerce/catalog.json b/web/locale/mn/forms/ecomerce/catalog.json index 5b624961..1b372742 100755 --- a/web/locale/mn/forms/ecomerce/catalog.json +++ b/web/locale/mn/forms/ecomerce/catalog.json @@ -3,7 +3,7 @@ ,"SearchResults": "Search results" ,"SelectFamily": "Select family" - ,"SelectSubtype": "Select a filter from the right menu" + ,"Select filter from right menu": "Зөв цэс нь шүүлтүүр сонгоно уу" ,"ArticleNotFound": "Item not found" ,"ArticleNotAvailable": "Item not available" diff --git a/web/locale/mn/forms/ecomerce/ticket.json b/web/locale/mn/forms/ecomerce/ticket.json index 11ed2c30..a0937941 100755 --- a/web/locale/mn/forms/ecomerce/ticket.json +++ b/web/locale/mn/forms/ecomerce/ticket.json @@ -1,7 +1,7 @@ { "OrderDetail": "Order detail" - ,"Print": "Print delivery note" + ,"Print delivery note": "Print delivery note" ,"TicketNumber:": "Ticket number:" ,"DateExit:": "Delivery date:" diff --git a/web/locale/mn/js/htk.js b/web/locale/mn/js/htk.js index a40e636b..a3a262fd 100755 --- a/web/locale/mn/js/htk.js +++ b/web/locale/mn/js/htk.js @@ -26,4 +26,6 @@ Vn.Locale.add ,"Close": "Close" ,"Previous": "Previous" ,"Next": "Next" + ,"Search": "хайх" + ,"Search...": "хайх..." }); diff --git a/web/reports/delivery-note/delivery-note.js b/web/reports/delivery-note/delivery-note.js new file mode 100755 index 00000000..ac2279a0 --- /dev/null +++ b/web/reports/delivery-note/delivery-note.js @@ -0,0 +1,21 @@ + +Vn.DeliveryNote = new Class +({ + Extends: Vn.Report + + ,subtotalRenderer: function (column, form) + { + column.value = this.subtotal (form); + } + + ,subtotal: function (form) + { + var price = form.get ('price'); + var discount = form.get ('discount'); + + if (price && form.get ('fixed')) + return form.get ('amount') * price * ((100 - discount) / 100); + else + return null; + } +}); diff --git a/web/reports/delivery-note/style.css b/web/reports/delivery-note/style.css new file mode 100644 index 00000000..08419bfb --- /dev/null +++ b/web/reports/delivery-note/style.css @@ -0,0 +1,45 @@ +* +{ + font-size: 4mm; +} +.sheet +{ + height: auto; +} +h1 +{ + font-weight: normal; + font-size: 200%; + text-align: center; + margin: 0 auto; + margin-bottom: 8mm; +} +.htk-grid +{ + border-collapse: collapse; + width: 100%; + margin: 0 auto; + padding: 0; +} +thead > tr +{ + border-bottom: 1px solid #333; + height: 10mm; +} +th +{ + font-weight: normal; +} +td +{ + padding-left: 2mm; +} +tbody > tr +{ + height: 18mm; +} +.cell-image > img +{ + width: 15mm; +} + diff --git a/web/reports/delivery-note/ui.xml b/web/reports/delivery-note/ui.xml new file mode 100755 index 00000000..bde2c553 --- /dev/null +++ b/web/reports/delivery-note/ui.xml @@ -0,0 +1,97 @@ + + + + + + SELECT t.id, date, a.Agencia, note, p.name province, + zip_code, city, c.name, consignee, invoice + FROM ticket_view t + JOIN address_view c ON t.address_id = c.id + JOIN vn2008.Agencias a ON t.agency_id = a.Id_Agencia + JOIN vn2008.province p ON c.province_id = p.province_id + WHERE t.id = #ticket + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + + + +
+ + + + + + + + + + + SELECT m.item_id, amount, concept, Categoria, Medida, Tallos, Color, + Abreviatura, IF(fixed != FALSE, price, NULL) price, fixed, discount + FROM ticket_row_view m + INNER JOIN vn2008.Articles a + ON m.item_id = a.Id_Article AND ticket_id = #ticket + LEFT JOIN vn2008.Origen o + ON a.id_origen = o.id + ORDER BY concept + + + + + + + + + + + + + + +
+
diff --git a/web/reports/shelves-report/shelves-report.js b/web/reports/shelves-report/shelves-report.js index 5344cde6..8ca24635 100755 --- a/web/reports/shelves-report/shelves-report.js +++ b/web/reports/shelves-report/shelves-report.js @@ -2,4 +2,364 @@ Vn.ShelvesReport = new Class ({ Extends: Vn.Report + + ,nItem: -1 + ,nColors: 5 + + ,open: function (batch) + { + this.batch = batch; + this.title = batch.getValue ('title'); + this.maxAmount = batch.getValue ('max-amount'); + this.showPacking = batch.getValue ('show-packing'); + this.stack = batch.getValue ('stack'); + + var query = + 'SELECT id, name, width, height, depth, max_height, tray_height, '+ + 'first_tray_elevation, tray_density, vspacing, hspacing '+ + 'FROM shelf WHERE id = #shelf; '+ + 'CALL item_organizer (#wh, #date, #family, #filter)'; + + this.conn.execQuery (query, this.onQueryExec.bind (this), this.batch); + } + + ,onQueryExec: function (resultSet) + { + // Fetch query data + + var res = resultSet.fetchResult (); + res.next (); + + var maxWidth = 170; + var maxHeight = 200; + + var scale = maxWidth / res.get ('width'); + + if (res.get ('max_height') * scale > maxHeight) + scale = maxHeight / res.get ('max_height'); + + var shelf = this.shelf = + { + width: res.get ('width') * scale + ,height: res.get ('height') * scale + ,depth: res.get ('depth') * scale + ,maxHeight: res.get ('max_height') * scale + ,trayHeight: res.get ('tray_height') * scale + ,firstTrayElevation: res.get ('first_tray_elevation') * scale + ,trayDensity: res.get ('tray_density') * scale + ,vspacing: res.get ('vspacing') * scale + ,hspacing: res.get ('hspacing') * scale + }; + + var items = this.items = []; + var remainings = this.remainings = []; + var res = resultSet.fetchResult (); + + if (res.data.length == 0) + { + Htk.Toast.showError (_('No items found, check that all fields are correct')); + return; + } + + var boxScale = scale * 10; + + while (res.next ()) + if (!this.maxAmount || res.get ('etiquetas') <= this.maxAmount) + { + items.push ({ + id: res.get ('Id_Article') + ,name: res.get ('Article') + ,packing: res.get ('packing') + ,amount: res.get ('etiquetas') + ,boxHeight: res.get ('z') * boxScale + ,boxWidth: res.get ('x') * boxScale + ,boxDepth: res.get ('y') * boxScale + }); + } + else + { + remainings.push ({ + id: res.get ('Id_Article') + ,name: res.get ('Article') + ,packing: res.get ('packing') + ,amount: res.get ('etiquetas') + }); + } + + // Intializes the allocator + + alloc = this.alloc = new Vn.Allocator (); + alloc.items = items; + alloc.shelfFunc = this.drawShelf.bind (this); + alloc.boxFunc = this.drawBox.bind (this); + alloc.stack = this.stack; + alloc.nTrays = Math.ceil ( + (shelf.height - shelf.firstTrayElevation) / + (shelf.trayHeight + shelf.trayDensity) + ); + alloc.width = shelf.width - shelf.hspacing * 2; + alloc.depth = shelf.depth; + alloc.trayHeight = shelf.trayHeight - shelf.vspacing; + alloc.topTrayHeight = shelf.maxHeight - shelf.vspacing + - shelf.firstTrayElevation - (alloc.nTrays - 1) * shelf.trayHeight; + + // Opens the report + + this.createWindow (); + } + + ,onWindowCreate: function () + { + // Remaining amount + + var remainings = this.remainings; + + if (remainings.length > 0) + { + var sheet = this.doc.createElement ('div'); + sheet.className = 'sheet'; + this.doc.body.appendChild (sheet); + + var title = this.doc.createElement ('h1'); + title.className = 'title'; + title.appendChild (this.doc.createTextNode (this.title)); + sheet.appendChild (title); + + var subtitle = this.doc.createElement ('h2'); + subtitle.className = 'subtitle'; + subtitle.appendChild (this.doc.createTextNode (_('Pallets'))); + sheet.appendChild (subtitle); + + var ul = this.doc.createElement ('ul'); + sheet.appendChild (ul); + + for (var i = 0; i < remainings.length; i++) + { + var li = this.doc.createElement ('li'); + ul.appendChild (li); + + var span = this.doc.createElement ('span'); + span.className = 'item-id'; + span.appendChild (this.doc.createTextNode (remainings[i].id.toLocaleString ())); + li.appendChild (span); + + var span = this.doc.createElement ('span'); + span.className = 'item'; + span.appendChild (this.doc.createTextNode (remainings[i].name)); + li.appendChild (span); + + if (this.showPacking) + span.appendChild (this.doc.createTextNode (' '+ remainings[i].packing)); + + var span = this.doc.createElement ('span'); + span.className = 'amount'; + span.appendChild (this.doc.createTextNode (remainings[i].amount)); + li.appendChild (span); + } + } + + // Draws the shelves + + this.alloc.run (); + this.drawShelfEnding (); + } + + ,drawShelf: function (allocator, item) + { + var shelf = this.shelf; + + var sheet = this.doc.createElement ('div'); + sheet.className = 'sheet'; + this.doc.body.appendChild (sheet); + + // Draws the title + + var pageNumber = this.doc.createElement ('h1'); + pageNumber.className = 'page-number'; + pageNumber.appendChild (this.doc.createTextNode (allocator.currentShelf + 1)); + sheet.appendChild (pageNumber); + + var title = this.doc.createElement ('h1'); + title.className = 'title'; + title.appendChild (this.doc.createTextNode (this.title)); + sheet.appendChild (title); + + var subtitle = this.doc.createElement ('h2'); + subtitle.className = 'subtitle'; + subtitle.appendChild (this.doc.createTextNode (item.id.toLocaleString ())); + sheet.appendChild (subtitle); + + this.drawShelfEnding (); + this.lastSubtitle = subtitle; + + // Draws the shelf + + var shelfDiv = this.shelfDiv = this.doc.createElement ('div'); + shelfDiv.className = 'shelf'; + shelfDiv.style.width = this.mm (shelf.width); + shelfDiv.style.height = this.mm (shelf.maxHeight); + sheet.appendChild (shelfDiv); + + // Draws trays + + var lastTrayY = shelf.firstTrayElevation; + + if (shelf.trayHeight > 0) + while (lastTrayY + shelf.trayDensity < shelf.height) + { + var tray = this.doc.createElement ('div'); + tray.className = 'tray'; + tray.style.width = this.mm (shelf.width); + tray.style.height = this.mm (shelf.trayDensity); + tray.style.bottom = this.mm (lastTrayY); + shelfDiv.appendChild (tray); + + lastTrayY += shelf.trayHeight + shelf.trayDensity; + } + } + + ,drawShelfEnding: function () + { + if (this.lastSubtitle) + this.lastSubtitle.appendChild ( + this.doc.createTextNode (' - '+ this.lastItem.id.toLocaleString ())); + } + + ,mm: function (size) + { + return size.toFixed (2) +'mm'; + } + + ,drawBox: function (allocator, item, amount) + { + if (item.boxWidth == 0 || item.boxHeight == 0) + return; + + var shelf = this.shelf; + + var x = allocator.trayX + shelf.hspacing; + var y = allocator.trayY + + shelf.firstTrayElevation + shelf.trayDensity + + allocator.currentTray * (shelf.trayHeight + shelf.trayDensity); + + var box = this.doc.createElement ('div'); + box.className = 'box'; + this.shelfDiv.appendChild (box); + + box.style.left = this.mm (x); + box.style.bottom = this.mm (y); + box.style.width = this.mm (item.boxWidth); + box.style.height = this.mm (item.boxHeight); + + if (amount == 0) + this.nItem++; + + var nColor = this.nItem % this.nColors; + Vn.Node.addClass (box, 'color'+ nColor); + + if (amount == 0 || allocator.firstShelfBox) + { + var fontSize = item.boxWidth / 5.2; + + if (fontSize > item.boxHeight - 1) + fontSize = item.boxHeight - 1; + + var boxLabel = this.doc.createElement ('div'); + boxLabel.className = 'box-label'; + boxLabel.style.fontSize = this.mm (fontSize); + boxLabel.appendChild (this.doc.createTextNode (item.id.toLocaleString ())); + box.appendChild (boxLabel); + } + + this.lastItem = item; + } +}); + +Vn.Allocator = new Class +({ + addShelf: function (item) + { + this.currentShelf++; + this.firstShelfBox = true; + + if (this.shelfFunc) + this.shelfFunc (this, item); + } + + ,addTray: function (item) + { + if (this.currentTray <= 0) + { + this.addShelf (item); + this.currentTray = this.nTrays - 1; + } + else + this.currentTray--; + + this.trayX = 0; + } + + ,addColumn: function (item) + { + if (this.trayX + this.columnWidth + item.boxWidth > this.width + || this.currentTray == -1) + this.addTray (item); + else + this.trayX += this.columnWidth; + + this.trayY = 0; + this.columnWidth = item.boxWidth; + this.lastBoxWidth = item.boxWidth; + } + + ,addBox: function (item, amount) + { + var trayHeight = this.trayHeight; + + if (this.currentTray == this.nTrays - 1) + trayHeight = this.topTrayHeight; + + if (this.trayY + item.boxHeight > trayHeight + || item.boxWidth > this.lastBoxWidth + || (!this.stack && amount == 0)) + this.addColumn (item); + + if (this.boxFunc) + this.boxFunc (this, item, amount); + + this.trayY += item.boxHeight; + + if (item.boxWidth < this.lastBoxWidth) + this.lastBoxWidth = item.boxWidth; + } + + ,run: function () + { + this.firstShelfBox = false; + this.currentShelf = -1; + this.currentTray = -1; + this.columnWidth = 0; + this.lastBoxWidth = 0; + this.trayX = 0; + this.trayY = 0; + this.remaining = false; + + for (var i = 0; i < this.items.length; i++) + { + var item = this.items[i]; + var boxIncrement = Math.floor (this.depth / item.boxDepth); + + if (boxIncrement < 1) + boxIncrement = 1; + + for (var amount = 0; amount < item.amount; amount += boxIncrement) + { + this.addBox (item, amount); + this.firstShelfBox = false; + } + } + + return this.currentShelf + 1; + } + });