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 "+" = pick, "-" = load)
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.1.6.tar.gz (32.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.1.6-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hanel_warehouse_gateway-0.1.6.tar.gz
  • Upload date:
  • Size: 32.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.1.6.tar.gz
Algorithm Hash digest
SHA256 ff22f422bf70311bbf72db0467cae4c25f1dc1c6060fa12152cafc6974cec02f
MD5 dc2f079680352e9af361b060e6ed3fd1
BLAKE2b-256 0c792ea06d10b77758b0595811b102bfc45ec52362259b6c93157036b36d2e2b

See more details on using hashes here.

Provenance

The following attestation bundles were made for hanel_warehouse_gateway-0.1.6.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.1.6-py3-none-any.whl.

File metadata

File hashes

Hashes for hanel_warehouse_gateway-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 5447136095e07e439bfd80b26a90417ea3e479b332491485fa5735bb97e43033
MD5 f27518820cec776f7af59375248229ec
BLAKE2b-256 4682a6f3afd66093bbb779e9e65e65f4b2bab9213fe99056e040d86ff2f54f9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for hanel_warehouse_gateway-0.1.6-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