Skip to main content

stapel-orders

CI coverage pypi downloads python license llms.txt

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, so GET cart/ makes zero comm calls.
  • Cart — one per user. A stapel-auth guest is a user too, and user.merged folds the guest's cart into the account on sign-in (same item summed, capped at MAX_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 in params.cart, so the shopper is never charged a number they did not see. Guests are asked to sign in unless CHECKOUT_REQUIRES_ACCOUNT is off.
  • Order — new → confirmed → shipped → completed, cancel from new by the buyer (OWNER_CANCELLABLE_STATUSES), staff for the rest, needs_review when a payment does not match. History is anchor-paginated.
  • Money — Decimal inside, strings on the wire. Line and cart limits are a proof that a total cannot overflow its column (tests/test_money_bounds.py, system check E005).
  • Payment — a provider seam: none (staff confirm by hand) or mock (prototype posture only). The outcome always arrives as payment.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)

Source distribution for stapel-orders 0.1.0
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)

Table of built distributions (wheels) for stapel-orders 0.1.0
File Interpreter ABI Platform Actions
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page