Skip to main content

Python gateway for the Hanel automated warehouse SOAP interface

Project description

Hanel Warehouse Gateway

Python module for communicating with the Hanel automatic warehouse via SOAP. Exposes a fully typed Python interface and hides all SOAP details from the caller.

Requirements

  • Python ≥ 3.10
  • uv (install with brew install uv or pip install uv)
  • Dependencies: requests, python-dotenv

Installation

# Install all dependencies including dev tools (recommended for development)
uv sync

# Production only (no dev dependencies)
uv sync --no-dev

Configuration

Copy .env.example to .env and fill in the values:

HANEL_ENDPOINT_URL=http://192.168.1.100:8080/HanelService
HANEL_TEST_MODE=false
HANEL_TEST_PREFIX=TEST_
Variable Description
HANEL_ENDPOINT_URL URL of the Hanel t-Server SOAP endpoint
HANEL_TEST_MODE Set to true to prefix order numbers, making them identifiable by warehouse operators
HANEL_TEST_PREFIX Prefix applied to order numbers when HANEL_TEST_MODE=true (default: TEST_)

Load the configuration in code with GatewayConfig.from_env():

from hanel_warehouse_gateway import HanelWarehouseGateway, GatewayConfig

# Reads from .env or environment variables
config = GatewayConfig.from_env()

# Optional overrides (useful in tests)
config = GatewayConfig.from_env({"endpoint_url": "http://localhost:8080/HanelService", "test_mode": True})

Quick start

from hanel_warehouse_gateway import (
    HanelWarehouseGateway,
    GatewayConfig,
    MovementLine,
)

config = GatewayConfig.from_env()
gateway = HanelWarehouseGateway(config)

# Register an article
gateway.register_article("ART-001", "Widget A")

# Send a movement order (operation "+" = load, "-" = pick)
gateway.send_movement_order("ORD-001", [
    MovementLine(article_number="ART-001", operation="+", nominal_quantity=5.0),
])

# Retrieve completed orders
results = gateway.get_completed_movements()
for r in results:
    print(r.job_number, r.job_status)
    for pos in r.positions:
        print(f"  {pos.article_number}: {pos.actual_quantity}/{pos.nominal_quantity}")

# Get stock levels
stock = gateway.get_inventory()
for record in stock:
    print(record.article_number, record.inventory_at_storage_location)

Available operations

Method Description
register_article(article_number, article_name) Register or update an article in the warehouse
send_movement_order(order_number, positions) Send a pick or load order
get_completed_movements() Retrieve orders with status = completed
get_all_orders() Retrieve all orders currently in the warehouse queue
get_inventory() Get stock levels for all articles across all physical locations
cancel_order(order_number) Cancel a queued order (only works if the order has not started)

Error handling

All exceptions inherit from HanelGatewayError:

Exception When raised
HanelGatewayNetworkError Network failure after all retry attempts are exhausted
HanelGatewayHttpError Non-2xx HTTP response from the server
HanelGatewaySoapFaultError SOAP fault element present in the response
HanelGatewayApplicationError returnValue != 0 in the application response
HanelGatewayValidationError Invalid input detected before sending (no HTTP call is made)
from hanel_warehouse_gateway import (
    HanelWarehouseGateway,
    GatewayConfig,
    HanelGatewayNetworkError,
    HanelGatewayApplicationError,
    HanelGatewayValidationError,
)

gateway = HanelWarehouseGateway(GatewayConfig.from_env())

try:
    gateway.register_article("ART-001", "Widget A")
except HanelGatewayValidationError as e:
    print(f"Invalid input for field '{e.field}': {e.value}")
except HanelGatewayNetworkError as e:
    print(f"Network error on {e.operation}: {e}")
except HanelGatewayApplicationError as e:
    print(f"t-Server returned error code {e.return_value}")

Release process

Releases are automated via release-please and triggered by merging commits into main.

Commit convention

All commits must follow the Conventional Commits format. The commit type determines the version bump:

