Skip to content

Commit

Permalink
fix: manage not found cellar object for logo/signature and generate P…
Browse files Browse the repository at this point in the history
…DF without logo/signature in case of missing image position
  • Loading branch information
loicguillois committed Dec 19, 2024
1 parent 5404cc4 commit dfe97fd
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 73 deletions.
38 changes: 19 additions & 19 deletions packages/draft/src/pdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,26 +220,26 @@ function createTransformer(opts: TransformerOptions) {

pdf.getPages().forEach((page, i) => {
const position = imagePositions.get(image.id)?.at(i);
if (!position) {
throw new Error('Image position not found');
}
if (embed instanceof PDFImage) {
page.drawImage(embed, {
x: toPoints(position.x),
// The Y-axis is inverted in the PDF specification
y: page.getHeight() - toPoints(image.height) - (image.type === 'signature' ? toPoints(position.y) : toPoints(40) + toPoints(firstImageHeight[image.type])),
width: toPoints(image.width),
height: toPoints(image.height)
});
} else if (embed instanceof PDFEmbeddedPage) {
page.drawPage(embed, {
x: toPoints(position.x) - (image.type === 'signature' ? toPoints(40) : 0),
// The Y-axis is inverted in the PDF specification
y: page.getHeight() - toPoints(imageHeight) - (image.type === 'signature' ? toPoints(position.y) : toPoints(40) + toPoints(firstImageHeight[image.type])),
width: toPoints(140),
height: toPoints(imageHeight)
});
if (position) {
logger.error(`Image position not found for page ${i}`)

Check failure on line 224 in packages/draft/src/pdf.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Missing semicolon
if (embed instanceof PDFImage) {
page.drawImage(embed, {
x: toPoints(position.x),
// The Y-axis is inverted in the PDF specification
y: page.getHeight() - toPoints(image.height) - (image.type === 'signature' ? toPoints(position.y) : toPoints(40) + toPoints(firstImageHeight[image.type])),
width: toPoints(image.width),
height: toPoints(image.height)
});
} else if (embed instanceof PDFEmbeddedPage) {
page.drawPage(embed, {
x: toPoints(position.x) - (image.type === 'signature' ? toPoints(40) : 0),
// The Y-axis is inverted in the PDF specification
y: page.getHeight() - toPoints(imageHeight) - (image.type === 'signature' ? toPoints(position.y) : toPoints(40) + toPoints(firstImageHeight[image.type])),
width: toPoints(140),
height: toPoints(imageHeight)
});

}
}
});
firstImageHeight[image.type] = firstImageHeight[image.type] === 0 ? imageHeight : 0;
Expand Down
26 changes: 16 additions & 10 deletions server/src/controllers/fileRepository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FileUploadDTO } from '@zerologementvacant/models';
import { createS3, getContent, toBase64 } from '@zerologementvacant/utils';
import FileMissingError from '~/errors/fileMissingError';
import config from '~/infra/config';
import { createLogger } from '~/infra/logger';

Expand All @@ -12,16 +13,21 @@ const s3 = createS3({
});

export async function download(logo: string): Promise<FileUploadDTO> {

logger.debug('Downloading logo from S3...');
const { content, response } = await getContent(logo, {
s3,
bucket: config.s3.bucket
});
try {
const { content, response } = await getContent(logo, {
s3,
bucket: config.s3.bucket
});

return {
id: logo,
content: toBase64(content, response.ContentType),
url: logo,
type: response.ContentType ?? 'base64'
};
return {
id: logo,
content: toBase64(content, response.ContentType),
url: logo,
type: response.ContentType ?? 'base64'
};
} catch (error) {
throw new FileMissingError();
}
}
13 changes: 13 additions & 0 deletions server/src/errors/fileMissingError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { constants } from 'http2';

import { HttpError } from './httpError';

export default class FileMissingError extends HttpError implements HttpError {
constructor() {
super({
name: 'FileMissingError',
message: `File not found on bucket`,
status: constants.HTTP_STATUS_NOT_FOUND,
});
}
}
39 changes: 26 additions & 13 deletions server/src/repositories/draftRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '~/repositories/senderRepository';
import { download } from '~/controllers/fileRepository';
import async from 'async';
import { FileUploadDTO } from '@zerologementvacant/models';

export const draftsTable = 'drafts';
export const Drafts = (transaction: Knex<DraftRecordDBO> = db) =>
Expand Down Expand Up @@ -134,19 +135,31 @@ export const formatDraftApi = (draft: DraftApi): DraftRecordDBO => ({
updated_at: new Date(draft.updatedAt)
});

export const parseDraftApi = async (draft: DraftDBO): Promise<DraftApi> => ({
id: draft.id,
subject: draft.subject,
body: draft.body,
logo: await async.map(draft.logo ?? [], download),
writtenAt: draft.written_at,
writtenFrom: draft.written_from,
establishmentId: draft.establishment_id,
senderId: draft.sender_id,
sender: await parseSenderApi(draft.sender),
createdAt: draft.created_at.toJSON(),
updatedAt: draft.updated_at.toJSON()
});
export const parseDraftApi = async (draft: DraftDBO): Promise<DraftApi> => {
let logo: FileUploadDTO[] | null = null;

if (Array.isArray(draft.logo)) {
try {
logo = await Promise.all(draft.logo.map(download));
} catch (error) {
logo = null;
}
}

return {
id: draft.id,
subject: draft.subject,
body: draft.body,
logo: logo,
writtenAt: draft.written_at,
writtenFrom: draft.written_from,
establishmentId: draft.establishment_id,
senderId: draft.sender_id,
sender: await parseSenderApi(draft.sender),
createdAt: draft.created_at.toJSON(),
updatedAt: draft.updated_at.toJSON(),
};
};

export default {
find,
Expand Down
74 changes: 43 additions & 31 deletions server/src/repositories/senderRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,37 +99,49 @@ export const formatSenderApi = (sender: SenderApi): SenderDBO => ({

export const parseSenderApi = async (
sender: SenderDBO
): Promise<SenderApi> => ({
id: sender.id,
name: sender.name,
service: sender.service,
firstName: sender.first_name,
lastName: sender.last_name,
address: sender.address,
email: sender.email,
phone: sender.phone,
signatories: [
{
firstName: sender.signatory_one_first_name,
lastName: sender.signatory_one_last_name,
role: sender.signatory_one_role,
file: sender.signatory_one_file
? await download(sender.signatory_one_file)
: null
},
{
firstName: sender.signatory_two_first_name,
lastName: sender.signatory_two_last_name,
role: sender.signatory_two_role,
file: sender.signatory_two_file
? await download(sender.signatory_two_file)
: null
}
],
createdAt: new Date(sender.created_at).toJSON(),
updatedAt: new Date(sender.updated_at).toJSON(),
establishmentId: sender.establishment_id
});
): Promise<SenderApi> => {
let signatory_one_file;
try {
signatory_one_file = sender.signatory_one_file ? await download(sender.signatory_one_file) : null;
} catch (error) {
signatory_one_file = null;
}

let signatory_two_file;
try {
signatory_two_file = sender.signatory_two_file ? await download(sender.signatory_two_file) : null;
} catch (error) {
signatory_two_file = null;
}

return {
id: sender.id,
name: sender.name,
service: sender.service,
firstName: sender.first_name,
lastName: sender.last_name,
address: sender.address,
email: sender.email,
phone: sender.phone,
signatories: [
{
firstName: sender.signatory_one_first_name,
lastName: sender.signatory_one_last_name,
role: sender.signatory_one_role,
file: signatory_one_file
},
{
firstName: sender.signatory_two_first_name,
lastName: sender.signatory_two_last_name,
role: sender.signatory_two_role,
file: signatory_two_file
}
],
createdAt: new Date(sender.created_at).toJSON(),
updatedAt: new Date(sender.updated_at).toJSON(),
establishmentId: sender.establishment_id
};
};

export default {
findOne,
Expand Down

0 comments on commit dfe97fd

Please sign in to comment.