feat: restructure sales, add PDF quote generation and WebSocket support
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import { createRoute } from "../../../../../modules/api-utils/createRoute";
|
||||
import { generatedQuotes } from "../../../../../managers/generatedQuotes";
|
||||
import { apiResponse } from "../../../../../modules/api-utils/apiResponse";
|
||||
import { injectPdfMetadata } from "../../../../../modules/pdf-utils";
|
||||
import { ContentfulStatusCode } from "hono/utils/http-status";
|
||||
import { authMiddleware } from "../../../../middleware/authorization";
|
||||
import GenericError from "../../../../../Errors/GenericError";
|
||||
|
||||
const VALID_FETCH_ACTIONS = ["download", "print"] as const;
|
||||
type FetchAction = (typeof VALID_FETCH_ACTIONS)[number];
|
||||
|
||||
/* GET /v1/sales/opportunities/:identifier/quote/:quoteId/download?fetchAction=download|print */
|
||||
export default createRoute(
|
||||
"get",
|
||||
["/opportunities/:identifier/quote/:quoteId/download"],
|
||||
async (c) => {
|
||||
const quoteId = c.req.param("quoteId");
|
||||
const user = c.get("user");
|
||||
const fetchAction = c.req.query("fetchAction") as FetchAction | undefined;
|
||||
|
||||
if (!fetchAction || !VALID_FETCH_ACTIONS.includes(fetchAction)) {
|
||||
throw new GenericError({
|
||||
status: 400,
|
||||
name: "InvalidFetchAction",
|
||||
message: `Query parameter 'fetchAction' is required and must be one of: ${VALID_FETCH_ACTIONS.join(", ")}`,
|
||||
});
|
||||
}
|
||||
|
||||
const downloadedAt = new Date().toISOString();
|
||||
|
||||
const quote = await generatedQuotes.recordDownload(quoteId, {
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
fetchAction,
|
||||
});
|
||||
|
||||
// Inject download-time metadata into the PDF's document properties
|
||||
const pdfWithMetadata = await injectPdfMetadata(quote.quoteFile, {
|
||||
downloadedAt,
|
||||
downloadedById: user.id,
|
||||
downloadedByName: user.name ?? undefined,
|
||||
downloadedByEmail: user.email ?? undefined,
|
||||
});
|
||||
|
||||
const response = apiResponse.successful("Quote downloaded successfully!", {
|
||||
id: quote.id,
|
||||
quoteFileName: quote.quoteFileName,
|
||||
mimeType: "application/pdf",
|
||||
contentBase64: Buffer.from(pdfWithMetadata).toString("base64"),
|
||||
});
|
||||
return c.json(response, response.status as ContentfulStatusCode);
|
||||
},
|
||||
authMiddleware({ permissions: ["sales.opportunity.quote.download"] }),
|
||||
);
|
||||
Reference in New Issue
Block a user