Enhance printing functionality in DocumentPrinterClient and interfaces
All checks were successful
farmcontrol/farmcontrol-server/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-server/pipeline/head This commit looks good
- Introduced job quantity handling in `DocumentPrinterClient` to manage multiple copies of print jobs. - Added `resolvePrintQuantity` method to ensure valid print quantities. - Updated `CupsInterface` and `ReceiptInterface` to accept a quantity parameter in the `print` method, allowing for multiple copies to be printed in a single call. - Improved logging to reflect the number of copies being printed for better user feedback.
This commit is contained in:
parent
0dc7ed3f92
commit
bb9b472559
@ -22,6 +22,7 @@ export class DocumentPrinterClient {
|
||||
this.documentPrinter = documentPrinter;
|
||||
this.connection = documentPrinter.connection;
|
||||
this.queue = [];
|
||||
this.jobQuantities = new Map();
|
||||
this.documentPrinterManager = documentPrinterManager;
|
||||
this.currentJob = null;
|
||||
this.active = documentPrinter.active == true;
|
||||
@ -297,6 +298,14 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
}
|
||||
|
||||
resolvePrintQuantity(quantity) {
|
||||
const parsed = Number(quantity);
|
||||
if (!Number.isFinite(parsed) || parsed < 1) {
|
||||
return 1;
|
||||
}
|
||||
return Math.floor(parsed);
|
||||
}
|
||||
|
||||
async updateJobState(jobId, state) {
|
||||
logger.info(`Updating job state for ${jobId}`);
|
||||
const notify =
|
||||
@ -389,6 +398,10 @@ export class DocumentPrinterClient {
|
||||
type: "queued",
|
||||
progress: null,
|
||||
});
|
||||
this.jobQuantities.set(
|
||||
documentJob._id,
|
||||
this.resolvePrintQuantity(documentJob.quantity),
|
||||
);
|
||||
// Only add job to queue if it's not already there
|
||||
if (!this.queue.includes(documentJob._id)) {
|
||||
this.queue.push(documentJob._id);
|
||||
@ -512,15 +525,21 @@ export class DocumentPrinterClient {
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info(`Printing job ${jobId} for ${this.documentPrinter.name}`);
|
||||
const quantity = this.resolvePrintQuantity(
|
||||
this.jobQuantities.get(jobId),
|
||||
);
|
||||
logger.info(
|
||||
`Printing job ${jobId} (${quantity} ${quantity === 1 ? "copy" : "copies"}) for ${this.documentPrinter.name}`,
|
||||
);
|
||||
await this.updateJobState(jobId, { type: "printing" });
|
||||
|
||||
await this.printerInterface.print(jobId);
|
||||
await this.printerInterface.print(jobId, quantity);
|
||||
logger.info(
|
||||
`Successfully printed job ${jobId} for ${this.documentPrinter.name}`,
|
||||
`Successfully printed job ${jobId} (${quantity} ${quantity === 1 ? "copy" : "copies"}) for ${this.documentPrinter.name}`,
|
||||
);
|
||||
// Only remove job from queue after successful printing
|
||||
this.queue.shift();
|
||||
this.jobQuantities.delete(jobId);
|
||||
await this.updateJobState(jobId, { type: "complete" });
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
@ -531,6 +550,7 @@ export class DocumentPrinterClient {
|
||||
// Remove failed job from queue to prevent infinite retry loop
|
||||
// You may want to implement retry logic or error handling here
|
||||
this.queue.shift();
|
||||
this.jobQuantities.delete(jobId);
|
||||
await this.updateJobState(jobId, { type: "failed" });
|
||||
// Continue with next job even if one fails
|
||||
}
|
||||
@ -561,6 +581,7 @@ export class DocumentPrinterClient {
|
||||
this.state = { type: this.active == false ? "inactive" : "offline" };
|
||||
this.isProcessingQueue = false;
|
||||
this.queue = []; // Clear queue on disconnect
|
||||
this.jobQuantities.clear();
|
||||
await this.updateDocumentPrinterState();
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
logger.info(`Successfully disconnected from ${this.documentPrinter.name}`);
|
||||
|
||||
@ -253,8 +253,11 @@ export default class CupsInterface {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
async print(jobId) {
|
||||
logger.info(`Printing job ${jobId} to CUPS printer ${this.name}`);
|
||||
async print(jobId, quantity = 1) {
|
||||
const copies = Math.max(1, Math.floor(Number(quantity) || 1));
|
||||
logger.info(
|
||||
`Printing job ${jobId} (${copies} ${copies === 1 ? "copy" : "copies"}) to CUPS printer ${this.name}`
|
||||
);
|
||||
|
||||
if (!this.isConnected || !this.cupsPrinter) {
|
||||
throw new Error("Printer is not connected");
|
||||
@ -295,22 +298,28 @@ export default class CupsInterface {
|
||||
data: documentData,
|
||||
};
|
||||
|
||||
// Send print job
|
||||
logger.debug(`Sending print job ${jobId} to ${this.cupsPrinterUrl}`);
|
||||
const response = await this.executeIPP("Print-Job", printJobMessage);
|
||||
|
||||
// Extract job ID from response
|
||||
const ippJobId = response["job-attributes-tag"]?.["job-id"];
|
||||
const jobUri = response["job-attributes-tag"]?.["job-uri"];
|
||||
// Send one print job per copy so quantity is honored even when the
|
||||
// printer does not support the IPP copies attribute.
|
||||
logger.debug(
|
||||
`Sending print job ${jobId} (${copies} ${copies === 1 ? "copy" : "copies"}) to ${this.cupsPrinterUrl}`
|
||||
);
|
||||
let ippJobId;
|
||||
let jobUri;
|
||||
for (let copy = 0; copy < copies; copy++) {
|
||||
const response = await this.executeIPP("Print-Job", printJobMessage);
|
||||
ippJobId = response["job-attributes-tag"]?.["job-id"];
|
||||
jobUri = response["job-attributes-tag"]?.["job-uri"];
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Successfully printed job ${jobId} to CUPS printer ${this.name}. IPP Job ID: ${ippJobId}`
|
||||
`Successfully printed job ${jobId} (${copies} ${copies === 1 ? "copy" : "copies"}) to CUPS printer ${this.name}. IPP Job ID: ${ippJobId}`
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
jobId: ippJobId,
|
||||
jobUri: jobUri,
|
||||
copies,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
|
||||
@ -120,8 +120,11 @@ export default class ReceiptInterface {
|
||||
return true;
|
||||
}
|
||||
|
||||
async print(jobId) {
|
||||
logger.info(`Printing job ${jobId} to receipt printer ${this.name}`);
|
||||
async print(jobId, quantity = 1) {
|
||||
const copies = Math.max(1, Math.floor(Number(quantity) || 1));
|
||||
logger.info(
|
||||
`Printing job ${jobId} (${copies} ${copies === 1 ? "copy" : "copies"}) to receipt printer ${this.name}`
|
||||
);
|
||||
|
||||
if (!this.isConnected || !this.receiptPrinter) {
|
||||
throw new Error("Printer is not connected");
|
||||
@ -138,22 +141,24 @@ export default class ReceiptInterface {
|
||||
|
||||
const imageArray = Array.isArray(images) ? images : [images];
|
||||
|
||||
for (const image of imageArray) {
|
||||
const imageBuffer = Buffer.isBuffer(image)
|
||||
? Buffer.from(image)
|
||||
: Buffer.from(image);
|
||||
await this.receiptPrinter.printImageBuffer(imageBuffer);
|
||||
this.receiptPrinter.cut();
|
||||
for (let copy = 0; copy < copies; copy++) {
|
||||
for (const image of imageArray) {
|
||||
const imageBuffer = Buffer.isBuffer(image)
|
||||
? Buffer.from(image)
|
||||
: Buffer.from(image);
|
||||
await this.receiptPrinter.printImageBuffer(imageBuffer);
|
||||
this.receiptPrinter.cut();
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the print job
|
||||
await this.receiptPrinter.execute({ waitForResponse: true });
|
||||
|
||||
logger.info(
|
||||
`Successfully printed job ${jobId} to receipt printer ${this.name}`
|
||||
`Successfully printed job ${jobId} (${copies} ${copies === 1 ? "copy" : "copies"}) to receipt printer ${this.name}`
|
||||
);
|
||||
|
||||
return { success: true };
|
||||
return { success: true, copies };
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to print job ${jobId} to receipt printer ${this.name}:`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user