| @@ -43,11 +43,12 @@ open class PlasticBagPrinterService( | |||
| val baos = ByteArrayOutputStream() | |||
| ZipOutputStream(baos).use { zos -> | |||
| // Reduced sizes to make files smaller while keeping readability/scanability | |||
| val productBmp = createMonochromeBitmap(productName, 520) // was 704 | |||
| val codeBmp = createMonochromeBitmap(itemCode, 900) // was 1173 | |||
| val expBmp = createMonochromeBitmap(expiryDate, 900) // was 1173 | |||
| val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 450) // was 1000 | |||
| // Reduced heights by ~80% to hit the 12KB-17KB file size target | |||
| // These heights (100-180) will produce much smaller BMP files | |||
| val productBmp = createMonochromeBitmap(productName, 100) | |||
| val codeBmp = createMonochromeBitmap(itemCode, 180) | |||
| val expBmp = createMonochromeBitmap(expiryDate, 180) | |||
| val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 250) | |||
| val nameFile = "${lotNo}_product.bmp" | |||
| val codeFile = "${lotNo}_code.bmp" | |||
| @@ -59,8 +60,8 @@ open class PlasticBagPrinterService( | |||
| addToZip(zos, expFile, expBmp.bytes) | |||
| addToZip(zos, qrFile, qrBmp.bytes) | |||
| // Minified XML - no indentation/newlines between tags | |||
| val imageXml = """<?xml version="1.0" encoding="utf-8"?><Legend type="Image.V1" PaperColor="White" BackgroundColor="DarkGray"><DeviceInfo DeviceURI="NGEDriver[SDX40c.cadb94e3-677c-4bcb-9c80-88bf9526d6fe]/"><DeviceName/></DeviceInfo><Mirrored>false</Mirrored><Orientation>DEG_0</Orientation><Width>5300</Width><Height>7100</Height><FieldList><Logo type="Logo.V1"><Name>LOGO</Name><Geometry><X>0</X><Y>250</Y></Geometry><FieldColor>BLACK</FieldColor><FileName>$nameFile</FileName><Width>${productBmp.width}</Width><Height>520</Height></Logo><Logo type="Logo.V1"><Name>LOGO_2</Name><Geometry><X>1000</X><Y>1250</Y></Geometry><FieldColor>BLACK</FieldColor><FileName>$codeFile</FileName><Width>${codeBmp.width}</Width><Height>900</Height></Logo><Logo type="Logo.V1"><Name>LOGO_3</Name><Geometry><X>500</X><Y>2500</Y></Geometry><FieldColor>BLACK</FieldColor><FileName>$expFile</FileName><Width>${expBmp.width}</Width><Height>900</Height></Logo><Logo type="Logo.V1"><Name>LOGO_4</Name><Geometry><X>750</X><Y>3750</Y></Geometry><FieldColor>BLACK</FieldColor><FileName>$qrFile</FileName><Width>${qrBmp.width}</Width><Height>450</Height></Logo></FieldList></Legend>""".trimIndent() | |||
| // The XML Width/Height must match the ACTUAL generated bitmap dimensions | |||
| val imageXml = """<?xml version="1.0" encoding="utf-8"?><Legend type="Image.V1" PaperColor="White" BackgroundColor="DarkGray"><DeviceInfo DeviceURI="NGEDriver[SDX40c.cadb94e3-677c-4bcb-9c80-88bf9526d6fe]/"><DeviceName /></DeviceInfo><Description /><Mirrored>false</Mirrored><Orientation>DEG_0</Orientation><Width>5300</Width><Height>7100</Height><FieldList><Logo type="Logo.V1"><Name>LOGO</Name><ID>4</ID><Geometry><X>250</X><Y>500</Y><Rotation>0</Rotation></Geometry><FieldColor>BLACK</FieldColor><FileName>$nameFile</FileName><Width>${productBmp.width}</Width><Height>100</Height></Logo><Logo type="Logo.V1"><Name>LOGO_2</Name><ID>5</ID><Geometry><X>1000</X><Y>1250</Y><Rotation>0</Rotation></Geometry><FieldColor>BLACK</FieldColor><FileName>$codeFile</FileName><Width>${codeBmp.width}</Width><Height>180</Height></Logo><Logo type="Logo.V1"><Name>LOGO_3</Name><ID>6</ID><Geometry><X>500</X><Y>2500</Y><Rotation>0</Rotation></Geometry><FieldColor>BLACK</FieldColor><FileName>$expFile</FileName><Width>${expBmp.width}</Width><Height>180</Height></Logo><Logo type="Logo.V1"><Name>LOGO_4</Name><ID>7</ID><Geometry><X>500</X><Y>3750</Y><Rotation>0</Rotation></Geometry><FieldColor>BLACK</FieldColor><FileName>$qrFile</FileName><Width>${qrBmp.width}</Width><Height>250</Height></Logo></FieldList></Legend>""".trimIndent() | |||
| addToZip(zos, "$lotNo.image", imageXml.toByteArray(Charsets.UTF_8)) | |||
| @@ -837,7 +837,7 @@ open class ProductionScheduleService( | |||
| if(isFriSat){ | |||
| //record.daysLeft = record.daysLeft | |||
| safetyStockDay = 2.6 | |||
| safetyStockDay = 3.0 | |||
| redLine = 3.0 | |||
| } | |||
| @@ -1431,7 +1431,7 @@ open class ProductionScheduleService( | |||
| val sheet = workbook.createSheet(safeSheetName) | |||
| val headers = listOf( | |||
| "Item Name", "Avg Qty Last Month", "Stock Qty", "Days Left", | |||
| "Item Code", "Item Name", "Avg Qty Last Month", "Stock Qty", "Days Left", | |||
| "Output Qty", "Batch Need", "Priority" | |||
| ) | |||
| @@ -1449,13 +1449,15 @@ open class ProductionScheduleService( | |||
| val row = sheet.createRow(index + 1) | |||
| row.heightInPoints = 35f // Slightly taller for portrait readability | |||
| row.createCell(0).apply { setCellValue(line["itemName"]?.toString() ?: ""); cellStyle = wrapStyle } | |||
| row.createCell(1).apply { setCellValue(asDouble(line["avgQtyLastMonth"])); cellStyle = wrapStyle } | |||
| row.createCell(2).apply { setCellValue(asDouble(line["stockQty"])); cellStyle = wrapStyle } | |||
| row.createCell(3).apply { setCellValue(asDouble(line["daysLeft"])); cellStyle = wrapStyle } | |||
| row.createCell(4).apply { setCellValue(asDouble(line["outputdQty"] ?: line["outputQty"])); cellStyle = wrapStyle } | |||
| row.createCell(5).apply { setCellValue(asDouble(line["batchNeed"])); cellStyle = wrapStyle } | |||
| row.createCell(6).apply { setCellValue(asDouble(line["itemPriority"])); cellStyle = wrapStyle } | |||
| var j = 0; | |||
| row.createCell(j++).apply { setCellValue(line["itemCode"]?.toString() ?: ""); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(line["itemName"]?.toString() ?: ""); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["avgQtyLastMonth"])); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["stockQty"])); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["daysLeft"])); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["outputdQty"] ?: line["outputQty"])); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["batchNeed"])); cellStyle = wrapStyle } | |||
| row.createCell(j++).apply { setCellValue(asDouble(line["itemPriority"])); cellStyle = wrapStyle } | |||
| } | |||
| // Auto-size with wider limits for portrait | |||
| @@ -1744,7 +1746,8 @@ open class ProductionScheduleService( | |||
| where ps.produceAt >= :fromDate | |||
| and ps.id = (select id from production_schedule where produceAt = ps.produceAt order by id desc limit 1) | |||
| -- and it.code = 'PP2236' | |||
| -- This is water | |||
| AND it.code != 'GI3236' | |||
| -- order by ps.produceAt asc, psl.itemPriority desc, itemCode asc | |||
| group by matCode | |||
| """; | |||
| @@ -1796,6 +1799,7 @@ open class ProductionScheduleService( | |||
| LIMIT 1 | |||
| ) | |||
| AND bm.itemId IS NOT NULL | |||
| AND itm.code != 'GI3236' | |||
| GROUP BY | |||
| itm.id, | |||
| DATE(ps.produceAt) | |||