pini-print-bot / controllers /documentController.js
dotandru's picture
V5.4: Resolve False Zero Prices & Implement Partial Transparency - Hebrew PDF Support Hardened
492565a
Raw
History Blame Contribute Delete
3.11 kB
const { getSession } = require('../services/sessionManager');
const { generateQuotePDF } = require('../services/pdfService');
const { generateSignedUploadUrl } = require('../services/storageService');
const { validateImageSize } = require('../engine/imageProcessor');
/**
* Handles requests for generating a PDF quote based on a user's cart.
*/
async function handlePdfQuote(req, res) {
const { userId, cart: clientCart } = req.body;
// Fetch cart from body, or fallback to server session state
let cart = clientCart;
let isDraft = false;
if (userId) {
const session = getSession(userId);
if (!cart) cart = session.cart;
if (session.draftAttributes && Object.keys(session.draftAttributes).length > 0) {
isDraft = true;
}
}
if (!cart || cart.length === 0) {
return res.status(400).send("ื”ืขื’ืœื” ืจื™ืงื”");
}
try {
console.log(`๐Ÿ“„ Generating PDF Quote (isDraft: ${isDraft}) via DocumentController...`);
// Build PDF Buffer
const pdfBuffer = await generateQuotePDF(cart, { name: "ืœืงื•ื— ื™ืงืจ" }, isDraft);
// Define headers for file download
res.set({
'Content-Type': 'application/pdf',
'Content-Length': pdfBuffer.length,
'Content-Disposition': 'attachment; filename="quote.pdf"'
});
// Send file
res.send(pdfBuffer);
console.log("โœ… PDF sent successfully to client");
} catch (error) {
console.error("โŒ DocumentController Error:", error);
res.status(500).json({ error: "Failed to generate PDF" });
}
}
/**
* Generates a signed URL for direct GCP upload.
* Validates session and file size (client-reported) before granting URL.
*/
async function handleSignedUrl(req, res) {
const { userId, fileName, fileSize } = req.body;
if (!userId || !fileName || !fileSize) {
return res.status(400).json({ error: "Missing required parameters (userId, fileName, fileSize)" });
}
// 10MB Gatekeeper (Technical size check before granting storage access)
const MAX_SIZE_BYTES = 10 * 1024 * 1024;
if (fileSize > MAX_SIZE_BYTES) {
console.warn(`[IMAGE GATEKEEPER] Rejected ${fileName} due to size: ${fileSize}`);
return res.status(413).json({
error: "FILE_TOO_LARGE",
message: "ืงื•ื‘ืฅ ื’ื“ื•ืœ ืžื“ื™. ืžืงืกื™ืžื•ื 10MB."
});
}
try {
const result = await generateSignedUploadUrl(userId, fileName);
res.json(result);
} catch (error) {
res.status(500).json({ error: "Failed to generate signed URL" });
}
}
/**
* Technical validator for buffers (for local processing if needed).
*/
async function handleImageValidation(req, res) {
const { buffer } = req.body; // Assuming small metadata/preview buffer for now
const check = validateImageSize(buffer);
if (!check.valid) {
return res.status(400).json(check);
}
res.json({ valid: true });
}
module.exports = {
handlePdfQuote,
handleSignedUrl,
handleImageValidation
};