Repository: MTES-MCT/trackdechets
Pull request #4014: Corrections cahier de recette Annexe 2 et entreposage provisoire
Author: login: benoitguigal
Labels: name: ready to merge
Created: 2025-03-06T12:54:02Z | Merged: 2025-03-07T14:20:43Z

- [Cahier de recette regroupement (Annexe 2)](https://favro.com/organization/ab14a4f0460a99a9d64d4945/2c84e07578945e0ee8fb61f3?card=tra-16064)
- [Cahier de recette Entreposage provisoire](https://favro.com/organization/ab14a4f0460a99a9d64d4945/2c84e07578945e0ee8fb61f3?card=tra-16067)


Diff:
diff --git a/back/src/forms/__tests__/form-converter.integration.ts b/back/src/forms/__tests__/form-converter.integration.ts
index 45c949a870..25ead4e017 100644
--- a/back/src/forms/__tests__/form-converter.integration.ts
+++ b/back/src/forms/__tests__/form-converter.integration.ts
@@ -203,7 +203,8 @@ describe("expandFormFromDb", () => {
         wasteAcceptationStatus: null,
         wasteRefusalReason: null,
         receivedAt: null,
-        receivedBy: null
+        receivedBy: null,
+        signedAt: null
       },
       destination: {
         cap: "CAP",
diff --git a/back/src/forms/converter.ts b/back/src/forms/converter.ts
index d704c4ae18..d3ac504799 100644
--- a/back/src/forms/converter.ts
+++ b/back/src/forms/converter.ts
@@ -855,7 +855,8 @@ export function expandFormFromDb(
             wasteAcceptationStatus: form.wasteAcceptationStatus,
             wasteRefusalReason: form.wasteRefusalReason,
             receivedAt: processDate(form.receivedAt),
-            receivedBy: form.receivedBy
+            receivedBy: form.receivedBy,
+            signedAt: form.signedAt
           },
           transporter: forwardedInTransporter
             ? expandTransporterFromDb(forwardedInTransporter)
diff --git a/back/src/forms/pdf/components/BsddPdf.tsx b/back/src/forms/pdf/components/BsddPdf.tsx
index d1220f8bc6..2428f59705 100644
--- a/back/src/forms/pdf/components/BsddPdf.tsx
+++ b/back/src/forms/pdf/components/BsddPdf.tsx
@@ -983,7 +983,9 @@ export function BsddPdf({
                 </p>
                 <AcceptationFields
                   {...form.temporaryStorageDetail?.temporaryStorer}
-                  signedAt={form.signedAt} //check this
+                  signedAt={
+                    form.temporaryStorageDetail?.temporaryStorer?.signedAt
+                  }
                 />
                 <p>
                   Nom :{" "}
diff --git a/back/src/forms/resolvers/mutations/__tests__/signTransportForm.integration.ts b/back/src/forms/resolvers/mutations/__tests__/signTransportForm.integration.ts
index 9306b7d718..ab921b8573 100644
--- a/back/src/forms/resolvers/mutations/__tests__/signTransportForm.integration.ts
+++ b/back/src/forms/resolvers/mutations/__tests__/signTransportForm.integration.ts
@@ -444,6 +444,7 @@ describe("signTransportForm", () => {
   it("should sign transport from temporary storage", async () => {
     const temporaryStorage = await userWithCompanyFactory("ADMIN");
     const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
     const emittedAt = new Date("2018-12-11T00:00:00.000Z");
     const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
 
@@ -499,6 +500,7 @@ describe("signTransportForm", () => {
   it("should sign transport from temporary storage when plates are valid", async () => {
     const temporaryStorage = await userWithCompanyFactory("ADMIN");
     const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
     const emittedAt = new Date("2018-12-11T00:00:00.000Z");
     const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
 
@@ -555,6 +557,7 @@ describe("signTransportForm", () => {
   it("should throw an error when signing transport from temporary storage and plates are invalid", async () => {
     const temporaryStorage = await userWithCompanyFactory("ADMIN");
     const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
     const emittedAt = new Date("2018-12-11T00:00:00.000Z");
     const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
 
@@ -604,6 +607,7 @@ describe("signTransportForm", () => {
   it("should sign transport from temporary storage with security code", async () => {
     const temporaryStorage = await userWithCompanyFactory("ADMIN");
     const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
     const emittedAt = new Date("2018-12-11T00:00:00.000Z");
     const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
 
@@ -701,6 +705,115 @@ describe("signTransportForm", () => {
     expect(errors).not.toBeUndefined();
   });
 
+  it("should throw an error when signing transport from temporary storage if plates are not provided and mode is ROAD", async () => {
+    const temporaryStorage = await userWithCompanyFactory("ADMIN");
+    const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
+    const emittedAt = new Date("2018-12-11T00:00:00.000Z");
+    const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
+    const form = await formWithTempStorageFactory({
+      ownerId: temporaryStorage.user.id,
+      opt: {
+        status: "SIGNED_BY_TEMP_STORER",
+        recipientCompanySiret: temporaryStorage.company.siret,
+        recipientCompanyName: temporaryStorage.company.name
+      },
+      forwardedInOpts: {
+        emittedAt: emittedAt,
+        emittedBy: temporaryStorage.user.name,
+        transporters: {
+          create: {
+            transporterCompanySiret: transporter.company.siret,
+            transporterCompanyName: transporter.company.name,
+            transporterTransportMode: "ROAD",
+            transporterNumberPlate: null,
+            number: 1
+          }
+        }
+      }
+    });
+
+    const { mutate } = makeClient(transporter.user);
+    const { errors } = await mutate<
+      Pick<Mutation, "signTransportForm">,
+      MutationSignTransportFormArgs
+    >(SIGN_TRANSPORT_FORM, {
+      variables: {
+        id: form.id,
+        input: {
+          takenOverAt: takenOverAt.toISOString() as unknown as Date,
+          takenOverBy: transporter.user.name,
+          transporterNumberPlate: null
+        }
+      }
+    });
+
+    expect(errors).toEqual([
+      expect.objectContaining({
+        message: "La plaque d'immatriculation est requise"
+      })
+    ]);
+  });
+
+  it("should sign transport from temporary storage if plates are not provided and mode is not ROAD", async () => {
+    const temporaryStorage = await userWithCompanyFactory("ADMIN");
+    const transporter = await userWithCompanyFactory("ADMIN");
+    await transporterReceiptFactory({ company: transporter.company });
+    const emittedAt = new Date("2018-12-11T00:00:00.000Z");
+    const takenOverAt = new Date("2018-12-12T00:00:00.000Z");
+    const form = await formWithTempStorageFactory({
+      ownerId: temporaryStorage.user.id,
+      opt: {
+        status: "SIGNED_BY_TEMP_STORER",
+        recipientCompanySiret: temporaryStorage.company.siret,
+        recipientCompanyName: temporaryStorage.company.name
+      },
+      forwardedInOpts: {
+        emittedAt: emittedAt,
+        emittedBy: temporaryStorage.user.name,
+        transporters: {
+          create: {
+            transporterCompanySiret: transporter.company.siret,
+            transporterCompanyName: transporter.company.name,
+            transporterTransportMode: "SEA",
+            transporterNumberPlate: null,
+            number: 1
+          }
+        }
+      }
+    });
+
+    const { mutate } = makeClient(transporter.user);
+    const { data, errors } = await mutate<
+      Pick<Mutation, "signTransportForm">,
+      MutationSignTransportFormArgs
+    >(SIGN_TRANSPORT_FORM, {
+      variables: {
+        id: form.id,
+        input: {
+          takenOverAt: takenOverAt.toISOString() as unknown as Date,
+          takenOverBy: transporter.user.name,
+          transporterNumberPlate: null
+        }
+      }
+    });
+
+    expect(errors).toBeUndefined();
+
+    expect(data.signTransportForm).toEqual(
+      expect.objectContaining({
+        status: "RESENT",
+        temporaryStorageDetail: expect.objectContaining({
+          signedAt: takenOverAt.toISOString(),
+          signedBy: temporaryStorage.user.name,
+
+          takenOverAt: takenOverAt.toISOString(),
+          takenOverBy: transporter.user.name
+        })
+      })
+    );
+  });
+
   it("should throw an error if signed by an intermediary", async () => {
     const intermediary = await userWithCompanyFactory("ADMIN");
     const emitter = await userWithCompanyFactory("ADMIN");
diff --git a/back/src/forms/resolvers/mutations/signTransportForm.ts b/back/src/forms/resolvers/mutations/signTransportForm.ts
index 75e37314e0..55f951b10f 100644
--- a/back/src/forms/resolvers/mutations/signTransportForm.ts
+++ b/back/src/forms/resolvers/mutations/signTransportForm.ts
@@ -21,7 +21,7 @@ import { getFormRepository } from "../../repository";
 import { getTransporterCompanyOrgId } from "@td/constants";
 import { runInTransaction } from "../../../common/repository/helper";
 import { sumPackagingInfos } from "../../repository/helper";
-import { validateBeforeTransport, plateSchemaFn } from "../../validation";
+import { validateBeforeTransport, transporterSchemaFn } from "../../validation";
 import { Permission } from "../../../permissions";
 import { enqueueUpdatedBsdToIndex } from "../../../queue/producers/elastic";
 import { recipifyFormInput } from "../../recipify";
@@ -333,12 +333,30 @@ const signatures: Partial<
     const existingFullForm = await getFullForm(existingForm);
 
     const transporter = getFirstTransporterSync(existingFullForm.forwardedIn!);
+    const signingTransporterOrgId = getTransporterCompanyOrgId(transporter)!;
     await checkCanSignFor(
-      getTransporterCompanyOrgId(transporter)!,
+      signingTransporterOrgId,
       user,
       Permission.BsdCanSignTransport,
       args.securityCode
     );
+    const transporterNumberPlate =
+      args.input.transporterNumberPlate ?? transporter?.transporterNumberPlate;
+
+    const transporterTransportMode =
+      args.input.transporterTransportMode ??
+      transporter?.transporterTransportMode;
+
+    const transporterSchema = transporterSchemaFn({ signingTransporterOrgId });
+
+    const receiptFields = await getFormReceiptField(transporter);
+
+    await transporterSchema.validate({
+      ...transporter,
+      transporterNumberPlate,
+      transporterTransportMode,
+      ...receiptFields
+    });
 
     const formUpdateInput: Prisma.FormUpdateInput = {
       forwardedIn: {
@@ -349,9 +367,9 @@ const signatures: Partial<
           transporters: {
             updateMany: {
               data: {
-                transporterNumberPlate:
-                  args.input.transporterNumberPlate ??
-                  transporter?.transporterNumberPlate
+                transporterNumberPlate,
+                transporterTransportMode,
+                ...receiptFields
               },
               where: { number: 1 }
             }
@@ -365,17 +383,6 @@ const signatures: Partial<
       }
     };
 
-    await plateSchemaFn().validate(
-      {
-        transporterNumberPlate:
-          args.input.transporterNumberPlate ??
-          transporter?.transporterNumberPlate
-      },
-      {
-        abortEarly: false
-      }
-    );
-
     const updatedForm = await getFormRepository(user).update(
       { id: existingFullForm.id, status: existingFullForm.status },
       {
diff --git a/back/src/forms/typeDefs/bsdd.objects.graphql b/back/src/forms/typeDefs/bsdd.objects.graphql
index 7ba104b1e7..5389c1e501 100644
--- a/back/src/forms/typeDefs/bsdd.objects.graphql
+++ b/back/src/forms/typeDefs/bsdd.objects.graphql
@@ -376,9 +376,10 @@ type TemporaryStorer {
   quantityAccepted: Float
   wasteAcceptationStatus: WasteAcceptationStatus
   wasteRefusalReason: String
-
   receivedAt: DateTime
   receivedBy: String
+  "Date à laquelle le déchet a été accepté ou refusé (case 13)"
+  signedAt: DateTime
 }
 
 "Destination finale après entreposage provisoire ou reconditionement"
diff --git a/back/src/forms/validation.ts b/back/src/forms/validation.ts
index 25231ce898..e6b1faa32b 100644
--- a/back/src/forms/validation.ts
+++ b/back/src/forms/validation.ts
@@ -1069,19 +1069,6 @@ export const validatePlates = (transporterNumberPlate: string) => {
   return true;
 };
 
-// Schema dedicated to validate plates on signTransportForm SIGNED_BY_TEMP_STORER
-export const plateSchemaFn = () =>
-  yup.object({
-    transporterNumberPlate: yup
-      .string()
-      .nullable()
-      .test(transporterNumberPlate => {
-        return transporterNumberPlate
-          ? validatePlates(transporterNumberPlate)
-          : true;
-      })
-  });
-
 export const transporterSchemaFn: FactorySchemaOf<
   Pick<FormValidationContext, "signingTransporterOrgId">,
   Transporter
diff --git a/front/src/Apps/Dashboard/dashboardServices.test.ts b/front/src/Apps/Dashboard/dashboardServices.test.ts
index c152bae396..d64fdf207f 100644
--- a/front/src/Apps/Dashboard/dashboardServices.test.ts
+++ b/front/src/Apps/Dashboard/dashboardServices.test.ts
@@ -1029,7 +1029,7 @@ describe("dashboardServices", () => {
           }
         },
         permissions,
-        "actTab"
+        "toCollectTab"
       );
       expect(result).toEqual(SIGNER);
     });
diff --git a/front/src/Apps/Dashboard/dashboardServices.ts b/front/src/Apps/Dashboard/dashboardServices.ts
index 1e2adae637..059459527c 100644
--- a/front/src/Apps/Dashboard/dashboardServices.ts
+++ b/front/src/Apps/Dashboard/dashboardServices.ts
@@ -933,7 +933,7 @@ export const getSignByProducerBtnLabel = (
     isSameSiretTransporter(currentSiret, bsd) &&
     permissions.includes(UserPermission.BsdCanSignTransport)
   ) {
-    if (isBsdd(bsd.type)) {
+    if (isBsdd(bsd.type) && isToCollectTab) {
       return SIGNER;
     }
     if (isBsdasri(bsd.type)) {
diff --git a/front/src/Apps/Forms/Components/PackagingList/PackagingForm.tsx b/front/src/Apps/Forms/Components/PackagingList/PackagingForm.tsx
index b5382b9c3e..867a9b4457 100644
--- a/front/src/Apps/Forms/Components/PackagingList/PackagingForm.tsx
+++ b/front/src/Apps/Forms/Components/PackagingList/PackagingForm.tsx
@@ -71,9 +71,16 @@ function PackagingForm({
     packagingsLength > 1
       ? // Un conditionnement en citerne ou benne exclut le mélange avec
         // tout autre type de conditionnement
-        packagingTypeOptions.filter(
-          o => o.value !== Packagings.Citerne && o.value !== Packagings.Benne
-        )
+        packagingTypeOptions.filter(o => {
+          return (
+            // tra-16064 - cas particulier si les conditionnements ont été calculés
+            // automatiquement à partir de la liste des annexes 2, on peut se retrouver
+            // avec des conditionnements incohérents et on veut quand même pouvoir afficher
+            // Citerne ou Benne dans la liste des options disponibles.
+            o.value === packaging.type ||
+            (o.value !== Packagings.Citerne && o.value !== Packagings.Benne)
+          );
+        })
       : packagingTypeOptions;
 
   return (
diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormJourneySummary.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormJourneySummary.tsx
index ed883a6a01..131629cbb5 100644
--- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormJourneySummary.tsx
+++ b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormJourneySummary.tsx
@@ -94,7 +94,11 @@ export function FormJourneySummary({ form }: FormJourneySummaryProps) {
             variant={
               form.temporaryStorageDetail.emittedAt
                 ? "complete"
-                : (form.transporters ?? []).every(t => Boolean(t.takenOverAt))
+                : (form.isDirectSupply && form.emittedAt) ||
+                  (!form.isDirectSupply &&
+                    (form.transporters ?? []).every(t =>
+                      Boolean(t.takenOverAt)
+                    ))
                 ? // Actif si tous les transporteurs ont signé, sinon en attente
                   "active"
                 : "incomplete"
diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormWasteEmissionSummary.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormWasteEmissionSummary.tsx
index 3395fde93a..6c1bcaf576 100644
--- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormWasteEmissionSummary.tsx
+++ b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormWasteEmissionSummary.tsx
@@ -75,6 +75,12 @@ export function FormWasteEmissionSummary({
         .filter((name, index, fields) => fields.indexOf(name) === index)
     );
 
+  // On ne doit pas pouvoir éditer la liste des contenants ou la plaque immat
+  // lors d'un acheminement direct par pipeline ou convoyeur sauf s'il s'agit
+  // de la signature du TTR après entreposage provisoire
+  const isDirectSupply =
+    form.temporaryStorageDetail && form.emittedAt ? false : form.isDirectSupply;
+
   return (
     <>
       <DataList>
@@ -104,7 +110,7 @@ export function FormWasteEmissionSummary({
             </button>
           </DataListDescription>
         </DataListItem>
-        {!form.isDirectSupply && (
+        {!isDirectSupply && (
           <DataListItem>
             <DataListTerm>Contenant(s)</DataListTerm>
             <DataListDescription>
@@ -157,22 +163,23 @@ export function FormWasteEmissionSummary({
             </DataListDescription>
           </DataListItem>
         )}
-        {form.emitter?.type !== EmitterType.Appendix1Producer && (
-          <DataListItem>
-            <DataListTerm>Plaque d'immatriculation</DataListTerm>
-            <DataListDescription>
-              {values.transporterNumberPlate}
+        {form.emitter?.type !== EmitterType.Appendix1Producer &&
+          !isDirectSupply && (
+            <DataListItem>
+              <DataListTerm>Plaque d'immatriculation</DataListTerm>
+              <DataListDescription>
+                {values.transporterNumberPlate}
 
-              <button
-                type="button"
-                onClick={() => addField("transporterNumberPlate")}
-                className="tw-ml-2"
-              >
-                <IconPaperWrite color="blue" />
-              </button>
-            </DataListDescription>
-          </DataListItem>
-        )}
+                <button
+                  type="button"
+                  onClick={() => addField("transporterNumberPlate")}
+                  className="tw-ml-2"
+                >
+                  <IconPaperWrite color="blue" />
+                </button>
+              </DataListDescription>
+            </DataListItem>
+          )}
       </DataList>
       {fields.length > 0 && (
         <div className="tw-mb-4">
diff --git a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/SignEmissionFormModalContent.tsx b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/SignEmissionFormModalContent.tsx
index 623573139e..addb61d201 100644
--- a/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/SignEmissionFormModalContent.tsx
+++ b/front/src/dashboard/components/BSDList/BSDD/WorkflowAction/SignEmissionFormModalContent.tsx
@@ -122,6 +122,14 @@ function SignEmissionFormModalContent({
     );
   }
   const form = data?.form;
+
+  const initialTransporterNumberPlate =
+    !!form.temporaryStorageDetail && !!form.emittedAt
+      ? // Il s'agit de la signature de l'émetteur après
+        // entreposage provisoire
+        form?.temporaryStorageDetail.transporter?.numberPlate
+      : form.transporter?.numberPlate;
+
   const initialValues = {
     emittedAt: TODAY.toISOString(),
     emittedBy: "",
@@ -131,7 +139,7 @@ function SignEmissionFormModalContent({
     packagingInfos: form.wasteDetails?.packagingInfos ?? [],
     quantity: form.wasteDetails?.quantity ?? 0,
     onuCode: form.wasteDetails?.onuCode ?? "",
-    transporterNumberPlate: form.transporter?.numberPlate ?? ""
+    transporterNumberPlate: initialTransporterNumberPlate ?? ""
   };
 
   const handlesubmit = async values => {
diff --git a/front/src/dashboard/detail/bsdd/BSDDetailContent.tsx b/front/src/dashboard/detail/bsdd/BSDDetailContent.tsx
index 65ede844b3..01c62a061c 100644
--- a/front/src/dashboard/detail/bsdd/BSDDetailContent.tsx
+++ b/front/src/dashboard/detail/bsdd/BSDDetailContent.tsx
@@ -910,14 +910,15 @@ export default function BSDDetailContent({
                 <span className={styles.detailTabCaption}>Courtier</span>
               </Tab>
             )}
-            {form.transporters?.map((_, idx) => (
-              <Tab className={styles.detailTab} key={idx}>
-                <IconWarehouseDelivery size="25px" />
-                <span className={styles.detailTabCaption}>
-                  {isMultiModal ? `Transp. n° ${idx + 1}` : "Transporteur"}
-                </span>
-              </Tab>
-            ))}
+            {!form.isDirectSupply &&
+              form.transporters?.map((_, idx) => (
+                <Tab className={styles.detailTab} key={idx}>
+                  <IconWarehouseDelivery size="25px" />
+                  <span className={styles.detailTabCaption}>
+                    {isMultiModal ? `Transp. n° ${idx + 1}` : "Transporteur"}
+                  </span>
+                </Tab>
+              ))}
             {hasTempStorage && (
               <Tab className={styles.detailTab}>
                 <IconWarehouseStorage size="25px" />
@@ -1019,7 +1020,7 @@ export default function BSDDetailContent({
               </TabPanel>
             )}
             {/* Transporter tab panel */}
-            {!form.isDirectSupply ? (
+            {!form.isDirectSupply &&
               (form.transporters ?? []).map((transporter, idx) => (
                 <TabPanel className={styles.detailTabPanel}>
                   <div className={`${styles.detailGrid} `}>
@@ -1078,17 +1079,7 @@ export default function BSDDetailContent({
                     />
                   </div>
                 </TabPanel>
-              ))
-            ) : (
-              <TabPanel className={styles.detailTabPanel}>
-                <div className={`${styles.detailGrid} `}>
-                  <DetailRow
-                    value="Acheminement direct par pipeline ou convoyeur"
-                    label="Transport"
-                  />
-                </div>
-              </TabPanel>
-            )}
+              ))}
 
             {/* Temp storage tab panel */}
             {hasTempStorage && (


Reviews:
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:55:03Z
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:56:50Z
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:57:39Z
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:57:57Z
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:59:13Z
user: login: benoitguigal
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T12:59:48Z
user: login: providenz
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-06T15:09:45Z
user: login: GaelFerrand
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T16:08:02Z

Review comments:
diff_hunk: @@ -983,7 +983,9 @@ export function BsddPdf({
                 </p>
                 <AcceptationFields
                   {...form.temporaryStorageDetail?.temporaryStorer}
-                  signedAt={form.signedAt} //check this
+                  signedAt={
+                    form.temporaryStorageDetail?.temporaryStorer?.signedAt
path: back/src/forms/pdf/components/BsddPdf.tsx
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 54 43](https://github.com/user-attachments/assets/2b1c3420-71bb-4bba-a737-61b54d3b952e)

![image(1)](https://github.com/user-attachments/assets/ef83433d-cd2a-4e5d-b7fe-903b67dba3ca)

created_at: 2025-03-06T12:55:03Z
author_association: MEMBER
diff_hunk: @@ -933,7 +933,7 @@ export const getSignByProducerBtnLabel = (
     isSameSiretTransporter(currentSiret, bsd) &&
     permissions.includes(UserPermission.BsdCanSignTransport)
   ) {
-    if (isBsdd(bsd.type)) {
+    if (isBsdd(bsd.type) && isToCollectTab) {
path: front/src/Apps/Dashboard/dashboardServices.ts
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 56 08](https://github.com/user-attachments/assets/bb1beb30-5a55-412a-92f2-51c56dbfa1f7)

<img width="1167" alt="image(2)" src="https://github.com/user-attachments/assets/73d19ce2-091f-4a0a-90e4-99d889b64798" />

created_at: 2025-03-06T12:56:50Z
author_association: MEMBER
diff_hunk: @@ -122,6 +122,14 @@ function SignEmissionFormModalContent({
     );
   }
   const form = data?.form;
+
+  const initialTransporterNumberPlate =
+    !!form.temporaryStorageDetail && !!form.emittedAt
+      ? // Il s'agit de la signature de l'émetteur après
+        // entreposage provisoire
+        form?.temporaryStorageDetail.transporter?.numberPlate
path: front/src/dashboard/components/BSDList/BSDD/WorkflowAction/SignEmissionFormModalContent.tsx
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 57 09](https://github.com/user-attachments/assets/c1a5e269-5cb5-4568-babc-da61d9786f5b)

created_at: 2025-03-06T12:57:39Z
author_association: MEMBER
diff_hunk: @@ -333,12 +333,22 @@ const signatures: Partial<
     const existingFullForm = await getFullForm(existingForm);
 
     const transporter = getFirstTransporterSync(existingFullForm.forwardedIn!);
+    const signingTransporterOrgId = getTransporterCompanyOrgId(transporter)!;
     await checkCanSignFor(
-      getTransporterCompanyOrgId(transporter)!,
+      signingTransporterOrgId,
       user,
       Permission.BsdCanSignTransport,
       args.securityCode
     );
+    const transporterNumberPlate =
+      args.input.transporterNumberPlate ?? transporter?.transporterNumberPlate;
+
+    const transporterSchema = transporterSchemaFn({ signingTransporterOrgId });
+
+    await transporterSchema.validate({
path: back/src/forms/resolvers/mutations/signTransportForm.ts
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 57 36](https://github.com/user-attachments/assets/dd628c2f-23f9-4ec0-89e2-0ba495f6dea1)

created_at: 2025-03-06T12:57:57Z
author_association: MEMBER
diff_hunk: @@ -75,6 +75,12 @@ export function FormWasteEmissionSummary({
         .filter((name, index, fields) => fields.indexOf(name) === index)
     );
 
+  // On ne doit pas pouvoir éditer la liste des contenants ou la plaque immat
+  // lors d'un acheminement direct par pipeline ou convoyeur sauf s'il s'agit
+  // de la signature du TTR après entreposage provisoire
+  const isDirectSupply =
path: front/src/dashboard/components/BSDList/BSDD/WorkflowAction/FormWasteEmissionSummary.tsx
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 58 38](https://github.com/user-attachments/assets/bc369eaf-f834-4b32-9bd7-69341759fa5c)

<img width="1409" alt="image(3)" src="https://github.com/user-attachments/assets/1e20e83e-c481-4db3-a590-b55b8c1571c3" />

created_at: 2025-03-06T12:59:12Z
author_association: MEMBER
diff_hunk: @@ -71,9 +71,16 @@ function PackagingForm({
     packagingsLength > 1
       ? // Un conditionnement en citerne ou benne exclut le mélange avec
         // tout autre type de conditionnement
-        packagingTypeOptions.filter(
-          o => o.value !== Packagings.Citerne && o.value !== Packagings.Benne
-        )
+        packagingTypeOptions.filter(o => {
+          return (
+            // tra-16064 - cas particulier si les conditionnements ont été calculés
path: front/src/Apps/Forms/Components/PackagingList/PackagingForm.tsx
user: login: benoitguigal
body: ![Capture d’écran 2025-03-06 à 13 59 32](https://github.com/user-attachments/assets/a538027c-a6ff-44d4-8002-15c625886ea5)

created_at: 2025-03-06T12:59:47Z
author_association: MEMBER

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-03-07T14:05:49Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=MTES-MCT_trackdechets&pullRequest=4014) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=MTES-MCT_trackdechets&pullRequest=4014&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=MTES-MCT_trackdechets&pullRequest=4014&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=MTES-MCT_trackdechets&pullRequest=4014&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=MTES-MCT_trackdechets&pullRequest=4014&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=MTES-MCT_trackdechets&pullRequest=4014&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=MTES-MCT_trackdechets&pullRequest=4014)


author_association: NONE