#!/usr/bin/env bash # OMNL Fineract — Post ledger allocation entries (T-001, T-001B, T-002A–T-008) per LEDGER_ALLOCATION_POSTING_RUNBOOK. # Prerequisites: GL accounts 1000, 1050, 2000, 2100 exist; officeId known (e.g. 1). Uses glCode to resolve GL account IDs via GET /glaccounts. # Usage: run from repo root. Set DRY_RUN=1 to print payloads only. Optional: TRANSACTION_DATE=yyyy-MM-dd (default today). set -euo pipefail REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}" DRY_RUN="${DRY_RUN:-0}" TRANSACTION_DATE="${TRANSACTION_DATE:-$(date +%Y-%m-%d)}" OFFICE_ID="${OFFICE_ID:-1}" 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:-}" if [ -z "$BASE_URL" ] || [ -z "$PASS" ]; then echo "Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD (e.g. omnl-fineract/.env)" >&2 exit 1 fi AUTH="${USER}:${PASS}" CURL_OPTS=(-s -S -w "\n%{http_code}" -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "$AUTH") # Resolve glCode -> id from GET /glaccounts get_gl_id() { local code="$1" local accs="$2" echo "$accs" | jq -r --arg c "$code" '.[] | select(.glCode == $c) | .id // empty' 2>/dev/null || true } GL_ACCOUNTS=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/glaccounts" 2>/dev/null | sed '$d') # If no jq or empty, try without jq (grep/sed) ID_1000=$(get_gl_id "1000" "$GL_ACCOUNTS") ID_1050=$(get_gl_id "1050" "$GL_ACCOUNTS") ID_2000=$(get_gl_id "2000" "$GL_ACCOUNTS") ID_2100=$(get_gl_id "2100" "$GL_ACCOUNTS") if [ -z "$ID_1000" ] || [ -z "$ID_2000" ]; then if [ "$DRY_RUN" = "1" ]; then echo "GL accounts not found; using placeholder IDs (1,2) for dry-run output only." >&2 ID_1000="${ID_1000:-1}" ID_1050="${ID_1050:-1}" ID_2000="${ID_2000:-2}" ID_2100="${ID_2100:-2}" else echo "Could not resolve GL account IDs (1000, 2000). Create GL accounts first (see docs/04-configuration/mifos-omnl-central-bank/LEDGER_ALLOCATION_GL_MAPPING.md and POSTING_RUNBOOK)." >&2 echo "Test: curl -s -u \"\$OMNL_FINERACT_USER:***\" -H 'Fineract-Platform-TenantId: omnl' ${BASE_URL}/glaccounts" >&2 exit 1 fi fi # Build journal entry payload. Fineract 1.x style: officeId, transactionDate, comments, credits[], debits[] (each glAccountId, amount). post_entry() { local memo="$1" local debit_id="$2" local credit_id="$3" local amount="$4" local comments="$5" local body body=$(jq -n \ --argjson officeId "$OFFICE_ID" \ --arg transactionDate "$TRANSACTION_DATE" \ --arg comments "$comments" \ --argjson debitId "$debit_id" \ --argjson creditId "$credit_id" \ --argjson amount "$amount" \ '{ officeId: $officeId, transactionDate: $transactionDate, dateFormat: "yyyy-MM-dd", locale: "en", currencyCode: "USD", comments: $comments, credits: [ { glAccountId: $creditId, amount: $amount } ], debits: [ { glAccountId: $debitId, amount: $amount } ] }' 2>/dev/null) if [ -z "$body" ]; then echo "jq required for posting. Install jq or post manually. Memo=$memo debit=$debit_id credit=$credit_id amount=$amount" >&2 return 1 fi if [ "$DRY_RUN" = "1" ]; then echo "DRY_RUN: $memo -> $body" return 0 fi local out out=$(curl "${CURL_OPTS[@]}" -X POST -d "$body" "${BASE_URL}/journalentries" 2>/dev/null) local code code=$(echo "$out" | tail -n1) local resp resp=$(echo "$out" | sed '$d') if [ "$code" = "200" ] || [ "${code:0:1}" = "2" ]; then echo "OK $memo (HTTP $code)" else echo "FAIL $memo HTTP $code: $resp" >&2 return 1 fi } # 1050 may not exist yet; use 1000 for T-001B debit if 1050 missing [ -z "$ID_1050" ] && ID_1050="$ID_1000" [ -z "$ID_2100" ] && ID_2100="$ID_2000" echo "Posting ledger entries (officeId=$OFFICE_ID, date=$TRANSACTION_DATE)..." >&2 post_entry "T-001" "$ID_1000" "$ID_2000" 900000000000 "Opening Balance Migration" post_entry "T-001B" "$ID_1050" "$ID_2000" 250000000000 "Treasury Conversion — Transfer to Reserve (M0)" post_entry "T-002A" "$ID_2000" "$ID_2000" 2900000000 "Shamrayan Available (M1)" post_entry "T-002B" "$ID_2000" "$ID_2100" 2100000000 "Shamrayan Restricted" post_entry "T-003" "$ID_2000" "$ID_2100" 350000000000 "HYBX Capitalization Escrow" post_entry "T-004" "$ID_2000" "$ID_2000" 5000000000 "TAJ Allocation (M1)" post_entry "T-005" "$ID_2000" "$ID_2000" 5000000000 "Aseret Allocation (M1)" post_entry "T-006" "$ID_2000" "$ID_2000" 5000000000 "Mann Li Allocation (M1)" post_entry "T-007" "$ID_2000" "$ID_2000" 50000000000 "OSJ Allocation (M1)" post_entry "T-008" "$ID_2000" "$ID_2000" 50000000000 "Alltra Allocation (M1)" echo "Done." >&2