Skip to content

Commit 094b246

Browse files
committed
Final fixes
1 parent 92fd593 commit 094b246

File tree

23 files changed

+372
-201
lines changed

23 files changed

+372
-201
lines changed
361 Bytes
Binary file not shown.

back/package-lock.json

+213-82
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

back/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"passport-local": "^1.0.0",
6565
"passport-oauth2-client-password": "^0.1.2",
6666
"pdf-lib": "^1.12.0",
67+
"postgres-migrations": "^5.1.0",
6768
"rate-limit-redis": "^2.0.0",
6869
"request": "^2.88.2",
6970
"winston": "^3.2.1",

back/prisma/migrate.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const dbConfig = {
66
user: process.env.POSTGRES_USER,
77
password: process.env.POSTGRES_PASSWORD,
88
host: process.env.POSTGRES_HOST,
9-
port: process.env.POSTGRES_PORT
9+
port: parseInt(process.env.POSTGRES_PORT, 10)
1010
};
1111

1212
migrate(dbConfig, path.join(__dirname, "migrations"))

back/prisma/migrations/03_migration.relations.sql

+27-1
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,30 @@ ALTER TABLE "default$default"."StatusLog" RENAME COLUMN "user" to "userId";
5757
ALTER TABLE "default$default"."TransportSegment" RENAME COLUMN "form" to "formId";
5858

5959
-- Form.isAccepted default to false
60-
ALTER TABLE "default$default"."Form" ALTER COLUMN "isAccepted" SET DEFAULT FALSE;
60+
ALTER TABLE "default$default"."Form" ALTER COLUMN "isAccepted" SET DEFAULT FALSE;
61+
62+
-- Application admins: Migrate from N-N to 1-N
63+
ALTER TABLE "default$default"."User" ADD COLUMN "applicationId" character varying(30);
64+
65+
UPDATE "default$default"."User"
66+
SET "applicationId" = t."A"
67+
FROM (
68+
SELECT *
69+
FROM "default$default"."_ApplicationToUser"
70+
) t
71+
WHERE t."B" = "default$default"."User"."id";
72+
73+
DROP TABLE "default$default"."_ApplicationToUser";
74+
75+
-- Appendix2 forms: Migrate from N-N to 1-N
76+
ALTER TABLE "default$default"."Form" ADD COLUMN "appendix2RootFormId" character varying(30);
77+
78+
UPDATE "default$default"."Form"
79+
SET "appendix2RootFormId" = t."A"
80+
FROM (
81+
SELECT *
82+
FROM "default$default"."_FormToForm"
83+
) t
84+
WHERE t."B" = "default$default"."Form"."id";
85+
86+
DROP TABLE "default$default"."_FormToForm";

back/prisma/schema.prisma

+17
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,23 @@ model Company {
152152
transporterReceipt TransporterReceipt? @relation(fields: [transporterReceiptId], references: [id])
153153
}
154154

