Hedera.ShelvesReport = new Class({ Extends: Hedera.Report ,nItem: -1 ,nColors: 5 ,trayThickness: 2 ,trayMargin: 5 ,async open(lot) { this.lot = lot; const query = 'SELECT id, name, nTrays, topTrayHeight, trayHeight, width, depth '+ 'FROM shelf WHERE id = #shelf; '+ 'CALL item_listAllocation(#warehouse, #date, #family, #namePrefix, #useIds)'; const resultSet = await this.conn.execQuery(query, lot.$); // Fetch query data const row = resultSet.fetchObject(); // Calculates the scale var maxWidth = 160; var maxHeight = 160; var shelfWidth = row.width; var shelfHeight = row.trayHeight * (row.nTrays - 1) + row.topTrayHeight; var scale = maxWidth / shelfWidth; if (shelfHeight * scale > maxHeight) scale = maxHeight / shelfHeight; // Calculates the shelf dimensions var shelf = this.shelf = { nTrays: row.nTrays ,trayHeight: row.trayHeight * scale ,topTrayHeight: row.topTrayHeight * scale ,width: row.width * scale ,depth: row.depth * scale }; // Gets the items var items = this.items = []; var remainings = this.remainings = []; var res = resultSet.fetchData(); if (res.length == 0) { Htk.Toast.showError(_('No items found, check that all fields are correct')); return; } var boxScale = scale * 10; for (const row of res) { if (!this.maxAmount || row.etiquetas <= this.maxAmount) { items.push({ id: row.Id_Article ,name: row.Article ,packing: row.packing ,amount: row.etiquetas ,boxHeight: row.height * boxScale ,boxWidth: row.width * boxScale ,boxDepth: row.depth * boxScale }); } else { remainings.push({ id: row.Id_Article ,name: row.Article ,packing: row.packing ,amount: row.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 = shelf.nTrays; alloc.width = shelf.width; alloc.depth = shelf.depth; alloc.trayHeight = shelf.trayHeight; alloc.topTrayHeight = shelf.topTrayHeight; // Opens the report this.createWindow(); } ,onWindowCreate() { // 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.drawShelfRange(this.lastItem, false); } ,drawShelf(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); if (this.subtitles) this.drawShelfRange(this.lastItem, false); this.subtitles = this.doc.createElement('div'); sheet.appendChild(this.subtitles); this.drawShelfRange(item, true); this.lastSubtitles = this.subtitles; // Draws the shelf var trayWidth = shelf.width + this.trayMargin * 2; var shelfHeight = shelf.trayHeight * (shelf.nTrays - 1) + shelf.topTrayHeight + (this.trayThickness + this.trayMargin) * shelf.nTrays; var shelfDiv = this.shelfDiv = this.doc.createElement('div'); shelfDiv.className = 'shelf'; shelfDiv.style.width = this.mm(trayWidth); shelfDiv.style.height = this.mm(shelfHeight); sheet.appendChild(shelfDiv); // Draws trays for (var i = 0; i < shelf.nTrays; i++) { var tray = this.doc.createElement('div'); tray.className = 'tray'; tray.style.bottom = this.mm((shelf.trayHeight + this.trayThickness + this.trayMargin) * i); tray.style.width = this.mm(trayWidth); tray.style.height = this.mm(this.trayThickness); shelfDiv.appendChild(tray); } } ,drawShelfRange(item, isFirst) { var labelText = isFirst ? _('Start') : _('End'); var label = this.doc.createElement('label'); label.className = 'range-label'; label.appendChild(this.doc.createTextNode(labelText)); this.subtitles.appendChild(label); var subtitle = this.doc.createElement('h2'); subtitle.className = 'subtitle'; subtitle.appendChild(this.doc.createTextNode(this.getItemLabel(item))); this.subtitles.appendChild(subtitle); } ,getItemLabel(item) { if (!this.useIds) { var packing = this.showPacking ? (' x'+ item.packing) : ''; return item.name + packing; } else return item.id.toLocaleString(); } ,mm(size) { return size.toFixed(2) +'mm'; } ,drawBox(allocator, item, amount) { if (item.boxWidth == 0 || item.boxHeight == 0) return; var shelf = this.shelf; var x = allocator.trayX + this.trayMargin; var y = allocator.trayY + this.trayThickness + this.trayMargin * allocator.currentTray + allocator.currentTray * (shelf.trayHeight + this.trayThickness); 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 boxLabel = this.doc.createElement('div'); if (this.useIds) { var fontSize = item.boxWidth / 5.2; if (fontSize > item.boxHeight - 1) fontSize = item.boxHeight - 1; boxLabel.style.fontSize = this.mm(fontSize); var cssClass = 'id'; } else var cssClass = 'name'; boxLabel.className = 'box-label '+ cssClass; var labelText = this.doc.createTextNode(this.getItemLabel(item)); boxLabel.appendChild(labelText); box.appendChild(boxLabel); } this.lastItem = item; } }); Vn.Allocator = new Class({ addShelf(item) { this.currentShelf++; this.firstShelfBox = true; if (this.shelfFunc) this.shelfFunc(this, item); } ,addTray(item) { if (this.currentTray <= 0) { this.addShelf(item); this.currentTray = this.nTrays - 1; } else this.currentTray--; this.trayX = 0; } ,addColumn(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(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() { 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; } });