stapel-orders
Cart, checkout and orders over opaque purchasables. A host registers what can be bought (purchasable_type -> a keyed-batch resolver Function answering title, price, currency, availability); the cart snapshots each line when it is added, so reading a cart never calls the product owner. Checkout re-prices every line, refuses with the refreshed cart when anything drifted, and places an order idempotently on a client key, emptying the cart and announcing orders.order.placed with its lines. Orders follow a staff-driven lifecycle with buyer cancel; payment is a provider seam (none, mock) whose outcome arrives as the payment.completed fact.
Part of the Stapel framework — composable Django apps that deploy as a monolith or as microservices without changing module code.
Install
pip install stapel-orders
At a glance
| Fact | Value |
|---|---|
| Version | 0.1.0 |
| Python | >=3.11 (3.11, 3.12, 3.13, 3.14) |
| HTTP operations | 10 |
| Config axes | 2 |
| Usage surface | 11 |
| Extension points | 7 |
| Error codes | 54 |
| Documented flows | 4 |
| Fleet dependencies | stapel-auth (optional) · stapel-core · stapel-currencies (optional) · stapel-listings (optional) |
Documentation
OpenAPI · capabilities.json · llms.txt (for agents)
What this is
Cart, checkout and orders for a Stapel shop — over opaque purchasables. The module ships knowing nothing about what is sold: a host registers each purchasable type with a comm Function that resolves a keyed batch of keys to title, price, currency and availability. Orders never imports a product model, so a listing, a spare part from a custom app, or anything else is bought through one cart.
Quick start
INSTALLED_APPS = [
# ...
"stapel_orders",
]
STAPEL_ORDERS = {
"PURCHASABLE_TYPES": {
"listing": {"resolve": "listings.purchasables"}, # stapel-shop preset default
},
}
# urls.py
path("orders/api/", include("stapel_orders.urls")) # -> /orders/api/v1/...
# settings.py — the abandoned-cart purge (Celery optional)
from stapel_orders.beat import get_orders_beat_schedule
CELERY_BEAT_SCHEDULE = {**get_orders_beat_schedule()}
A custom product type is one resolver and one registration:
from stapel_core.comm import function
@function("parts.purchasables")
def purchasables(payload):
parts = Part.objects.filter(pk__in=payload["keys"])
return {str(p.pk): {"title": p.name, "price": str(p.price), "currency": "USD",
"available": p.stock > 0, "max_quantity": p.stock,
"seller_id": None, "image": None, "url": f"/parts/{p.pk}"}
for p in parts}
# AppConfig.ready()
from stapel_orders.registry import register_purchasable_type
register_purchasable_type("part", {"resolve": "parts.purchasables"})
Concepts
- Purchasable — an opaque pair
(purchasable_type, purchasable_key). The resolver answers on add and at checkout only; a cart line is a snapshot, soGET cart/makes zero comm calls. - Cart — one per user. A stapel-auth guest is a user too, and
user.mergedfolds the guest's cart into the account on sign-in (same item summed, capped atMAX_LINE_QUANTITY). One currency per cart; a line in another currency is refused, never converted. - Checkout — one idempotent call (
idempotency_key). Every line is re-priced; a changed price, a vanished item or short stock refreshes the cart and refuses with it inparams.cart, so the shopper is never charged a number they did not see. Guests are asked to sign in unlessCHECKOUT_REQUIRES_ACCOUNTis off. - Order —
new → confirmed → shipped → completed, cancel fromnewby the buyer (OWNER_CANCELLABLE_STATUSES), staff for the rest,needs_reviewwhen a payment does not match. History is anchor-paginated. - Money —
Decimalinside, strings on the wire. Line and cart limits are a proof that a total cannot overflow its column (tests/test_money_bounds.py, system checkE005). - Payment — a provider seam:
none(staff confirm by hand) ormock(prototype posture only). The outcome always arrives aspayment.completed, the one path that marks an order paid. - GDPR — erasure deletes carts and pseudonymizes the person on orders; amounts stay.
License
MIT — see LICENSE.
This page is assembled by stapel-readme from docs/readme.md plus the contract artifacts in docs/. Edit the prose in docs/readme.md; the badges, facts and links above and below it are generated — do not hand-edit README.md.
Metadata
Release files for stapel-orders 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| stapel_orders-0.1.0.tar.gz | 73.3 kB | With provenance | Details for stapel_orders-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| stapel_orders-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for stapel_orders-0.1.0-py3-none-any.whl |
Total release size: 146.5 kB
Release files / stapel_orders-0.1.0.tar.gz
| Download URL | stapel_orders-0.1.0.tar.gz |
|---|---|
| Size | 73.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0110e70148eda6c266bce6dd8feb218295e416ff3f44eda48d7947de7f5a6e98
|
|
BLAKE2b-256 checksum How to use checksums |
489f70b3c31d3fb4b93ca9478fefe37b917826ef9d11648f87e5d0dedcee68db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logRelease files / stapel_orders-0.1.0-py3-none-any.whl
| Download URL | stapel_orders-0.1.0-py3-none-any.whl |
|---|---|
| Size | 73.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b24544efd6214b5fb8b2f7a8cfc4a874b77b8c3a731a5fe6abcf1402b85079cd
|
|
BLAKE2b-256 checksum How to use checksums |
77336076b999c3c9fe14239529c41fd9eff2057d6c7764fbcf6369bb49cf1e5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logSecurity for stapel-orders 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for stapel_orders-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.