On a serial-tracked product each physical unit is a row of its own, with its own code, cost, acquisition date and status. That is what lets you say not just “two cameras went out” but which two, and it is what the send and return screens move around. These fields let you list, add, change and remove them.
They all need a token holding SalesIgniter_Rental::serial.
Listing serials #
query WhatIsOnTheShelf {
rentalSerialNumbers(
filter: { sku: { eq: "CANON-R6" }, status: { eq: "available" } }
sort: { serial_number: ASC }
pageSize: 50
) {
total_count
items {
id
serial_number
sku
product_name
status
cost
date_acquired
notes
source_code
reservation_id
maintenance_ticket_id
}
page_info { current_page total_pages }
}
}
| Filter | Notes |
|---|---|
product_id, sku | {eq} or {in}. Everything for one product. |
serial_number | {match: "CR6"} — a substring search, for a search box. |
status | {eq} or {in}, using the stored status string. |
source_code | Which depot the unit lives at, on an MSI store. |
reservation_id | The units out on one particular booking. |
date_acquired | {from, to} — useful for depreciation and fleet-age reporting. |
Sort on id, serial_number, product_id, status, date_acquired or cost. Fetch one with rentalSerialNumber(id: 5012).
Status #
The status you read back is one of a fixed set — AVAILABLE, RENTED, MAINTENANCE, RETIRED, or UNKNOWN for a value this version does not have a name for. A unit is only rentable when it is AVAILABLE.
You rarely need to set it by hand. Sending a unit out moves it to RENTED and returning it moves it back; putting it on a maintenance ticket moves it to MAINTENANCE and takes it off the rentable fleet until the ticket is closed. Set it yourself mainly to retire a unit.
Two related fields tell you why a unit is unavailable: reservation_id is the booking it is out on, and maintenance_ticket_id is the ticket holding it. Both are null for a unit on the shelf.
Adding units #
mutation AddOne {
createRentalSerialNumber(input: {
sku: "CANON-R6"
serial_number: "CR6-0042"
cost: 2100.00
date_acquired: "2026-09-30"
notes: "Bought from Dealer Ltd, 2yr warranty"
source_code: "manchester"
}) {
serial_number { id serial_number status date_acquired }
}
}
status defaults to available and date_acquired to today. A serial code must be unique for that product — the same code on a different product is fine, which matters when manufacturers reuse sequences. A duplicate is refused with a graphql-already-exists error.
A whole delivery at once #
mutation AddDelivery {
createRentalSerialNumbers(input: [
{ sku: "CANON-R6", serial_number: "CR6-0043", cost: 2100.00 },
{ sku: "CANON-R6", serial_number: "CR6-0044", cost: 2100.00 },
{ sku: "CANON-R6", serial_number: "CR6-0045", cost: 2100.00 }
]) {
created_count
serial_numbers { id serial_number }
}
}
Up to 500 at a time, and it is all or nothing — if any row is rejected, none are written and you can fix the input and resend the whole batch without worrying about what got halfway in. Duplicates inside the batch itself are caught too, not just clashes with what is already there.
Updating a unit #
mutation Retire {
updateRentalSerialNumber(
id: 5012
input: { status: "retired", notes: "Sensor damaged beyond economic repair, 2026-10-01" }
) {
serial_number { id serial_number status notes }
}
}
Only the fields you send are written — everything else keeps its value, so you can update a note without resending the cost. Renaming a unit re-runs the uniqueness check against its product.
A unit cannot be moved between products. If a unit really has been reassigned, retire it and add it under the new product, so the history of what went out under the old code stays intact.
Deleting a unit #
mutation Remove {
deleteRentalSerialNumber(id: 5012) { success id }
}
Deleting is refused while the unit is out on a booking or held by a maintenance ticket, with an error saying which. That is deliberate: deleting a unit that is with a customer leaves a booking pointing at nothing and the kit effectively disappears from the system while still being in someone’s van.
For a unit that has left the fleet, prefer setting status to retired over deleting. A retired unit stops being rentable but its rental history and cost stay available for reporting; a deleted one takes all of that with it.
Finding what is where #
A stock-take of everything not on the shelf, and why:
query NotOnTheShelf {
rentalSerialNumbers(
filter: { status: { in: ["rented", "maintenance"] } }
pageSize: 200
) {
total_count
items { serial_number sku status reservation_id maintenance_ticket_id }
}
}
Follow reservation_id into rentalReservation for the customer and due-back date, or maintenance_ticket_id into rentalMaintenanceTicket for what is being done to it.
