How Frasers DORs Work

Created Jun 17, 2026 public

A DOR (Denial of Receipt) is the form a customer signs to confirm they never received their goods. The courier (DPD) needs it before they'll pay a lost/disputed claim.

The key thing to understand: we don't email the customer a document to print and sign. We email them a link to an online form. They tick which items were missing and draw a signature in their browser. Nothing comes back by email — it comes back as data in our system.

Two programs do the work, and they only talk to each other through the database:

A small table, FrasersGroup_DOR, tracks each DOR with a Status number that ticks up as it moves through the journey. Follow the number, follow the flow.

The Journey at a Glance

Step 1 — We Send Out the Link (Status 1 → 2)

Handled by the console method CheckForEmailingDORs()FrasersGroup.ClaimManager/Automation.cs:4414.

  1. Find every FrasersGroup_DOR row at Status == 1 (just created) for the Frasers client. — Automation.cs:4424
  2. Look up the customer's Freshdesk ticket from the order data. — Automation.cs:4439
  3. Send an HTML email as a reply on that Freshdesk ticket, so it reaches the customer in their existing support thread, from the Frasers support address. — Automation.cs:4482
  4. The email body is just a link — Click here to access the form{PortalBaseUrl}/dor/{token}. — Automation.cs:4457
  5. Flip the row to Status = 2 (Sent), move the claim to "DOR Sent", and set the Freshdesk ticket to "Waiting on DOR". — Automation.cs:4520

The link's token is a signed code (HMAC-SHA256 of the DOR id + a secret, then Base62-encoded) — built in SDK/Objects/Frasers Group/FGEmailLink.cs. It can't be guessed or forged. The link itself is the password.

Step 2 — The Customer Signs It Online (Status 2 → 3)

This happens on the Portal website, not the console.

The customer clicks the link and lands on the form at /dor/{token} (DORPage). They tick which products were missing, draw a signature on a signature pad, and submit.

Their browser posts to /dor/{dorId}/submitDORController.Submitfrontend/Claimit.Portal/DOR/DORController.cs:27. The endpoint is public ([AllowAnonymous]) — the signed token is the only key needed. It then:

At this point we have the signature, but there is still no DOR PDF and no file attached to the claim yet.

Step 3 — We Build the Real DOR (Status 3 → 4)

Back on the console, method CheckForReturnedSignedDORs()FrasersGroup.ClaimManager/Automation.cs:4554.

  1. Find every row at Status == 3.
  2. Build the DOR PDF: customer name, tracking number, declared value, the pasted signature image, and the date. — Automation.cs:4636
  3. Attach the PDF to the Freshdesk ticket as a private note. — Automation.cs:4720
  4. Write the file against the claim — a FileData row (FileDataType = DOR, OwnerId = claimId) plus the PDF in blob storage. This is the record everything downstream reads.Automation.cs:4735
  5. Set Status = 4 (PDF created) and move the claim to DORReceived. — Automation.cs:4880

The DPD Temporal workflow then sees the claim is signed (Status >= 4) and submits it to MyDPD with the DOR attached (it slots into the Proof-of-Cost upload).

The Status Numbers

Status Meaning Set by
1 Created — waiting to be emailed Claim creation
2 Sent — link emailed, waiting on customer CheckForEmailingDORs (Automation.cs:4520)
3 Signed — customer completed the online form DORController.Submit (DORController.cs:78)
4 PDF created — DOR built + saved against the claim CheckForReturnedSignedDORs (Automation.cs:4880)
5 Expired — customer never signed in time CheckForNonReturnedDORs

Why This Matters If DORs Aren't Going Out

Both the send and the PDF build live in the one console app, FrasersGroup.ClaimManager. Its Program.cs runs the methods top-to-bottom once and then exits — there is no built-in loop or scheduler. So:

Fastest health check: count FrasersGroup_DOR rows stuck at Status 1 (never emailed) or Status 3 (signed but no PDF). Either pile sitting there means the console isn't doing its job.

Code Path Reference

What Where
Send the link (Status 1 → 2) FrasersGroup.ClaimManager/Automation.cs:4414 (CheckForEmailingDORs)
Signed link / token generation SDK/Objects/Frasers Group/FGEmailLink.cs
Signing form submit (Status 2 → 3) frontend/Claimit.Portal/DOR/DORController.cs:27 (Submit)
Signature stored to blob DORController.cs:68 (dor/{id}/signature.png)
Build PDF + save file (Status 3 → 4) FrasersGroup.ClaimManager/Automation.cs:4554 (CheckForReturnedSignedDORs)
The file written against the claim Automation.cs:4735 (FileData, FileDataType = DOR)
State table model SDK/Objects/Frasers Group/FrasersGroupDOR.cs
Console run order FrasersGroup.ClaimManager/Program.cs