Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/CodexaCP/DG_APK/llms.txt

Use this file to discover all available pages before exploring further.

The Shipments module drives outbound warehouse operations on the Dragon Guard handheld. Operators load the backend-managed list of shipment headers, select a document, confirm shipped quantities against each line, then post to commit the outbound movement. Like receipts, the app trusts the server’s document visibility entirely — no client-side status filtering is applied when loading the header list.

Status Reference

Shipment headers expose three status fields. The computed VisibleStatus prefers ProcessingStatus over DocumentStatus, then StatusPalette maps the result to a short handheld label and badge color.
Short LabelRaw Status ValuesBadge Color
RelRELEASED#2563EB (blue)
OpenOPEN#2563EB (blue)
ShipSHIPPING#F59E0B (amber)
PendPENDING#F59E0B (amber)
PartPARTIALLY SHIPPED, PARTIALLY POSTED#F97316 / #F59E0B
DonePOSTED, CLOSED#16A34A (green)
The fields on ShipmentHeaderDto that power the badge:
// ShipmentDto.cs
public string VisibleStatus =>
    string.IsNullOrWhiteSpace(ProcessingStatus) ? DocumentStatus : ProcessingStatus;

public string StatusShortLabel => StatusPalette.GetShortLabel(VisibleStatus);
public string StatusBadgeColor => StatusPalette.GetBadgeColor(VisibleStatus);
The legacy ShipmentStatus field is retained for ERP compatibility. It is not used to compute badge labels — the handheld always renders from VisibleStatus. When the backend returns only ShipmentStatus and both DocumentStatus and ProcessingStatus are blank, the badge falls back to a neutral color (#475569).PARTIALLY SHIPPED and PARTIALLY POSTED both produce the short label Part but differ in badge color: PARTIALLY SHIPPED renders orange (#F97316) while PARTIALLY POSTED renders amber (#F59E0B).

Shipment Header Fields

Id
Guid
required
Internal record identifier used to load lines and post the shipment.
CompanyId
Guid
Company the shipment belongs to.
CompanyCode
string
Company code. Searchable in the header list.
ShipmentNo
string
required
Human-readable shipment number displayed in list and detail views.
ExternalShipmentNo
string
Customer or ERP sales order reference, searchable in the header list.
ShipmentType
string
Classification of the outbound movement (e.g., sales, transfer). Searchable in the header list.
ShipmentStatus
string
Legacy ERP status field. Kept for compatibility; not used for badge rendering.
DocumentStatus
string
Handheld-facing document lifecycle status. Badge source when ProcessingStatus is blank.
ProcessingStatus
string
Fine-grained workflow status (e.g., SHIPPING). Takes priority over DocumentStatus for badge rendering.
CustomerCode
string
ERP customer code for the outbound order.
CustomerName
string
Customer display name shown on the header card.
WarehouseCode
string
Source warehouse code. Exposed as LocationCode (defaulting to MAIN when blank).
TotalLines
int
Number of lines in the shipment, shown on the header card.
TotalQty
decimal
Sum of all ordered quantities across lines.
IsClosed
bool
true when the backend marks the document as fully closed.
PlannedShipDate
DateTime?
Target ship date, filterable in the client-side search.
ActualShipDate
DateTime?
Recorded actual dispatch date, set after posting. Searchable in the header list.
CreatedAt
DateTime
Timestamp when the shipment record was created.

Shipment Line Fields

Id
string
required
Line identifier used in PUT /api/shipmentlines/{id} update calls.
ShipmentId
string
Parent shipment identifier linking this line to its header document.
CompanyId
string
Company identifier at the line level.
LineNo
int
Sequential line number within the shipment.
LineStatus
string
Status of the individual line (e.g., open, completed).
ItemId
string
Internal item identifier. Not shown to the operator.
ItemNo
string
ERP item code for this line.
ItemDescription
string
Item display name shown on the line card.
UnitOfMeasure
string
Unit of measure for all quantities on the line.
WarehouseId
string
Internal warehouse identifier.
BinId
string
Internal bin identifier for the source bin.
BinCode
string
Source bin code from which the item should be picked.
OrderedQty
decimal
Full quantity ordered for this line. ShippedQty is clamped to this value in the UI.
PickedQty
decimal
Quantity confirmed picked prior to shipping.
ShippedQty
decimal
Quantity the operator enters as actually shipped. Clamped to [0, OrderedQty] by the model setter.
BaseUomQty
decimal?
Quantity expressed in the item’s base unit of measure.
AlreadyPostedQty
decimal
Cumulative quantity already posted in previous posting events.
PostedQuantity
decimal
Cumulative quantity posted to the stock ledger.
RemainingQty
decimal
Legacy remaining quantity field from older API responses.
RemainingQuantity
decimal
Remaining quantity field from newer API responses. The effective balance used by the UI is max(RemainingQuantity, RemainingQty) via the RemainingBalance computed property.
LotNo
string
Lot tracking reference when the item is lot-tracked.
SerialNo
string
Serial number when the item is serial-tracked.
ExpirationDate
DateTime?
Expiry date when the item is expiration-tracked.
UnitWeight
decimal?
Item unit weight, used for load calculations.
UnitVolume
decimal?
Item unit volume, used for capacity calculations.
IsCompleted
bool
Set to true by the backend when the line is fully shipped.

API Endpoints

MethodEndpointPurpose
GET/api/shipmentheaders?pageNumber={n}&pageSize={n}Load the paginated header list
GET/api/shipmentlines?shipmentId={id}&pageNumber={n}&pageSize={n}Load lines for a shipment
GET/api/shipmentheaders/{id}Fallback: load header with embedded lines
PUT/api/shipmentlines/{id}Persist shipped quantity for a line
POST/api/shipmentheaders/{id}/postPost (commit) the shipment
All shipment endpoints use lowercase shipmentheaders and shipmentlines — unlike the receipt endpoints which use PascalCase. The header list is fetched without any hard status filter — status and shipmentNo are passed only when the caller explicitly provides them:
// ShipmentService.cs
var query = new StringBuilder();
query.Append($"?pageNumber={pageNumber}");
query.Append($"&pageSize={pageSize}");
query.Append($"&sortBy={sortBy}");
query.Append($"&sortDesc={sortDesc}");

if (!string.IsNullOrWhiteSpace(status))
    query.Append($"&status={Uri.EscapeDataString(status)}");

if (!string.IsNullOrWhiteSpace(shipmentNo))
    query.Append($"&shipmentNo={Uri.EscapeDataString(shipmentNo)}");

var response = await _httpClient.GetAsync($"/api/shipmentheaders{query}");

End-to-End Shipment Flow

1

Open the Shipments module

From the home screen, tap Shipments. ShipmentHeadersViewModel.InitializeAsync() loads headers once on first visit; returning to the list always calls LoadAsync() to pull fresh data from the server.
2

Browse and search headers

Up to 20 headers are loaded per page from GET /api/shipmentheaders. The search bar filters client-side across ShipmentNo, ExternalShipmentNo, ShipmentType, all three status fields, WarehouseCode, LocationCode, CustomerCode, CustomerName, CompanyCode, TotalLines, TotalQty, IsClosed, planned and actual ship dates, and CreatedAt.
3

Select a shipment header

Tap a header card to open the lines screen. ShipmentHeadersViewModel.SelectShipmentCommand navigates to ShipmentLinesPage and calls GET /api/shipmentlines?shipmentId={id}&pageNumber=1&pageSize=20 to load lines.
4

Enter shipped quantities

Tap a line to open the detail screen. Enter the quantity shipped into ShippedQty. The model enforces 0 ≤ ShippedQty ≤ OrderedQty automatically. Save the line via PUT /api/shipmentlines/{id}:
// UpdateShipmentLineDto.cs
public class UpdateShipmentLineDto
{
    public decimal ShippedQty { get; set; }
}
5

Post the shipment

From the header detail action menu, tap Post. The app calls POST /api/shipmentheaders/{id}/post with no request body:
// ShipmentLineService.cs
public async Task<bool> PostShipmentAsync(string shipmentId)
{
    var endpoint = $"api/shipmentheaders/{shipmentId}/post";
    var response = await _http.PostAsync(endpoint, null);

    if (!response.IsSuccessStatusCode)
    {
        var error = await response.Content.ReadAsStringAsync();
        throw new InvalidOperationException(ApiErrorMapper.ToUserMessage(
            error,
            "No se pudo postear el despacho."));
    }

    return true;
}
6

Verify updated status

After posting, the header list refreshes from the server. Partially-posted documents remain visible with the Part badge until the backend fully closes them. A fully posted document either shows the Done badge or disappears from the list if the backend removes it from the visible set.
Posting is blocked for documents that are already fully posted or closed.The line service will throw an InvalidOperationException if the backend rejects the post. StatusPalette.IsPostBlocked returns true for statuses that normalise to POSTED or CLOSED:
// StatusPalette.cs
public static bool IsPostBlocked(string? status)
{
    var normalized = Normalize(status);
    return normalized is "POSTED" or "CLOSED";
}
Posting is intentionally allowed for released, in-process (SHIPPING), and partially-posted statuses — the guard only blocks fully completed documents.

Legacy Line Fallback

On older backend deployments the dedicated /api/shipmentlines endpoint may return an error for certain shipment records. When this occurs, ShipmentLineService automatically retries by fetching the header record at /api/shipmentheaders/{id} and extracting the lines array embedded in the response body. Client-side pagination is then applied to the embedded array so the handheld continues operating normally without any operator intervention.
// ShipmentLineService.cs — TryGetShipmentLinesFromHeaderAsync
var response = await _http.GetAsync($"api/shipmentheaders/{shipmentId}");
if (!response.IsSuccessStatusCode)
    return null;

using var document = await JsonDocument.ParseAsync(stream);
if (!document.RootElement.TryGetProperty("lines", out var linesElement) ||
    linesElement.ValueKind != JsonValueKind.Array)
    return null;

var items = JsonSerializer.Deserialize<List<ShipmentLineDto>>(
    linesElement.GetRawText(), options) ?? new List<ShipmentLineDto>();

var paged = items
    .Skip(Math.Max(0, pageNumber - 1) * pageSize)
    .Take(pageSize)
    .ToList();

Local Search Behaviour

The header list supports client-side filtering without an additional API call. The view model filters across all relevant string, numeric, and date fields:
// ShipmentHeadersViewModel.cs
var filtered = _allItems
    .Where(x =>
        (x.ShipmentNo?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.ExternalShipmentNo?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.ShipmentType?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.ShipmentStatus?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.DocumentStatus?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.ProcessingStatus?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.WarehouseCode?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.LocationCode.Contains(search, StringComparison.OrdinalIgnoreCase)) ||
        (x.CustomerCode?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.CustomerName?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        (x.CompanyCode?.Contains(search, StringComparison.OrdinalIgnoreCase) ?? false) ||
        x.TotalLines.ToString().Contains(search) ||
        x.TotalQty.ToString().Contains(search) ||
        (x.IsClosed ? "Closed" : "Open")
            .Contains(search, StringComparison.OrdinalIgnoreCase) ||
        (x.PlannedShipDate?.ToString("yyyy-MM-dd").Contains(search) ?? false) ||
        (x.ActualShipDate?.ToString("yyyy-MM-dd").Contains(search) ?? false) ||
        x.CreatedAt.ToString("yyyy-MM-dd").Contains(search)
    )
    .ToList();

Build docs developers (and LLMs) love