Warehouse Management System for QQQ Applications - Task-Centric, Perpetual Inventory
This QBit provides a complete WMS for QQQ applications, covering receiving, putaway, inventory management, order fulfillment (pick/pack/ship), returns processing, kitting, cycle counting, replenishment, and 3PL billing. The system is metadata-driven, multi-warehouse capable, and supports both brand-direct and 3PL operating models.
- Task-Centric Work Engine: A unified
wms_tasktable is the heart of the system. Every warehouse operation (putaway, picking, packing, counting, moving, replenishment, loading, QC inspection, kit assembly) creates directed work tasks. Workers interact through a single task queue. Supervisors monitor, reprioritize, and reassign tasks. - Perpetual Inventory Through Transactions: The
wms_inventory_transactiontable is the authoritative ledger. Every quantity change is recorded as an immutable transaction first. Inventory can be fully reconstructed from the transaction log at any point in time. - Receiving & Putaway: PO-based, blind, and ASN receiving with directed or manual putaway. QC inspection gates putaway when required.
- Order Fulfillment: Configurable allocation (FEFO/FIFO/LIFO), wave-based pick release, cartonization, and short-pick resolution.
- Shipping: Carrier label generation (parcel and LTL/FTL), manifesting, dock appointment scheduling, and ship confirmation.
- Returns Processing: Full RMA lifecycle with inspection grading, disposition rules, and restock/scrap handling.
- Kitting: Bill-of-materials-driven kit assembly flowing through the task engine with component deduction and finished kit creation.
- Cycle Counting: ABC-based, location-based, SKU-based, and random counting with blind count support and supervisor variance approval.
- Replenishment: Rule-based pick-face replenishment with configurable min/max thresholds.
- 3PL Billing: Activity-based billing automatically captured from task completion hooks. Rate cards, invoicing, and storage snapshots.
- Multi-Warehouse: Warehouse-scoped data isolation from day one via
warehouse_idFK and RecordSecurityLock. - License Plate Tracking: First-class LPN entity for pallet-level operations and container lifecycle tracking.
- 11 Dashboard Widgets: Task queue summary, worker productivity, fulfillment pipeline, SLA risk, inventory accuracy, billing dashboard, and more.
QBit WMS is 100% open source under AGPL v3. All data stays in your systems. No external WMS services required.
-
Task-centric work engine: A unified
wms_tasktable sits at the heart of the system. Every warehouse operation, from putaway to picking to cycle counting, creates directed work tasks. Workers interact with the system through a single task queue. Supervisors monitor, reprioritize, and reassign tasks. This gives the warehouse a single source of truth for "what work needs to happen" and "who is doing it." -
Perpetual inventory through transactions: The
wms_inventory_transactiontable is the authoritative ledger. Inventory quantities onwms_inventoryare never modified directly. Every quantity change is recorded as an immutable transaction first, andwms_inventory.quantity_on_handis updated as a consequence. Inventory can be fully reconstructed from the transaction ledger at any point in time, and every unit movement is traceable to the task, user, and timestamp that caused it. -
Completion hook dispatcher: When a task is completed, a
TaskCompletionDispatcherswitches ontask_typeand calls the appropriate type-specific handler. Each handler contains the full chain of side effects (deduct inventory, update order lines, log transactions, create downstream tasks, capture billing activities). This explicit dispatcher pattern keeps completion logic testable in isolation and avoids unintended triggering from non-completion task updates.
- Java 17+ with QQQ backend modules
- QQQ Framework: Entities, processes, widgets, permissions, API layer
- Database: RDBMS through QQQ's backend abstraction
- MemoryRecordStore: Full test suite runs in-memory (no database required)
qbit-wms/
src/main/java/com/kingsrook/qbits/wms/
WmsQBitConfig.java -- Configuration (backend, strategies, companion QBits)
WmsQBitProducer.java -- Gen 2 QBitMetaDataProducer (auto-discovers all entities)
core/ -- Warehouse, Zone, Location, Item, ItemCategory, UOM, Client, Vendor
tasks/ -- Unified task engine (wms_task, task type config, task processes)
receiving/ -- POs, Receipts, ASNs, Putaway rules
inventory/ -- Tracking, Counting, Adjustments, Holds, License Plates
fulfillment/ -- Orders, Waves, Cartons, Allocation, Kitting
shipping/ -- Shipments, Manifests, Dock Appointments, Labels
returns/ -- RMA, Inspection, Disposition
billing/ -- 3PL activity capture, Rate Cards, Invoicing
widgets/ -- 11 dashboard widgets (producers + renderers)
Below is a full working example showing how to bootstrap a QQQ application with the WMS QBit. This assumes you have an RDBMS backend already configured.
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.MetaDataProducerMultiOutput;
import com.kingsrook.qbits.wms.WmsQBitConfig;
import com.kingsrook.qbits.wms.WmsQBitProducer;
public class MyWarehouseApp
{
public static void main(String[] args) throws Exception
{
///////////////////////////
// 1. Create QInstance //
///////////////////////////
QInstance qInstance = new QInstance();
//////////////////////////////////
// 2. Add your database backend //
//////////////////////////////////
// Register your RDBMS backend with QQQ (PostgreSQL, MySQL, H2, etc.)
// The backend name you choose here is what you pass to WmsQBitConfig.
// See QQQ documentation for backend configuration details.
////////////////////////////////////
// 3. Configure the WMS QBit //
////////////////////////////////////
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withDefaultAllocationStrategy("FEFO")
.withDefaultPickStrategy("BATCH")
.withDefaultPutawayStrategy("DIRECTED")
.withBlindCountDefault(true)
.withAdjustmentApprovalThreshold(100)
.withCycleCountVarianceThreshold(new java.math.BigDecimal("5.0"));
////////////////////////////////////
// 4. Produce and register //
////////////////////////////////////
WmsQBitProducer producer = new WmsQBitProducer()
.withQBitConfig(config);
MetaDataProducerMultiOutput output = producer.produce(qInstance);
output.addSelfToInstance(qInstance);
// At this point, qInstance contains all 46 WMS tables, 47 processes,
// 11 widgets, security locks, and permission rules.
////////////////////////////////////
// 5. Start your QQQ application //
////////////////////////////////////
// Use standard QQQ application startup (e.g., Javalin middleware).
}
}WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withCarrierAdapter(new UpsCarrierAdapter()) // your CarrierAdapter implementation
.withAccountingAdapter(new QuickBooksAdapter()); // your AccountingAdapter implementation
WmsQBitProducer producer = new WmsQBitProducer()
.withQBitConfig(config);
MetaDataProducerMultiOutput output = producer.produce(qInstance);
output.addSelfToInstance(qInstance);- Java 17+
- Maven 3.8+
- QQQ Application (this is a QBit, not a standalone application)
<dependency>
<groupId>com.kingsrook.qbits</groupId>
<artifactId>qbit-wms</artifactId>
<version>0.1.0-SNAPSHOT</version>
</dependency>If you are using the QQQ BOM POM, the version is managed for you:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.kingsrook.qqq</groupId>
<artifactId>qqq-bom-pom</artifactId>
<version>${qqq.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("yourBackendName");
WmsQBitProducer producer = new WmsQBitProducer()
.withQBitConfig(config);
MetaDataProducerMultiOutput output = producer.produce(qInstance);
output.addSelfToInstance(qInstance);Default security locks (warehouseId DENY + clientId ALLOW) and permission rules are applied automatically in postProduceActions.
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("yourBackendName")
.withRecordSecurityLocks(List.of(
new RecordSecurityLock()
.withFieldName("warehouseId")
.withSecurityKeyType("warehouseAccess")
.withNullValueBehavior(RecordSecurityLock.NullValueBehavior.DENY),
new RecordSecurityLock()
.withFieldName("clientId")
.withSecurityKeyType("clientAccess")
.withNullValueBehavior(RecordSecurityLock.NullValueBehavior.ALLOW)
));All configuration is provided through WmsQBitConfig. The only required field is backendName.
| Field | Type | Default | Description |
|---|---|---|---|
backendName |
String |
(required) | Name of the QQQ backend where all WMS tables are stored. Must match a backend already registered on your QInstance. |
tableNamePrefix |
String |
null |
Optional prefix prepended to all WMS table names (e.g., "acme" produces acme_wmsWarehouse). Useful for running multiple WMS instances in the same database. |
defaultAllocationStrategy |
String |
"FIFO" |
Default inventory allocation strategy. Options: FEFO (first expired, first out), FIFO (first in, first out), LIFO (last in, first out). |
defaultPickStrategy |
String |
"BATCH" |
Default pick strategy for wave release. Options: DISCRETE, BATCH, ZONE, CLUSTER, WAVE. |
defaultPutawayStrategy |
String |
"DIRECTED" |
Default putaway strategy for received goods. Options: DIRECTED (system-recommended locations), MANUAL (operator chooses). |
adjustmentApprovalThreshold |
Integer |
100 |
Inventory adjustments with a quantity above this value require supervisor approval. |
cycleCountVarianceThreshold |
BigDecimal |
5.0 |
Variance percentage that triggers a recount during cycle counting. |
blindCountDefault |
Boolean |
true |
When true, expected quantities are hidden from counters during cycle counts. Reduces confirmation bias. |
recordSecurityLocks |
List<RecordSecurityLock> |
auto | Custom record security locks applied to all WMS tables. When null, defaults to warehouseId (DENY on null) and clientId (ALLOW on null). |
carrierAdapter |
CarrierAdapter |
DefaultCarrierAdapter |
Pluggable carrier integration for label generation and rate lookup. The default adapter returns synthetic tracking numbers. |
accountingAdapter |
AccountingAdapter |
DefaultAccountingAdapter |
Pluggable accounting system integration for invoice sync. The default adapter returns synthetic external IDs. |
opensearchHost |
String |
null |
OpenSearch/ElasticSearch host for quick-search integration (used with the qbit-quick-search companion). |
opensearchPort |
Integer |
null |
OpenSearch/ElasticSearch port. |
opensearchIndexName |
String |
null |
OpenSearch/ElasticSearch index name. |
3PL operation with FEFO allocation and strict counting:
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withDefaultAllocationStrategy("FEFO")
.withCycleCountVarianceThreshold(new BigDecimal("2.0"))
.withAdjustmentApprovalThreshold(50)
.withBlindCountDefault(true);Brand-direct with manual putaway and OpenSearch:
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withDefaultPutawayStrategy("MANUAL")
.withDefaultPickStrategy("DISCRETE")
.withOpensearchHost("search.example.com")
.withOpensearchPort(9200)
.withOpensearchIndexName("wms-items");Multi-instance with table prefix:
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withTableNamePrefix("east");
// Tables become: east_wmsWarehouse, east_wmsTask, etc.The task engine is the central nervous system of the WMS. Every physical warehouse operation -- receiving, putaway, picking, packing, counting, moving, replenishing, loading, QC inspection, kit assembly -- is modeled as a task in the wms_task table. Here is a complete walkthrough of a real-world receiving-to-shipping flow.
RECEIVING CLERK (desktop)
1. Opens "Receive Against PO" process
2. Scans PO barcode -> system loads PO lines
3. Scans each item, enters quantity received
4. Clicks "Complete Receipt"
-> System creates PUTAWAY tasks for each received line
-> If item requires QC, creates QC_INSPECT task (PUTAWAY stays ON_HOLD)
FORKLIFT DRIVER (RF gun / mobile)
1. Opens "Get Next Task" -> system assigns highest-priority PUTAWAY task
2. Sees: "Go to Receiving Dock, pick up SKU-12345, qty 48"
3. Scans source location (receiving staging area)
4. Scans item barcode (system validates correct item)
5. Drives to directed putaway location (e.g., A-03-02-B)
6. Scans destination location (system validates)
7. Confirms quantity -> task status set to COMPLETED
-> Inventory record created at location A-03-02-B
-> Inventory transaction logged to wms_inventory_transaction
-> Receipt line updated to PUTAWAY_COMPLETE
-> PO status cascades to RECEIVED when all lines done
-> Billing activity captured for 3PL clients
ORDER FULFILLMENT (system / desktop)
1. Orders arrive via API -> status PENDING
2. "Allocate Orders" process reserves inventory -> status ALLOCATED
3. "Create Wave" groups orders by carrier cutoff -> wave created
4. "Release Wave" generates PICK tasks -> status PICK_RELEASED
PICKER (RF gun / mobile)
1. "Get Next Task" -> system assigns next PICK task
2. Walks to pick location, scans location barcode
3. Scans item barcode (system validates correct SKU)
4. Confirms quantity picked
5. Task COMPLETED
-> Inventory deducted via transaction
-> Order line pick quantity updated
-> When all picks done for an order -> PACK task auto-created
PACKER (pack station / desktop)
1. Scans order at pack station
2. Scans each item into carton (system verifies against order lines)
3. System confirms all items present and accounted for
4. "Generate Shipping Label" -> carrier label printed
-> Carton status set to LABELED
SHIPPING (dock door)
1. "Ship Confirm" at dock door -> LOAD task completed
2. Order status -> SHIPPED
3. Tracking number pushed to source system
4. Manifest created for end-of-day carrier pickup
Every task moves through a standard set of statuses:
PENDING -> ASSIGNED -> IN_PROGRESS -> COMPLETED
\-> PAUSED -> IN_PROGRESS
\-> ON_HOLD -> PENDING
\-> CANCELLED
The TaskCompletionDispatcher is the key mechanism. When any task reaches COMPLETED status, the dispatcher routes to the appropriate type-specific handler:
| Task Type | Completion Handler | Side Effects |
|---|---|---|
| PUTAWAY | PutawayTaskCompletionHandler |
Create inventory, log transaction, update receipt line, capture billing |
| PICK | PickCompletionHandler |
Deduct inventory, update order line, create PACK task when all picks done |
| PACK | PackCompletionHandler |
Update carton status, verify all items packed |
| COUNT | CountTaskCompletionHandler |
Record count, calculate variance, trigger recount or approval |
| MOVE | MoveTaskCompletionHandler |
Transfer inventory between locations, log transaction |
| REPLENISH | ReplenishCompletionHandler |
Move inventory from bulk to pick face, log transaction |
| LOAD | LoadCompletionHandler |
Confirm shipment, update order to SHIPPED |
| QC_INSPECT | QcInspectTaskCompletionHandler |
Release or reject inventory, unblock downstream PUTAWAY tasks |
| KIT_ASSEMBLE | KitAssembleCompletionHandler |
Deduct components, create finished kit inventory |
| RETURN_PUTAWAY | ReturnPutawayCompletionHandler |
Restock returned items, log transaction |
Mobile workers (forklift drivers, pickers, packers) interact with the WMS through a repeating scan-verify-confirm loop built on two core processes: getNextTask and completeTask.
1. Worker calls GET NEXT TASK
-> System finds the highest-priority pending task
matching the worker's zone and equipment qualifications
-> Task status moves from PENDING to ASSIGNED
2. Worker navigates to the source location
-> Scans the LOCATION barcode (system validates it matches the task)
3. Worker identifies the item
-> Scans the ITEM barcode (system validates correct SKU, lot, serial)
4. Worker confirms the quantity
-> Enters or confirms the quantity to move/pick/count
5. Worker navigates to the destination (if applicable)
-> Scans the DESTINATION location barcode (system validates)
6. Worker calls COMPLETE TASK
-> TaskCompletionDispatcher fires the type-specific handler
-> All side effects execute (inventory updates, downstream tasks, billing)
-> Worker returns to step 1
Each task type has configurable scan requirements set in wms_task_type_config per warehouse. Common configurations:
| Setting | Purpose |
|---|---|
| Source location scan | Confirms the worker is at the correct pick/source location |
| Item barcode scan | Validates the correct SKU is being handled |
| Destination location scan | Confirms putaway/move to the correct target location |
| Quantity confirmation | Worker enters or confirms the quantity moved |
Scan requirements can be adjusted per warehouse and task type. For example, a high-value warehouse might require all four scans, while a small operation might only require item and quantity confirmation.
Supervisors have access to additional task management processes that operate outside the mobile scan loop:
- reassignTask: Move a task from one worker to another
- reprioritizeTask: Change task priority to reorder the queue
- holdTask / releaseTask: Temporarily freeze and unfreeze tasks
- cancelTask: Cancel a task with type-specific reversal logic (e.g., deallocate inventory for cancelled picks)
- staleTaskCheck: Scheduled process that detects and unassigns abandoned tasks
| Table | Description |
|---|---|
wmsWarehouse |
Top-level organizational unit with timezone and address |
wmsZone |
Logical grouping of locations (Bulk, Pick Face, Cold, Hazmat, Staging, etc.) |
wmsLocation |
Individual storage positions (bins, shelves, floor spots) with capacity tracking |
wmsItem |
Product/SKU master with lot, serial, expiration tracking and velocity classification |
wmsItemCategory |
Hierarchical item categories with default storage requirements |
wmsUnitOfMeasure |
Item-specific UOM conversions (Each, Case, Pallet, Custom) |
wmsClient |
3PL client records (empty in brand-direct mode) |
wmsVendor |
Supplier/vendor master with lead time and contact info |
| Table | Description |
|---|---|
wmsTask |
Central work table for all warehouse operations (10 task types, 8 statuses) |
wmsTaskTypeConfig |
Configurable defaults per task type per warehouse (priority, equipment, auto-assign, scan requirements) |
| Table | Description |
|---|---|
wmsPurchaseOrder |
Inbound purchase orders with vendor reference and dock door assignment |
wmsPurchaseOrderLine |
PO line items with over/under receiving tolerance percentages |
wmsReceipt |
Receiving events (PO-based, blind, ASN, return, cross-dock) |
wmsReceiptLine |
Receipt line items with QC status tracking through putaway |
wmsAsn |
Advance ship notices with carrier and tracking info |
wmsAsnLine |
ASN line-level detail for pre-validation and variance detection |
| Table | Description |
|---|---|
wmsInventory |
Core inventory record at item+location+lot+status intersection |
wmsInventoryTransaction |
Immutable append-only ledger of every inventory movement |
wmsCycleCount |
Count plans (full, ABC-based, location-based, SKU-based, random) |
wmsCycleCountLine |
Individual count lines with variance tracking and supervisor approval |
wmsInventoryHold |
Hold records for QC, damage, recall, regulatory, and custom holds |
wmsLicensePlate |
First-class LPN entity for pallets, cases, and totes |
| Table | Description |
|---|---|
wmsOrder |
Customer orders with carrier, service level, and ship-to address |
wmsOrderLine |
Order line items with allocation, pick, pack, ship quantity tracking |
wmsWave |
Wave groupings for coordinated pick release (carrier cutoff, priority, zone) |
wmsCarton |
Physical shipping containers with dimensions, weight, and tracking |
wmsCartonLine |
Items packed into cartons with lot and serial tracking |
wmsCartonType |
Available box/container sizes for cartonization |
wmsAllocationRule |
Configurable allocation strategy rules (FEFO, FIFO, LIFO) per category |
wmsKitBom |
Kit bill of materials linking finished items to components |
| Table | Description |
|---|---|
wmsShipment |
Shipment records with carrier, tracking, and parcel/LTL/FTL mode |
wmsShipmentOrder |
Many-to-many junction for split shipments and order consolidation |
wmsManifest |
End-of-day carrier manifests |
wmsDockAppointment |
Inbound/outbound dock door scheduling |
| Table | Description |
|---|---|
wmsReturnAuthorization |
RMA records with reason codes and lifecycle status |
wmsReturnAuthorizationLine |
Return line items with authorized quantities and expected condition |
wmsReturnReceipt |
Physical receipt of returned goods |
wmsReturnReceiptLine |
Inspected return items with grade, disposition, and restock location |
| Table | Description |
|---|---|
wmsBillingRateCard |
Client-specific rate card definitions with effective dates |
wmsBillingRate |
Individual rates per activity type (receiving, storage, pick, pack, ship, etc.) |
wmsBillingActivity |
Automatically captured billable events from task completion hooks |
wmsInvoice |
Generated invoices with billing period, totals, and accounting sync |
wmsInvoiceLine |
Invoice line items aggregated by activity type |
| Table | Description |
|---|---|
wmsPutawayRule |
Configurable directed putaway rules (zone type, velocity, category, storage) |
wmsReplenishmentRule |
Min/max thresholds for pick-face replenishment by item and location |
| Process | Description |
|---|---|
receiveAgainstPO |
Receive goods against a PO with tolerance validation, QC check, and PUTAWAY task creation |
blindReceive |
Receive unexpected goods without a PO |
receiveASN |
Receive against an advance ship notice with per-line variance detection |
directedPutaway |
Evaluate configurable rules to recommend directed putaway locations |
qualityInspection |
QC inspection gate for received goods |
| Process | Description |
|---|---|
wmsCycleCount |
Generate count plans (ABC, random, location-based) and create COUNT tasks |
approveCountVariance |
Supervisor reviews count variances, approves adjustments or triggers recounts |
inventoryAdjustment |
Manual adjustment with reason codes and optional supervisor approval |
inventoryMove |
Request an inventory relocation, creates MOVE task |
inventoryHold |
Place inventory on hold (QC, damage, recall, regulatory) |
inventoryRelease |
Release held inventory back to available status |
| Process | Description |
|---|---|
allocateOrders |
Reserve inventory using FEFO/FIFO/LIFO allocation rules |
createWave |
Create a wave grouping for coordinated pick release |
releaseWave |
Release a wave and create optimized PICK tasks |
packOrder |
Pack picked items into cartons with scan verification |
kitAssembly |
Assemble kits from BOM components via KIT_ASSEMBLE tasks |
shortPickResolution |
Handle short picks with reallocation from alternate locations or backorder |
voidCarton |
Void a packed carton and return items to the pick queue |
cancelWave |
Cancel a wave with allocation reversal and order status rollback |
holdOrder |
Place an order on hold with associated task hold management |
releaseOrder |
Release a held order and resume fulfillment |
| Process | Description |
|---|---|
generateShippingLabel |
Create carrier labels for parcel; generate BOL for LTL/FTL |
manifestShipments |
Create and transmit end-of-day carrier manifests |
shipConfirm |
Confirm shipment departure and push tracking to order source |
| Process | Description |
|---|---|
createRMA |
Generate return authorization from original order |
receiveReturn |
Receive returned items and create QC_INSPECT tasks |
inspectReturn |
Inspect and grade returned items per quality criteria |
dispositionReturn |
Apply disposition rules (restock, scrap, return to vendor) |
| Process | Description |
|---|---|
getNextTask |
Mobile: assign and return the next available task for a worker |
completeTask |
Mobile: complete a task with scan verification and fire completion dispatcher |
reassignTask |
Supervisor: move a task to a different worker |
reprioritizeTask |
Supervisor: change task priority |
holdTask |
Supervisor: place a task on hold |
releaseTask |
Supervisor: release a held task back to the queue |
cancelTask |
Supervisor: cancel a task with type-specific reversal logic |
pauseTask |
Pause a task in progress |
resumeTask |
Resume a paused task |
staleTaskCheck |
Scheduled: find and unassign stuck or abandoned tasks |
| Process | Description |
|---|---|
generateInvoice |
Create invoice for a billing period with rate card application |
storageSnapshot |
Scheduled nightly: calculate daily storage billing per client |
syncInvoiceToAccounting |
Push invoices to accounting systems (QuickBooks, Xero) |
| Process | Description |
|---|---|
abcAnalysis |
Reclassify SKU velocity (A/B/C) from order history |
autoAllocateAndRelease |
Scheduled: allocate new orders and release picks automatically |
autoAssignTasks |
Scheduled: auto-assign pending tasks to available workers by zone and equipment |
expirationAlertCheck |
Scheduled: flag inventory approaching expiration |
lowStockAlertCheck |
Scheduled: flag items below reorder point |
replenishCheck |
Scheduled: detect low pick-face inventory and create REPLENISH tasks |
| Widget | Type | Description |
|---|---|---|
wmsTaskQueueSummary |
Multi-Statistics | Task counts by type and status |
wmsTaskAging |
Bar Chart | Pending/assigned tasks by age bucket |
wmsActiveWorkers |
Table | Active workers with current task and time on task |
wmsWorkerProductivity |
Table | Per-worker task completion metrics |
| Widget | Type | Description |
|---|---|---|
wmsOrdersToday |
Multi-Statistics | Orders received / picked / packed / shipped today |
wmsFulfillmentPipeline |
Stacked Bar | Orders by status from pending to shipped |
wmsSlaRisk |
Table | Orders at risk of missing ship-by date |
| Widget | Type | Description |
|---|---|---|
wmsInventorySummary |
Statistics | Total SKUs, units, locations, and utilization percentage |
wmsLowStockAlerts |
Table | Items below reorder point |
wmsInventoryAccuracy |
Statistics | Accuracy percentage from recent cycle counts |
| Widget | Type | Description |
|---|---|---|
wmsBillingDashboard |
Multi-Statistics | Revenue, unbilled activities, and invoice status |
Index wmsItem, wmsOrder, wmsInventory, and wmsTask for full-text global search.
Supported event types:
| Event | Fires When |
|---|---|
wms.task.assigned |
Task assigned to a worker |
wms.task.completed |
Task completed |
wms.task.short |
Task completed with short quantity |
wms.task.cancelled |
Task cancelled |
wms.order.created / wms.order.shipped |
Order created or shipped |
wms.receipt.completed |
Receipt fully received and put away |
wms.inventory.adjusted |
Inventory adjustment recorded |
wms.inventory.low |
Item fell below reorder point |
wms.return.dispositioned |
Return disposition complete (enables refund processing) |
wms.shipment.confirmed |
Shipment confirmed with tracking |
Carrier label generation, rate shopping, and tracking number retrieval for parcel shipments. The WMS defines a CarrierAdapter interface so multiple carrier QBits can be plugged in.
The WMS is designed to be extended through two adapter interfaces and the QQQ metadata system.
The CarrierAdapter interface (com.kingsrook.qbits.wms.shipping.CarrierAdapter) defines two methods for carrier integration. The default DefaultCarrierAdapter returns synthetic tracking numbers -- replace it for production use.
import com.kingsrook.qbits.wms.shipping.CarrierAdapter;
import java.math.BigDecimal;
public class UpsCarrierAdapter implements CarrierAdapter
{
@Override
public String generateLabel(String carrier, String serviceLevel,
String shipFromAddress, String shipToAddress, BigDecimal weightLbs)
{
// Call UPS Shipping API to create a shipment and generate a label.
// Return the tracking number assigned by UPS.
UpsClient client = new UpsClient(apiKey);
UpsShipment shipment = client.createShipment(
serviceLevel, shipFromAddress, shipToAddress, weightLbs);
return shipment.getTrackingNumber();
}
@Override
public BigDecimal getRate(String carrier, String serviceLevel, BigDecimal weightLbs)
{
// Call UPS Rating API to get a shipping rate quote.
UpsClient client = new UpsClient(apiKey);
return client.getRate(serviceLevel, weightLbs);
}
}Register it on the config:
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withCarrierAdapter(new UpsCarrierAdapter());The AccountingAdapter interface (com.kingsrook.qbits.wms.billing.AccountingAdapter) defines one method for syncing invoices to an external accounting system. The default DefaultAccountingAdapter returns synthetic external IDs.
import com.kingsrook.qbits.wms.billing.AccountingAdapter;
import java.math.BigDecimal;
public class QuickBooksAdapter implements AccountingAdapter
{
@Override
public String syncInvoice(Integer invoiceId, String invoiceNumber, BigDecimal total)
{
// Call QuickBooks API to create an invoice in the accounting system.
// Return the QuickBooks invoice ID for cross-reference.
QBooksClient qb = new QBooksClient(oauthToken);
QBooksInvoice invoice = qb.createInvoice(invoiceNumber, total);
return invoice.getId();
}
}Register it on the config:
WmsQBitConfig config = new WmsQBitConfig()
.withBackendName("rdbms")
.withAccountingAdapter(new QuickBooksAdapter());The task engine is designed around a dispatcher pattern. Adding a new task type conceptually involves:
-
Define the task type: Add a new value to the task type enumeration (e.g.,
QUALITY_AUDIT). -
Create a completion handler: Implement a handler class that defines what happens when a task of this type is completed. Follow the pattern of existing handlers like
PutawayTaskCompletionHandlerorPickCompletionHandler. Each handler receives the completed task record and executes the appropriate side effects (inventory changes, status updates, downstream task creation, billing capture). -
Register with the dispatcher: Add the new task type to
TaskCompletionDispatcherso it routes completed tasks to your handler. -
Configure per warehouse: Add a
wmsTaskTypeConfigrecord for each warehouse to control priority, equipment requirements, auto-assignment behavior, and scan requirements for the new task type.
The dispatcher pattern ensures that each task type's completion logic is isolated and independently testable.
mvn test # Run all tests
mvn test -Dtest=BaseTest # Verify QBit produces metadata- All tests run in-memory via MemoryRecordStore (no database required)
- Test classes cover all entities, processes, widgets, completion hooks, and task dispatching
mvn org.jacoco:jacoco-maven-plugin:0.8.11:prepare-agent test \
org.jacoco:jacoco-maven-plugin:0.8.11:report
# Report at: target/site/jacoco/index.html| Phase | Tables | Processes | Widgets | Focus |
|---|---|---|---|---|
| 1 | 12 | 14 | 10 | Core + Task Engine + Inventory |
| 2 | 8 | 5 | 1 | Receiving + Putaway |
| 3 | 8 | 9 | 2 | Fulfillment (Pick/Pack/Kit) |
| 4 | 4 | 3 | 0 | Shipping |
| 5 | 4 | 4 | 0 | Returns + Kitting |
| 6 | 5 | 4 | 5 | 3PL Billing |
| 7 | 4 | 6+ | 6 | Replenishment, Analytics, Optimization |
| Total | 46 | 47 | 11 |
- QQQ Wiki - Framework documentation
- QBit Development Guide - How QBits work
- Design Spec - Full data model and architecture in
QRun-IO/specs/2026-03-28-qbit-wms-design-v2.md
QBit WMS is open source and welcomes contributions.
- Report Issues - Bug reports and feature requests
- QQQ Contribution Guide - How to contribute
QBit WMS is built by Kingsrook - making engineers more productive through intelligent automation and developer tools.
- Website: https://qrun.io
- Contact: contact@kingsrook.com
- GitHub: https://github.com/QRun-IO
This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE file for details.