## Summary Maps every code path in the API repo that creates an e-conomic draft invoice or sends draft lines, and documents which paths pick a layout, which one they pick, and how the planned **with-discounts / without-discounts** two-layout selection applies. **Key finding:** the two envelope creators already implement a discount-aware selector. No code change is required for the TRU-197 rollout — only the two `invoice*LayoutNumber` config variables need to be set in the `economic` module. ## Findings at a glance - **22** code paths in `services/nginx/app/` create or send draft invoices (2 envelope creators + 6 line-add paths + 14 caller/selector/helper paths) - **2** paths currently pick a layout — both already discount-aware - **0** paths need updating for the 2-layout rollout - **2** config variables drive the selection: `invoiceLayoutNumber` and `invoiceDiscountLayoutNumber` (already wired into `economic::$config` and the OpenAPI schema) ## The two selectors 1. `economic_invoice_draft_mo::resolveLayoutNumber()` at `services/nginx/app/modules/economic/invoices/draft/economic_invoice_draft_mo.php:115` — used by `createInvoiceDraftExample()` for the single-order draft flow. 2. `collected_order_invoices_o::resolveInvoiceLayoutNumber()` at `services/nginx/app/objects/collected_order_invoices_o.php:673` — used by `createInvoiceDraft()` for the collected-invoice flow. Both return `invoice_discount_layout` if any item has a non-zero discount, otherwise `invoice_layout`. They throw if the discount layout is required and `invoiceDiscountLayoutNumber` is unconfigured. ## Document `documentation/economic/layout-selection-flow.md` — full inventory table, current/desired state, and migration plan. ## Related - TRU-197 — `documentation/economic/invoice-template-audit.md` - TRU-193 — `documentation/economic/export-field-audit.md` - PR #391 — `economic_export_sanitizer` Refs: TRU-198 --------- Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: OpenClaw <openclaw@copenhagentruckwash.io> Co-authored-by: TRU-198 Subagent <subagent@openhands.dev>
128 lines
4.7 KiB
YAML
128 lines
4.7 KiB
YAML
name: Verify e-conomic Live
|
|
|
|
# Live verification of e-conomic export sanitization.
|
|
# Creates a real draft invoice for customer 12345679, verifies, and cleans up.
|
|
# Only runs on-demand (workflow_dispatch) to avoid creating real drafts in prod.
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
customer_number:
|
|
description: 'e-conomic customer number to test against'
|
|
required: false
|
|
default: '12345679'
|
|
type: string
|
|
dry_run:
|
|
description: 'Dry run (skip actual API calls, just verify env)'
|
|
required: false
|
|
default: 'true'
|
|
type: choice
|
|
options:
|
|
- 'true'
|
|
- 'false'
|
|
schedule:
|
|
# Run every Monday at 06:00 UTC to catch any drift in e-conomic behavior
|
|
- cron: '0 6 * * 1'
|
|
|
|
concurrency:
|
|
group: live-verify-economic
|
|
cancel-in-progress: false
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
verify:
|
|
name: Live verify e-conomic draft flow
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
env:
|
|
ECONOMIC_API_APP_ACCESS_GRANT: ${{ secrets.ECONOMIC_API_APP_ACCESS_GRANT }}
|
|
ECONOMIC_API_APP_SECRET_TOKEN: ${{ secrets.ECONOMIC_API_APP_SECRET_TOKEN }}
|
|
ECONOMIC_API_BASE_URL: ${{ secrets.ECONOMIC_API_BASE_URL || 'https://restapi.e-conomic.com' }}
|
|
ECONOMIC_CUSTOMER_NUMBER: ${{ github.event.inputs.customer_number || '12345679' }}
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@11d5960a326750d5838078e36cf5b85af677262 # v4
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Setup PHP
|
|
uses: shivammathur/setup-php@e4a38cfe05f3813d096c1c2c0e7bf21a3100c93a # v2
|
|
with:
|
|
php-version: '8.4'
|
|
extensions: curl
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Dry-run mode (verify env only)
|
|
if: ${{ github.event.inputs.dry_run == 'true' }}
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Dry-run mode: checking environment..."
|
|
if [ -z "${ECONOMIC_API_APP_ACCESS_GRANT:-}" ]; then
|
|
echo "::error::ECONOMIC_API_APP_ACCESS_GRANT is not set"
|
|
exit 1
|
|
fi
|
|
if [ -z "${ECONOMIC_API_APP_SECRET_TOKEN:-}" ]; then
|
|
echo "::error::ECONOMIC_API_APP_SECRET_TOKEN is not set"
|
|
exit 1
|
|
fi
|
|
# Mask secrets in logs
|
|
echo "ECONOMIC_API_APP_ACCESS_GRANT=${ECONOMIC_API_APP_ACCESS_GRANT:0:8}..."
|
|
echo "ECONOMIC_API_APP_SECRET_TOKEN=${ECONOMIC_API_APP_SECRET_TOKEN:0:4}..."
|
|
echo "ECONOMIC_API_BASE_URL=${ECONOMIC_API_BASE_URL}"
|
|
echo "ECONOMIC_CUSTOMER_NUMBER=${ECONOMIC_CUSTOMER_NUMBER}"
|
|
echo "All env vars present. Re-run with dry_run=false to do a live test."
|
|
|
|
- name: Run live verification (creates and cleans up a real draft)
|
|
if: ${{ github.event.inputs.dry_run == 'false' }}
|
|
run: |
|
|
set -euo pipefail
|
|
cd /workspace/copenhagentruckwash/api
|
|
# Use the script that's checked in
|
|
# (we expect the script to be in the repo, e.g., scripts/verify-economic-drafts-live.php)
|
|
if [ -f scripts/verify-economic-drafts-live.php ]; then
|
|
php8.4 scripts/verify-economic-drafts-live.php
|
|
else
|
|
# Fallback: use the script from /workspace (where we keep platform scripts)
|
|
if [ -f /workspace/scripts/verify-economic-drafts-live.php ]; then
|
|
php8.4 /workspace/scripts/verify-economic-drafts-live.php
|
|
else
|
|
echo "::error::Live verification script not found"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
- name: Upload verification logs
|
|
if: ${{ always() }}
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
with:
|
|
name: live-verify-logs
|
|
path: |
|
|
/tmp/verify-economic-*.log
|
|
.tmp/verify-economic-*.log
|
|
if-no-files-found: warn
|
|
retention-days: 7
|
|
|
|
- name: Notify Slack on failure
|
|
if: ${{ failure() && env.SLACK_BOT_TOKEN != '' }}
|
|
env:
|
|
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
SLACK_DEFAULT_WEBHOOK: ${{ secrets.SLACK_DEFAULT_WEBHOOK }}
|
|
AI_DAILY_CHANNEL: ${{ secrets.AI_DAILY_CHANNEL || 'C0AM3E43249' }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [ -n "${SLACK_DEFAULT_WEBHOOK:-}" ]; then
|
|
curl -fsS -X POST "$SLACK_DEFAULT_WEBHOOK" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "$(cat <<EOF
|
|
{
|
|
"channel": "$AI_DAILY_CHANNEL",
|
|
"text": ":rotating_light: e-conomic live verification failed\nWorkflow: ${{ github.workflow }}\nRun: ${{ github.run_id }}\nURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
}
|
|
EOF
|
|
)"
|
|
fi
|