Carrier Complaints Built
A carrier complaint is a formal claim against a delivery carrier — India Post or a courier — for a package that was lost, damaged, delayed, wrongly delivered or tampered with, tracked from the moment you raise it through to the money the carrier actually pays back.
What a carrier complaint is
Despatched packages sometimes go wrong in the carrier's hands, not AIR's. A carrier complaint gives you one record per incident with the carrier, even when several packages are involved: it groups one or more items — each item one package, one type of problem (lost, damaged, delayed, wrong delivery, tampered, other), a description and a claim amount — under a single header for that carrier. Two totals travel with the header as you go: the total claim amount you are asking the carrier to make good, and the resolution amount the carrier actually agrees to pay once the complaint is settled. The ratio between the two — resolution ÷ claim, shown as a percentage — is the complaint's recovery rate, a quick read on how much of what you claimed was actually recovered.
Every complaint carries the whole trail: which packages were affected, what kind of problem each one was, what you claimed, what the carrier's own reference for the case was, what they paid, and any notes recorded along the way.
Where to find it & who can see it
Open Despatch › Carrier Complaints in the left navigation.
The state machine
A complaint moves through five states, one deliberate step at a time. Every transition is a button on the list, gated by state and by carrier_complaint.manage — nothing advances automatically.
| State | Meaning |
|---|---|
| Draft | Just raised. Items and claim amounts are recorded; nothing has been sent to the carrier yet. |
| Submitted | Submit has run — the complaint has been sent to the carrier. |
| Acknowledged | Acknowledge has run — the carrier has confirmed receipt, and the carrier's own reference/ticket for the case (if given) is on file. |
| Resolved | Resolve has run — the carrier's decision is recorded: how much they are paying and any resolution notes. This is what the recovery percentage is calculated from. |
| Closed | Close has run — AIR has accepted the resolution. The complaint's final state; no further action is offered. |
Filing a complaint
Select New carrier complaint from the list. This needs carrier_complaint.create. Creation is routed through CarrierComplaintService::createDraft() rather than a plain Eloquent save, so the reference number, the item rows, the two computed totals and the creating user are all recorded consistently.
- Fill in the complaint header
Choose the carrier the complaint is against, the complaint date (defaults to today) and any notes.
Field Type Required Notes Carrier Select (searchable) Yes The delivery carrier the complaint is against — see Warehouses & Carriers. Complaint date Date picker Yes Defaults to today. Notes Textarea No Free text, full width. - Add one or more package items
Use Add package in the items repeater to add a row for each affected package. At least one item is required.
Field Type Required Notes Package Select (searchable) Yes The despatched package this line is about. Listed by package number, most recent 50 shown before you search. Complaint type Select (searchable) Yes One of the active complaint types (Lost, Damaged, Delayed, Wrong delivery, Tampered, Other, or any type an administrator has added). Claim amount Number, ₹ Yes 2 decimal places, minimum 0. What you are claiming for this package. Description Textarea No Free text detail for this specific package. - Save
Create raises the complaint in the Draft state with a generated reference such as
CMP-2026-00001(year-scoped, zero-padded, sequential). The service computes total packages (a count of the items) and total claim amount (the sum of every item's claim amount) itself — there is nothing to fill in for either; they simply reflect whatever rows you added.
The lifecycle actions
- Submit Draft → Submitted carrier_complaint.manage Confirmation required
Shown on a Draft complaint. A confirmation dialog is all it asks for — no form. Confirming sends the complaint to the carrier and moves it straight to Submitted; nothing else on the record changes.
- Acknowledge Submitted → Acknowledged carrier_complaint.manage
Shown on a Submitted complaint. Opens a small form for the carrier's own reference to the case.
Field Type Required Notes Carrier reference Text No Max 100 characters. The carrier's own ticket/reference number for the case, if they gave one. Submitting the form is the confirmation — the complaint moves to Acknowledged and the carrier reference (or blank, if none was given) is saved.
- Resolve Acknowledged → Resolved carrier_complaint.manage
Shown on an Acknowledged complaint. Opens a form to record what the carrier actually agreed to pay.
Field Type Required Notes Resolution amount Number, ₹ Yes 2 decimal places, minimum 0. What the carrier is paying back. This is what drives the recovery percentage shown on the list. Resolution notes Textarea No Free text — how the carrier explained or justified the amount. Submitting the form moves the complaint to Resolved and saves both fields against the complaint header.
- Close Resolved → Closed carrier_complaint.manage Confirmation required
Shown on a Resolved complaint. A confirmation dialog is all it asks for — no form. Confirming records that AIR accepts the carrier's resolution and moves the complaint to Closed, its final state. No action is offered on a closed complaint.
Columns
| Column | Shows |
|---|---|
reference | The complaint's identifying number, shown as a badge. Searchable and sortable. |
| Carrier | carrier.name. Searchable. |
| State | A coloured badge — see the state machine above for the colour key. |
| Pkgs | total_packages — a count of the complaint's items, computed automatically on creation. |
| Claim | total_claim_amount in ₹ — the sum of every item's claim amount, computed automatically on creation. |
| Resolution | resolution_amount in ₹ — zero until Resolve sets it. |
| Recovery | Resolution amount ÷ total claim amount, as a rounded percentage — e.g. a ₹4,500 resolution against a ₹5,000 claim shows 90%. Shown as an em dash ("—") until the claim amount is greater than zero (in practice, before Resolve has run, since resolution amount starts at zero). |
complaint_date | Date the complaint was raised. Sortable. |
created_at | Date and time created. Sortable, hidden by default. |
Filters
Select Filters to open two drop-downs: State (all five CarrierComplaintState values) and Carrier (a select over every delivery carrier). The search box matches on reference and carrier name.
The View page
Selecting a complaint's reference opens its view page. The top section is read-only: reference, carrier, state, complaint date, carrier reference, total packages, total claim amount, resolution amount, resolution notes and notes.
Below it, an Items tab lists every package on the complaint, also read-only — items are only ever created together, through New carrier complaint; there is no way to add, edit or remove an item after the complaint is raised.
| Column | Shows |
|---|---|
| Package | package.package_number. |
| Type | type.name — the item's complaint type. |
| Claim amount | claim_amount in ₹. |
| Description | The item's free-text description, or an em dash ("—") if none was given. |
Complaint types
Open Despatch › Carrier Complaint Types — the lookup master that every complaint item's Complaint type field is chosen from. It's a small, straightforward CRUD list: viewing needs carrier_complaint.view; creating, editing and deleting a type all need carrier_complaint.manage.
Six types are pre-seeded and cannot be deleted by the seeder itself (though an administrator can still remove or deactivate any of them by hand):
| Code | Name | Auto-assign | SMS | |
|---|---|---|---|---|
lost | Lost in Transit | Yes | Yes | No |
damaged | Damaged | Yes | Yes | No |
delayed | Delayed | No | No | No |
wrong_delivery | Wrong Delivery | Yes | Yes | Yes |
tampered | Tampered | Yes | Yes | No |
other | Other | No | No | No |
Fields
| Field | Type | Required | Notes |
|---|---|---|---|
code | Text | Yes | Max 50 characters. A short machine-readable identifier, e.g. lost. |
name | Text | Yes | Max 255 characters. The label shown in the complaint type select. |
| Auto-assign | Toggle | No | Off by default. |
| Auto-assign role | Select (searchable) | No | The role a complaint of this type would be routed to. |
| Toggle | No | Off by default. | |
| SMS | Toggle | No | Off by default. |
| Active | Toggle | No | Defaults on. Only active types are offered in a complaint's item repeater. |
Every complaint type carries an Auto-assign toggle with an Auto-assign role, plus Email and SMS toggles, and you can edit all of them today. Nothing in the console currently reads these flags to route a newly-raised complaint to a role automatically or to send an email or SMS notification — raising, acknowledging, resolving and closing a complaint are all manual actions regardless of how a type's flags are set. The fields exist so this behaviour can be switched on later without a schema change; for now, treat them as configuration held in reserve.
Related pages
See Warehouses & Carriers for the Delivery Carrier master every complaint is raised against, Packages for the despatched packages a complaint's items refer to, and Discounts, Refunds & Charges for how a carrier's resolution amount relates to (but is recorded separately from) money moving on a customer's account.