175 lines
5.0 KiB
TypeScript
175 lines
5.0 KiB
TypeScript
import {FastifyInstance} from "fastify";
|
||
// import { PNG } from 'pngjs'
|
||
// import { ready as zplReady } from 'zpl-renderer-js'
|
||
// import { Utils } from '@mmote/niimbluelib'
|
||
// import { createCanvas } from 'canvas'
|
||
// import bwipjs from 'bwip-js'
|
||
// import Sharp from 'sharp'
|
||
// import fs from 'fs'
|
||
|
||
import { tenants } from "../../db/schema"
|
||
import { eq } from "drizzle-orm"
|
||
|
||
export const useNextNumberRangeNumber = async (
|
||
server: FastifyInstance,
|
||
tenantId: number,
|
||
numberRange: string
|
||
) => {
|
||
// 1️⃣ Tenant laden
|
||
const [tenant] = await server.db
|
||
.select()
|
||
.from(tenants)
|
||
.where(eq(tenants.id, tenantId))
|
||
|
||
if (!tenant) {
|
||
throw new Error(`Tenant ${tenantId} not found`)
|
||
}
|
||
|
||
const numberRanges = tenant.numberRanges || {}
|
||
|
||
if (!numberRanges[numberRange]) {
|
||
throw new Error(`Number range '${numberRange}' not found`)
|
||
}
|
||
|
||
const current = numberRanges[numberRange]
|
||
|
||
// 2️⃣ Used Number generieren
|
||
const usedNumber =
|
||
(current.prefix || "") +
|
||
current.nextNumber +
|
||
(current.suffix || "")
|
||
|
||
// 3️⃣ nextNumber erhöhen
|
||
const updatedRanges = {
|
||
// @ts-ignore
|
||
...numberRanges,
|
||
[numberRange]: {
|
||
...current,
|
||
nextNumber: current.nextNumber + 1
|
||
}
|
||
}
|
||
|
||
// 4️⃣ Tenant aktualisieren
|
||
await server.db
|
||
.update(tenants)
|
||
.set({ numberRanges: updatedRanges })
|
||
.where(eq(tenants.id, tenantId))
|
||
|
||
return { usedNumber }
|
||
}
|
||
|
||
|
||
/*
|
||
export async function encodeBase64ToNiimbot(base64Png, printDirection = 'top') {
|
||
// 1️⃣ PNG dekodieren
|
||
const buffer = Buffer.from(base64Png, 'base64')
|
||
const png = PNG.sync.read(buffer) // liefert {width, height, data: Uint8Array(RGBA)}
|
||
|
||
const { width, height, data } = png
|
||
console.log(width, height, data)
|
||
const cols = printDirection === 'left' ? height : width
|
||
const rows = printDirection === 'left' ? width : height
|
||
const rowsData = []
|
||
|
||
console.log(cols)
|
||
|
||
if (cols % 8 !== 0) throw new Error('Column count must be multiple of 8')
|
||
|
||
// 2️⃣ Zeilenweise durchgehen und Bits bilden
|
||
for (let row = 0; row < rows; row++) {
|
||
let isVoid = true
|
||
let blackPixelsCount = 0
|
||
const rowData = new Uint8Array(cols / 8)
|
||
|
||
for (let colOct = 0; colOct < cols / 8; colOct++) {
|
||
let pixelsOctet = 0
|
||
for (let colBit = 0; colBit < 8; colBit++) {
|
||
const x = printDirection === 'left' ? row : colOct * 8 + colBit
|
||
const y = printDirection === 'left' ? height - 1 - (colOct * 8 + colBit) : row
|
||
const idx = (y * width + x) * 4
|
||
const lum = 0.299 * data[idx] + 0.587 * data[idx + 1] + 0.114 * data[idx + 2]
|
||
const isBlack = lum < 128
|
||
if (isBlack) {
|
||
pixelsOctet |= 1 << (7 - colBit)
|
||
isVoid = false
|
||
blackPixelsCount++
|
||
}
|
||
}
|
||
rowData[colOct] = pixelsOctet
|
||
}
|
||
|
||
const newPart = {
|
||
dataType: isVoid ? 'void' : 'pixels',
|
||
rowNumber: row,
|
||
repeat: 1,
|
||
rowData: isVoid ? undefined : rowData,
|
||
blackPixelsCount,
|
||
}
|
||
|
||
if (rowsData.length === 0) {
|
||
rowsData.push(newPart)
|
||
} else {
|
||
const last = rowsData[rowsData.length - 1]
|
||
let same = newPart.dataType === last.dataType
|
||
if (same && newPart.dataType === 'pixels') {
|
||
same = Utils.u8ArraysEqual(newPart.rowData, last.rowData)
|
||
}
|
||
if (same) last.repeat++
|
||
else rowsData.push(newPart)
|
||
if (row % 200 === 199) {
|
||
rowsData.push({
|
||
dataType: 'check',
|
||
rowNumber: row,
|
||
repeat: 0,
|
||
rowData: undefined,
|
||
blackPixelsCount: 0,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
return { cols, rows, rowsData }
|
||
}
|
||
|
||
export async function generateLabel(context,width,height) {
|
||
// Canvas für Hintergrund & Text
|
||
const canvas = createCanvas(width, height)
|
||
const ctx = canvas.getContext('2d')
|
||
|
||
// Hintergrund weiß
|
||
ctx.fillStyle = '#FFFFFF'
|
||
ctx.fillRect(0, 0, width, height)
|
||
|
||
// Überschrift
|
||
ctx.fillStyle = '#000000'
|
||
ctx.font = '32px Arial'
|
||
ctx.fillText(context.text, 20, 40)
|
||
|
||
// 3) DataMatrix
|
||
const dataMatrixPng = await bwipjs.toBuffer({
|
||
bcid: 'datamatrix',
|
||
text: context.datamatrix,
|
||
scale: 6,
|
||
})
|
||
|
||
// Basisbild aus Canvas
|
||
const base = await Sharp(canvas.toBuffer())
|
||
.png()
|
||
.toBuffer()
|
||
|
||
// Alles zusammen compositen
|
||
const final = await Sharp(base)
|
||
.composite([
|
||
{ input: dataMatrixPng, top: 60, left: 20 },
|
||
])
|
||
.png()
|
||
.toBuffer()
|
||
|
||
fs.writeFileSync('label.png', final)
|
||
|
||
// Optional: Base64 zurückgeben (z.B. für API)
|
||
const base64 = final.toString('base64')
|
||
|
||
return base64
|
||
}*/
|