Prefix Version bump When to use
fix: patch (0.1.0 → 0.1.1) Bug fix
feat: minor (0.1.0 → 0.2.0) New operation or feature
feat!: or footer BREAKING CHANGE: major (0.1.0 → 1.0.0) Incompatible public API change
chore:, docs:, test:, refactor:, ci: none Everything else

The commitlint CI check enforces this format on every PR.

How a release works

  1. Merge one or more conventional commits into main.
  2. The Release Please workflow opens (or updates) a "Release PR" automatically, with the computed version and a generated CHANGELOG.md.
  3. Review and optionally edit the changelog text in the PR.
  4. Merge the Release PR.
  5. Release Please creates the git tag and the GitHub Release; a second CI job builds the wheel and sdist and attaches them as release assets.

One-time repository setup

In Settings → Actions → General, enable "Allow GitHub Actions to create and approve pull requests" — required for Release Please to open its PR.

Running tests

# Unit tests (no external dependencies)
uv run pytest tests/ --ignore=tests/test_mock_server.py --tb=short -q

# Unit tests with coverage report
uv run pytest tests/ --ignore=tests/test_mock_server.py --cov=src/hanel_warehouse_gateway --cov-report=term-missing

# Integration tests against the mock server (requires: docker compose up --build)
uv run pytest tests/test_mock_server.py --tb=short -q

# Type checking
uv run mypy src/hanel_warehouse_gateway/

# Lint
uv run ruff check src/ tests/

Mock server

The mock_server/ directory contains a Flask implementation of the Hanel t-Server SOAP interface, intended for local development and integration testing without access to the physical warehouse. It supports all five SOAP operations (sendAPDReqV01, sendJobsReqV01, readAllJobsReqV01, readAllAMDReqV01, deleteJobReqV01), simulates automatic order completion after a configurable delay, and exposes additional HTTP endpoints (/admin/state, /admin/reset, /admin/complete-all) to inspect and control state during testing.

Start it with:

docker compose up --build

The server listens at http://localhost:8080/HanelService.

See mock_server/README.md for full documentation, including data formats, environment variables, and example curl requests for each operation.

License

This project is licensed under the GNU Lesser General Public License v3.0 or later (LGPL-3.0-or-later). See the LICENSE file for the full text; the LGPL is supplemented by the GNU GPL v3 it incorporates, provided in LICENSE.GPL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hanel_warehouse_gateway-0.2.1.tar.gz (33.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hanel_warehouse_gateway-0.2.1-py3-none-any.whl (35.7 kB view details)

Uploaded Python 3

File details

Details for the file hanel_warehouse_gateway-0.2.1.tar.gz.

File metadata

  • Download URL: hanel_warehouse_gateway-0.2.1.tar.gz
  • Upload date:
  • Size: 33.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hanel_warehouse_gateway-0.2.1.tar.gz
Algorithm Hash digest
SHA256 ff760c20b13b25b6e2328c696171b73973f8245ae821d94c582e704a271e7ce7
MD5 4e4ceb6f4b2eb03a0d56311f988705f7
BLAKE2b-256 b9737684263c12124e044876f0a2e5871577eebe4ed7a28713324cd5c5af6cc6

See more details on using hashes here.

Provenance

The following attestation bundles were made for hanel_warehouse_gateway-0.2.1.tar.gz:

Publisher: release-please.yml on 6feetup/hanel_warehouse_gateway

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hanel_warehouse_gateway-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for hanel_warehouse_gateway-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a708de9b336469b72e2042f9db8e6af26799afae802bef199372c6970d11ec1e
MD5 c63d3d1b223d227177d01af9282502c5
BLAKE2b-256 a285a4b2cd423cd1119d8298789425ed40e09d1e93af4dcf583a7383d1fa5fb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for hanel_warehouse_gateway-0.2.1-py3-none-any.whl:

Publisher: release-please.yml on 6feetup/hanel_warehouse_gateway

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page