diff --git a/Claude outputs/main.py b/Claude outputs/main.py index 8ca93ed..5e9669d 100644 --- a/Claude outputs/main.py +++ b/Claude outputs/main.py @@ -519,6 +519,43 @@ async def _ensure_deck_board() -> dict: return _deck_cache +async def create_order(customer: str, description: str, due_date: str = None) -> dict: + board = await _ensure_deck_board() + stack_id = board["stacks"]["Offen"] + + body = {"title": customer, "description": description, "type": "plain", "order": 999} + if due_date: + body["duedate"] = _as_calendar_local(datetime.fromisoformat(due_date)).isoformat() + + card = await _deck_request("POST", f"/boards/{board['board_id']}/stacks/{stack_id}/cards", body) + return { + "id": card["id"], + "customer": customer, + "description": description, + "status": "Offen", + "due_date": due_date, + } + + +async def list_orders(status: str = None) -> list: + board = await _ensure_deck_board() + stacks = await _deck_request("GET", f"/boards/{board['board_id']}/stacks") + + orders = [] + for stack in stacks: + if status and stack["title"] != status: + continue + for card in stack.get("cards", []): + orders.append({ + "id": card["id"], + "customer": card["title"], + "description": card.get("description", ""), + "status": stack["title"], + "due_date": card.get("duedate"), + }) + return orders + + def _decode_mime_words(value: str) -> str: parts = decode_header(value) decoded = [] diff --git a/Claude outputs/tests/test_orders.py b/Claude outputs/tests/test_orders.py index 8a45134..73fef13 100644 --- a/Claude outputs/tests/test_orders.py +++ b/Claude outputs/tests/test_orders.py @@ -141,3 +141,77 @@ async def test_ensure_deck_board_caches_after_first_lookup(): mock_req.assert_not_called() assert board["board_id"] == 10 + + +_BOARD = {"board_id": 10, "stacks": {"Offen": 1, "In Arbeit": 2, "Erledigt": 3}} + + +@pytest.mark.asyncio +async def test_create_order_creates_card_in_offen_stack(): + with patch.object(main, "_ensure_deck_board", new=AsyncMock(return_value=_BOARD)), patch.object( + main, "_deck_request", new=AsyncMock(return_value={"id": 55}) + ) as mock_req: + order = await main.create_order("Feuerwehr Onza", "10x Handschuhe Groesse L") + + assert order == { + "id": 55, + "customer": "Feuerwehr Onza", + "description": "10x Handschuhe Groesse L", + "status": "Offen", + "due_date": None, + } + method, path, body = mock_req.call_args[0] + assert method == "POST" + assert path == "/boards/10/stacks/1/cards" + assert body["title"] == "Feuerwehr Onza" + assert body["description"] == "10x Handschuhe Groesse L" + assert "duedate" not in body + + +@pytest.mark.asyncio +async def test_create_order_localizes_due_date(): + with patch.object(main, "_ensure_deck_board", new=AsyncMock(return_value=_BOARD)), patch.object( + main, "_deck_request", new=AsyncMock(return_value={"id": 55}) + ) as mock_req: + await main.create_order("Feuerwehr Onza", "Helme", due_date="2026-09-20") + + _, _, body = mock_req.call_args[0] + assert body["duedate"] == datetime(2026, 9, 20, tzinfo=main.CALENDAR_TIMEZONE).isoformat() + + +@pytest.mark.asyncio +async def test_list_orders_flattens_cards_across_stacks(): + stacks_response = [ + {"id": 1, "title": "Offen", "cards": [ + {"id": 55, "title": "Feuerwehr Onza", "description": "Helme", "duedate": None} + ]}, + {"id": 2, "title": "In Arbeit", "cards": []}, + {"id": 3, "title": "Erledigt", "cards": [ + {"id": 56, "title": "Musterfirma", "description": "Stiefel", "duedate": "2026-09-20T00:00:00+02:00"} + ]}, + ] + with patch.object(main, "_ensure_deck_board", new=AsyncMock(return_value=_BOARD)), patch.object( + main, "_deck_request", new=AsyncMock(return_value=stacks_response) + ): + orders = await main.list_orders() + + assert len(orders) == 2 + assert orders[0] == { + "id": 55, "customer": "Feuerwehr Onza", "description": "Helme", "status": "Offen", "due_date": None + } + assert orders[1]["status"] == "Erledigt" + + +@pytest.mark.asyncio +async def test_list_orders_filters_by_status(): + stacks_response = [ + {"id": 1, "title": "Offen", "cards": [{"id": 55, "title": "A", "description": "", "duedate": None}]}, + {"id": 2, "title": "In Arbeit", "cards": []}, + {"id": 3, "title": "Erledigt", "cards": [{"id": 56, "title": "B", "description": "", "duedate": None}]}, + ] + with patch.object(main, "_ensure_deck_board", new=AsyncMock(return_value=_BOARD)), patch.object( + main, "_deck_request", new=AsyncMock(return_value=stacks_response) + ): + orders = await main.list_orders(status="Erledigt") + + assert [o["id"] for o in orders] == [56]