Files
proxmox/scripts/omnl/create-office-and-fund.sh
defiQUG b3a8fe4496
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
chore: sync all changes to Gitea
- Config, docs, scripts, and backup manifests
- Submodule refs unchanged (m = modified content in submodules)

Made-with: Cursor
2026-03-02 11:37:34 -08:00

129 lines
6.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# OMNL — Create one new office (by name, parentId, externalId, openingDate) and fund it with a two-leg M1 transfer from HO.
# Rail B: Leg 1 at HO (Dr 2100 / Cr 1410), Leg 2 at new office (Dr 1410 / Cr 2100).
# Usage:
# OFFICE_NAME="Crunchygalaxy Unip Lda - Portugal" EXTERNAL_ID="CRUNCHYGALAXY-515159573" \
# OPENING_DATE="2026-02-24" AMOUNT=1000000000 APPROVER="<name>" \
# bash scripts/omnl/create-office-and-fund.sh
# Optional: SKIP_OFFICE_CREATE=1 (use existing office by EXTERNAL_ID), SKIP_TRANSFER=1 (create office only), DRY_RUN=1, SKIP_INITIAL_CLOSURES=1 (do not run closures before legs; use when posting on same day as existing closure would block).
# Requires: resolve_ids.sh, omnl-gl-closures-post.sh, omnl-je-maker.sh, omnl-je-checker.sh, omnl-audit-packet-office20.sh.
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
SKIP_OFFICE_CREATE="${SKIP_OFFICE_CREATE:-0}"
SKIP_TRANSFER="${SKIP_TRANSFER:-0}"
SKIP_INITIAL_CLOSURES="${SKIP_INITIAL_CLOSURES:-0}"
DRY_RUN="${DRY_RUN:-0}"
OPENING_DATE="${OPENING_DATE:-$(date +%Y-%m-%d)}"
TX_DATE="${TX_DATE:-$(date +%Y-%m-%d)}"
: "${OFFICE_NAME:?Set OFFICE_NAME}"
: "${EXTERNAL_ID:?Set EXTERNAL_ID}"
: "${AMOUNT:?Set AMOUNT (minor units, e.g. 1000000000 for 1B)}"
# Material (≥10M) requires APPROVER
if [ "${AMOUNT:-0}" -ge 10000000 ] 2>/dev/null; then
: "${APPROVER:?Set APPROVER for material posting}"
fi
if [ -f "${REPO_ROOT}/omnl-fineract/.env" ]; then
set +u; source "${REPO_ROOT}/omnl-fineract/.env" 2>/dev/null || true; set -u
elif [ -f "${REPO_ROOT}/.env" ]; then
set +u; source "${REPO_ROOT}/.env" 2>/dev/null || true; set -u
fi
BASE_URL="${OMNL_FINERACT_BASE_URL:-}"
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
USER="${OMNL_FINERACT_USER:-app.omnl}"
PASS="${OMNL_FINERACT_PASSWORD:-}"
[ -z "$BASE_URL" ] || [ -z "$PASS" ] && { echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD" >&2; exit 1; }
CURL_OPTS=(-s -S -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
# --- Resolve GL IDs
echo "=== Resolve IDs ===" >&2
bash "${REPO_ROOT}/scripts/omnl/resolve_ids.sh"
source "${REPO_ROOT}/ids.env" 2>/dev/null || source ids.env 2>/dev/null
: "${ID_1410:?}"
: "${ID_2100:?}"
# --- Create or find office
offices_json=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/offices" 2>/dev/null)
NEW_OFFICE_ID=$(echo "$offices_json" | jq -r --arg e "$EXTERNAL_ID" '.[] | select(.externalId == $e) | .id' 2>/dev/null | head -1)
if [ -n "$NEW_OFFICE_ID" ] && [ "$NEW_OFFICE_ID" != "null" ]; then
echo "Office already exists: officeId=$NEW_OFFICE_ID (externalId=$EXTERNAL_ID)" >&2
else
if [ "$SKIP_OFFICE_CREATE" = "1" ]; then
echo "SKIP_OFFICE_CREATE=1 and office not found for externalId=$EXTERNAL_ID" >&2
exit 1
fi
payload=$(jq -n \
--arg name "$OFFICE_NAME" \
--arg openingDate "$OPENING_DATE" \
--arg externalId "$EXTERNAL_ID" \
'{ name: $name, parentId: 1, openingDate: $openingDate, externalId: $externalId, dateFormat: "yyyy-MM-dd", locale: "en" }')
if [ "$DRY_RUN" = "1" ]; then
echo "DRY_RUN: would POST /offices $payload" >&2
exit 0
fi
res=$(curl "${CURL_OPTS[@]}" -X POST -d "$payload" "${BASE_URL}/offices" 2>/dev/null) || true
NEW_OFFICE_ID=$(echo "$res" | jq -r '.resourceId // .officeId // empty')
[ -z "$NEW_OFFICE_ID" ] && { echo "Failed to create office: $res" >&2; exit 1; }
echo "Created office: officeId=$NEW_OFFICE_ID" >&2
fi
if [ "$SKIP_TRANSFER" = "1" ]; then
echo "SKIP_TRANSFER=1. NEW_OFFICE_ID=$NEW_OFFICE_ID" >&2
exit 0
fi
# --- Closures (idempotent; skip if SKIP_INITIAL_CLOSURES=1 to allow same-day post when server blocks on closure date)
if [ "$SKIP_INITIAL_CLOSURES" != "1" ]; then
echo "=== GL closures ===" >&2
CLOSING_DATE="${TX_DATE}" bash "${REPO_ROOT}/scripts/omnl/omnl-gl-closures-post.sh" 2>/dev/null || true
fi
# --- Leg 1: HO (Office 1) Dr 2100 / Cr 1410
REF_L1="CRUNCHY-1-$(date +%Y%m%d)-TR1-1B-L1"
REF_L2="CRUNCHY-${NEW_OFFICE_ID}-$(date +%Y%m%d)-TR1-1B-L2"
echo "=== Leg 1 (HO reduction) ===" >&2
if [ "$DRY_RUN" = "1" ]; then
echo "Would maker+checker REF=$REF_L1 OFFICE_ID=1 Dr 2100 Cr 1410 AMOUNT=$AMOUNT" >&2
else
REQUIRES_APPROVAL=1 APPROVER="${APPROVER:-}" REFERENCE_NUMBER="$REF_L1" TX_DATE="$TX_DATE" OFFICE_ID=1 \
DEBIT_GL_ID="$ID_2100" CREDIT_GL_ID="$ID_1410" AMOUNT="$AMOUNT" \
bash "${REPO_ROOT}/scripts/omnl/omnl-je-maker.sh"
PAYLOAD_FILE=$(ls "${REPO_ROOT}/reconciliation/je-${REF_L1}"*.payload.json 2>/dev/null | head -1)
[ -z "$PAYLOAD_FILE" ] && PAYLOAD_FILE="${REPO_ROOT}/reconciliation/je-${REF_L1}.payload.json"
PAYLOAD_FILE="$PAYLOAD_FILE" bash "${REPO_ROOT}/scripts/omnl/omnl-je-checker.sh"
fi
# --- Leg 2: New office Dr 1410 / Cr 2100
echo "=== Leg 2 (Office $NEW_OFFICE_ID funding) ===" >&2
if [ "$DRY_RUN" = "1" ]; then
echo "Would maker+checker REF=$REF_L2 OFFICE_ID=$NEW_OFFICE_ID Dr 1410 Cr 2100 AMOUNT=$AMOUNT" >&2
else
REQUIRES_APPROVAL=1 APPROVER="${APPROVER:-}" REFERENCE_NUMBER="$REF_L2" TX_DATE="$TX_DATE" OFFICE_ID="$NEW_OFFICE_ID" \
DEBIT_GL_ID="$ID_1410" CREDIT_GL_ID="$ID_2100" AMOUNT="$AMOUNT" \
bash "${REPO_ROOT}/scripts/omnl/omnl-je-maker.sh"
PAYLOAD_FILE=$(ls "${REPO_ROOT}/reconciliation/je-${REF_L2}"*.payload.json 2>/dev/null | head -1)
[ -z "$PAYLOAD_FILE" ] && PAYLOAD_FILE="${REPO_ROOT}/reconciliation/je-${REF_L2}.payload.json"
PAYLOAD_FILE="$PAYLOAD_FILE" bash "${REPO_ROOT}/scripts/omnl/omnl-je-checker.sh"
fi
# --- Post-audit for new office
echo "=== Post-audit (Office $NEW_OFFICE_ID) ===" >&2
if [ "$DRY_RUN" != "1" ]; then
OUT_BASE="${REPO_ROOT}/reconciliation" OFFICE_ID="$NEW_OFFICE_ID" bash "${REPO_ROOT}/scripts/omnl/omnl-audit-packet-office20.sh"
PACKET_DIR=$(find "${REPO_ROOT}/reconciliation" -maxdepth 1 -type d -name "audit-office${NEW_OFFICE_ID}-*" 2>/dev/null | sort -r | head -1)
echo "Audit packet: $PACKET_DIR" >&2
fi
# --- Re-lock
echo "=== Re-lock closures ===" >&2
CLOSING_DATE="${TX_DATE}" bash "${REPO_ROOT}/scripts/omnl/omnl-gl-closures-post.sh" 2>/dev/null || true
[ -n "${PACKET_DIR:-}" ] && echo "Package: cd reconciliation && zip -r ../CRUNCHY-${NEW_OFFICE_ID}-$(date +%Y%m%d)-TR1-1B-AUDIT.zip $(basename "$PACKET_DIR") && cd .." >&2
echo "Done. NEW_OFFICE_ID=$NEW_OFFICE_ID" >&2