155+
// Companies with restricted diffusion of SIRENE information (police, army, etc)
156+
157+
// "Certaines entreprises demandent à ne pas figurer sur les listes de diffusion publique
158+
// en vertu de l'article A123-96 du code du commerce. On parle d‘entreprise non diffusable.
159+
// Dans ce cas les API SIRENE ne diffusent pas les informations de cette entreprise dans
160+
// les résultats de recherche. Pour des raisons de sécurité, certaines associations et les
161+
// organismes relevant du Ministère de la Défense ne sont pas diffusibles non plus."
162+
model AnonymousCompany {
163+
id String @id @default(cuid())
164+
siret String @unique
165+
name String
166+
address String
167+
codeNaf String
168+
libelleNaf String
169+
codeCommune String
170+
}
171+
155172
model CompanyAssociation {
156173
id String @id @default(cuid())
157174
role UserRole

back/prisma/scripts/load-anonymous-companies.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as fs from "fs";
22
import { Updater, registerUpdater } from "./helper/helper";
3-
import { prisma } from "../../src/generated/prisma-client";
3+
import prisma from "src/prisma";
44

55
@registerUpdater(
66
"Load anonymous companies",
@@ -20,7 +20,7 @@ export class LoadAnonymousCompaniesUpdater implements Updater {
2020
const data = JSON.parse(fs.readFileSync(fixturePath, "utf8"));
2121

2222
for (const companyInput of data) {
23-
await prisma.createAnonymousCompany(companyInput);
23+
await prisma.anonymousCompany.create({ data: companyInput });
2424
}
2525
} catch (err) {
2626
console.error("☠ Something went wrong during the update", err);

back/prisma/scripts/set-contacts.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import axios from "axios";
2-
import { addContact } from "src/common/mails.helper";
2+
import { addContact } from "src/mailer/mailing";
33
import prisma from "src/prisma";
44
import { Updater, registerUpdater } from "./helper/helper";
55

back/src/commands/__tests__/sendmails.tests.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ jest.mock("src/prisma", () => ({
2323
}));
2424

2525
describe("xDaysAgo", () => {
26-
it("should return a formatted relative past date", () => {
26+
it("should return a relative past date", () => {
2727
const someDate = new Date(2019, 9, 3, 10, 0, 0);
2828
const threeDaysBefore = xDaysAgo(someDate, 3);
29-
expect(threeDaysBefore).toEqual("2019-09-30");
29+
expect(threeDaysBefore.toISOString()).toEqual("2019-09-30T00:00:00.000Z");
3030
});
3131
});
3232

back/src/commands/onboarding.helpers.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import { userMails } from "../users/mails";
77
*
88
* @param baseDate Date
99
* @param daysAgo Integer
10-
* @return a date formatted as "YYYY-MM-DD"
10+
* @return a date at 00:00:00
1111
*/
12-
export const xDaysAgo = (baseDate: Date, daysAgo: number): string => {
12+
export const xDaysAgo = (baseDate: Date, daysAgo: number): Date => {
1313
const clonedDate = new Date(baseDate.getTime()); // avoid mutating baseDate
14-
return new Date(clonedDate.setDate(clonedDate.getDate() - daysAgo))
15-
.toISOString()
16-
.split("T")[0];
14+
clonedDate.setDate(clonedDate.getDate() - daysAgo);
15+
16+
return new Date(clonedDate.toDateString());
1717
};
1818

1919
/**
@@ -31,8 +31,8 @@ export const sendOnboardingEmails = async (daysAgo: number, emailFunction) => {
3131
const recipients = await prisma.user.findMany({
3232
where: {
3333
AND: [
34-
{ createdAt_gt: inscriptionDateGt },
35-
{ createdAt_lt: inscriptionDateLt }
34+
{ createdAt: { gt: inscriptionDateGt } },
35+
{ createdAt: { lt: inscriptionDateLt } }
3636
],
3737
isActive: true
3838
}

back/src/companies/sirene/__tests__/index.integration.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { UserInputError } from "apollo-server-express";
2+
import prisma from "src/prisma";
13
import * as searchCompanyDecorated from "../searchCompany";
24
import { searchCompany } from "../index";
35
import { resetDatabase } from "../../../../integration-tests/helper";
4-
import { UserInputError } from "apollo-server-express";
5-
import { prisma } from "../../../generated/prisma-client";
66

77
const searchCompanySpy = jest.spyOn(searchCompanyDecorated, "default");
88
// Mock the fact a siret is not found in SIRENE API's
@@ -21,13 +21,15 @@ describe("searchCompany", () => {
2121
// do not bypass sirene client call
2222
process.env.NODE_ENV = "production";
2323
const siret = "11111111111111";
24-
const anonymousCompany = await prisma.createAnonymousCompany({
25-
siret,
26-
name: "GENDARMERIE NATIONALE",
27-
address: "Rue des tropiques, Saint Tropez",
28-
codeNaf: "7150",
29-
libelleNaf: "Service du ministère de la Défense",
30-
codeCommune: "83119 "
24+
const anonymousCompany = await prisma.anonymousCompany.create({
25+
data: {
26+
siret,
27+
name: "GENDARMERIE NATIONALE",
28+
address: "Rue des tropiques, Saint Tropez",
29+
codeNaf: "7150",
30+
libelleNaf: "Service du ministère de la Défense",
31+
codeCommune: "83119 "
32+
}
3133
});
3234
const searchResult = await searchCompany(siret);
3335
expect(searchResult).toMatchObject(anonymousCompany);

back/src/companies/sirene/anonymous.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CompanySearchResult } from "../../generated/graphql/types";
2-
import { prisma } from "../../generated/prisma-client";
2+
import prisma from "src/prisma";
33

44
/**
55
* "Certaines entreprises demandent à ne pas figurer sur les listes de diffusion publique
@@ -14,7 +14,9 @@ import { prisma } from "../../generated/prisma-client";
1414
export async function searchAnonymousCompany(
1515
siret: string
1616
): Promise<CompanySearchResult> {
17-
const company = await prisma.anonymousCompany({ siret });
17+
const company = await prisma.anonymousCompany.findUnique({
18+
where: { siret }
19+
});
1820
if (company) {
1921
return {
2022
...company,

back/src/events/__tests__/traceability-break.test.ts

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Form } from "@prisma/client";
2-
import axios from "axios";
2+
import * as mailing from "../../mailer/mailing";
33
import { TDEventPayload } from "../emitter";
44

55
import { formsEventCallback } from "../forms";
@@ -43,18 +43,15 @@ describe("mailWhenFormTraceabilityIsBroken", () => {
4343
} as Form
4444
};
4545

46-
const mockedAxiosPost = jest.spyOn(axios, "post");
47-
mockedAxiosPost.mockResolvedValue({} as any);
46+
const mockedSendMail = jest.spyOn(mailing, "sendMail");
4847

4948
await formsEventCallback(formPayload);
5049

51-
expect(mockedAxiosPost as jest.Mock<any>).toHaveBeenCalledTimes(1);
50+
expect(mockedSendMail as jest.Mock<any>).toHaveBeenCalledTimes(1);
5251

53-
const postArgs = mockedAxiosPost.mock.calls[0];
52+
const postArgs = mockedSendMail.mock.calls[0];
5453

55-
expect(postArgs[0]).toEqual("http://mailservice/smtp/email"); // fake url for tests
56-
57-
const payload = postArgs[1];
54+
const payload = postArgs[0];
5855

5956
// Check To & Cc
6057
expect(payload.to[0].email).toEqual(mockedForm.emitterCompanyMail);
@@ -64,9 +61,9 @@ describe("mailWhenFormTraceabilityIsBroken", () => {
6461
expect(payload.cc[0].name).toEqual(mockedForm.recipientCompanyContact);
6562

6663
// check mail body infos
67-
expect(payload.params.body).toContain(mockedForm.readableId);
68-
expect(payload.params.body).toContain(mockedForm.recipientCompanyName);
69-
expect(payload.params.body).toContain(mockedForm.wasteDetailsName);
70-
expect(payload.params.body).toContain(mockedForm.wasteDetailsCode);
64+
expect(payload.body).toContain(mockedForm.readableId);
65+
expect(payload.body).toContain(mockedForm.recipientCompanyName);
66+
expect(payload.body).toContain(mockedForm.wasteDetailsName);
67+
expect(payload.body).toContain(mockedForm.wasteDetailsCode);
7168
});
7269
});

back/src/forms/__tests__/permissions.integration.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Form, User } from "@prisma/client";
1+
import { Form, User, Status } from "@prisma/client";
22
import prisma from "src/prisma";
33
import { resetDatabase } from "../../../integration-tests/helper";
44
import { ErrorCode } from "../../common/errors";
@@ -25,7 +25,7 @@ import {
2525

2626
async function checkEmitterPermission(
2727
permission: (user: User, form: Form) => Promise<boolean>,
28-
formStatus = "DRAFT"
28+
formStatus = Status.DRAFT
2929
) {
3030
const owner = await userFactory();
3131
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -38,7 +38,7 @@ async function checkEmitterPermission(
3838

3939
async function checkRecipientPermission(
4040
permission: (user: User, form: Form) => Promise<boolean>,
41-
formStatus = "DRAFT"
41+
formStatus = Status.DRAFT
4242
) {
4343
const owner = await userFactory();
4444
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -51,7 +51,7 @@ async function checkRecipientPermission(
5151

5252
async function checkTransporterPermission(
5353
permission: (user: User, form: Form) => Promise<boolean>,
54-
formStatus = "DRAFT"
54+
formStatus = Status.DRAFT
5555
) {
5656
const owner = await userFactory();
5757
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -64,7 +64,7 @@ async function checkTransporterPermission(
6464

6565
async function checkTraderPermission(
6666
permission: (user: User, form: Form) => Promise<boolean>,
67-
formStatus = "DRAFT"
67+
formStatus = Status.DRAFT
6868
) {
6969
const owner = await userFactory();
7070
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -77,7 +77,7 @@ async function checkTraderPermission(
7777

7878
async function checkEcoOrganismePermission(
7979
permission: (user: User, form: Form) => Promise<boolean>,
80-
formStatus = "DRAFT"
80+
formStatus = Status.DRAFT
8181
) {
8282
const owner = await userFactory();
8383
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -101,7 +101,7 @@ async function checkEcoOrganismePermission(
101101

102102
async function checkTransporterAfterTempStoragePermission(
103103
permission: (user: User, form: Form) => Promise<boolean>,
104-
formStatus = "DRAFT"
104+
formStatus = Status.DRAFT
105105
) {
106106
const owner = await userFactory();
107107
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -123,7 +123,7 @@ async function checkTransporterAfterTempStoragePermission(
123123

124124
async function checkDestinationAfterTempStoragePermission(
125125
permission: (user: User, form: Form) => Promise<boolean>,
126-
formStatus = "DRAFT"
126+
formStatus = Status.DRAFT
127127
) {
128128
const owner = await userFactory();
129129
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -145,7 +145,7 @@ async function checkDestinationAfterTempStoragePermission(
145145

146146
async function checkMultiModalTransporterPermission(
147147
permission: (user: User, form: Form) => Promise<boolean>,
148-
formStatus = "DRAFT"
148+
formStatus = Status.DRAFT
149149
) {
150150
const owner = await userFactory();
151151
const { user, company } = await userWithCompanyFactory("MEMBER");
@@ -166,7 +166,7 @@ async function checkMultiModalTransporterPermission(
166166

167167
async function checkRandomUserPermission(
168168
permission: (user: User, form: Form) => Promise<boolean>,
169-
formStatus = "DRAFT"
169+
formStatus = Status.DRAFT
170170
) {
171171
const owner = await userFactory();
172172
const user = await userFactory();

back/src/forms/permissions.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
Company,
3-
Form,
4-
User
5-
} from "@prisma/client";
1+
import { Company, Form, User } from "@prisma/client";
62
import { ForbiddenError } from "apollo-server-express";
73
import prisma from "src/prisma";
84
import { FormSirets } from "./types";

back/src/forms/resolvers/mutations/__tests__/deleteForm.integration.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ describe("Mutation.deleteForm", () => {
133133

134134
expect(data.deleteForm.id).toBeTruthy();
135135

136-
const deletedForm = await prisma.form({ id: form.id });
136+
const deletedForm = await prisma.form.findUnique({
137+
where: { id: form.id }
138+
});
137139
expect(deletedForm.isDeleted).toBe(true);
138140
}
139141
);

back/src/forms/resolvers/mutations/duplicateForm.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ const duplicateFormResolver: MutationResolvers["duplicateForm"] = async (
121121

122122
const newForm = await duplicateForm(user, existingForm);
123123

124-
const temporaryStorageDetail = await prisma
125-
.form({ id: existingForm.id })
124+
const temporaryStorageDetail = await prisma.form
125+
.findUnique({ where: { id: existingForm.id } })
126126
.temporaryStorageDetail();
127127

128128
if (temporaryStorageDetail) {

back/src/forms/resolvers/mutations/updateForm.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ const updateFormResolver = async (
8787
nextFormSirets.temporaryStorageDetail = {
8888
destinationCompanySiret:
8989
temporaryStorageDetail?.destination?.company?.siret ??
90-
existingTemporaryStorageDetail?.destinationCompanySiret
90+
existingTemporaryStorageDetail?.destinationCompanySiret,
91+
transporterCompanySiret:
92+
existingTemporaryStorageDetail?.transporterCompanySiret
9193
};
9294
}
9395

back/src/forms/types.ts

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
Form,
3-
TemporaryStorageDetail,
4-
TransportSegment
5-
} from "@prisma/client";
1+
import { Form, TemporaryStorageDetail, TransportSegment } from "@prisma/client";
62

73
/**
84
* A Prisma Form with linked objects

0 commit comments

Comments
 (0)