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.7.tar.gz (32.7 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.7-py3-none-any.whl (35.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hanel_warehouse_gateway-0.1.7.tar.gz
  • Upload date:
  • Size: 32.7 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.7.tar.gz
Algorithm Hash digest
SHA256 3974ccdfb7ccb0f44f4338b5d431c995d4c9ee9478400d3036772d550ccde3fa
MD5 53e709695bf678abe2322f4705a1acb4
BLAKE2b-256 96b59d252f367de8800c383f9a4120feb1c3e293338a0f8572f6bb542b4daa67

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for hanel_warehouse_gateway-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 b8a8465bfd9fc42bc451f233cf015ba891f824c8133d9d78974932a279f3ce08
MD5 09e7eca4f4c58619f93b75050498ba04
BLAKE2b-256 711a51922cdd6531ce2a00bd5ce6d5a1170adbe41d49f809afa123fe6e91b72b

See more details on using hashes here.

Provenance

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