Files
proxmox/scripts/omnl/omnl-gl-accounts-fx-gru-create.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

135 lines
5.1 KiB
Bash

#!/usr/bin/env bash
# Create FX and GRU (M00) GL accounts from CHART_OF_ACCOUNTS.md in OMNL Fineract.
# Idempotent: skips if glCode exists. Creates parents before children. Run from repo root.
# Requires: curl, jq.
# See: docs/04-configuration/mifos-omnl-central-bank/CHART_OF_ACCOUNTS.md, OMNL_GL_ACCOUNTS_FX_GRU.md
set -euo pipefail
REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
# usage: 1=DETAIL, 2=HEADER
USAGE_DETAIL=1
USAGE_HEADER=2
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
CURL_OPTS=(-s -S -w "\n%{http_code}" -H "Fineract-Platform-TenantId: ${TENANT}" -H "Content-Type: application/json" -u "${USER}:${PASS}")
# Build glCode -> id map from existing GL accounts
get_gl_map() {
local json
json=$(curl "${CURL_OPTS[@]}" "${BASE_URL}/glaccounts" 2>/dev/null | sed '$d')
echo "$json" | jq -r '.[] | "\(.glCode)|\(.id)"' 2>/dev/null || true
}
# Create one GL account; optional parent glCode; usage 1=DETAIL 2=HEADER
create_gl() {
local gl_code="$1" name="$2" type_id="$3" usage_id="$4" parent_gl="$5" desc="$6"
local body parent_id
if [ -n "${GL_ID_MAP[$gl_code]:-}" ]; then
echo " [skip] $gl_code$name (exists)"
return 0
fi
parent_id=""
if [ -n "$parent_gl" ] && [ -n "${GL_ID_MAP[$parent_gl]:-}" ]; then
parent_id="${GL_ID_MAP[$parent_gl]}"
fi
if [ -n "$parent_id" ]; then
body=$(jq -n \
--arg code "$gl_code" \
--arg name "$name" \
--argjson type "$type_id" \
--argjson usage "$usage_id" \
--argjson parentId "$parent_id" \
--arg desc "$desc" \
'{ glCode: $code, name: $name, type: $type, usage: $usage, parentId: $parentId, manualEntriesAllowed: true, description: $desc }')
else
body=$(jq -n \
--arg code "$gl_code" \
--arg name "$name" \
--argjson type "$type_id" \
--argjson usage "$usage_id" \
--arg desc "$desc" \
'{ glCode: $code, name: $name, type: $type, usage: $usage, manualEntriesAllowed: true, description: $desc }')
fi
local out
out=$(curl "${CURL_OPTS[@]}" -X POST -d "$body" "${BASE_URL}/glaccounts" 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
local new_id
new_id=$(echo "$resp" | jq -r '.resourceId // empty')
if [ -n "$new_id" ]; then
GL_ID_MAP[$gl_code]=$new_id
fi
echo " [created] $gl_code$name"
else
echo " [fail] $gl_code$name HTTP $code: $resp" >&2
return 1
fi
}
# Load initial map
declare -A GL_ID_MAP
while IFS='|' read -r code id; do
[ -n "$code" ] && [ -n "$id" ] && GL_ID_MAP[$code]=$id
done < <(get_gl_map)
echo "=== OMNL Fineract — Create FX and GRU (M00) GL accounts ==="
echo "Base URL: $BASE_URL"
echo ""
# Type: 1=ASSET, 2=LIABILITY, 4=INCOME, 5=EXPENSE
# Order: parents before children
echo "--- Assets (FX reserves & settlement) ---"
create_gl "10000" "Assets (header)" 1 $USAGE_HEADER "" "Total assets"
create_gl "12000" "Foreign currency reserves (header)" 1 $USAGE_HEADER "10000" "FX reserves header"
create_gl "12010" "FX reserves — USD" 1 $USAGE_DETAIL "12000" "Foreign currency reserves — USD"
create_gl "12020" "FX reserves — EUR" 1 $USAGE_DETAIL "12000" "Foreign currency reserves — EUR"
create_gl "12090" "FX reserves — other" 1 $USAGE_DETAIL "12000" "Other ISO-4217 and special units"
create_gl "13000" "FX settlement balances (header)" 1 $USAGE_HEADER "10000" "FX settlement header"
create_gl "13010" "FX settlement — nostro" 1 $USAGE_DETAIL "13000" "Settlement balances with counterparties"
echo "--- Liabilities (GRU / M00) ---"
create_gl "20000" "Liabilities (header)" 2 $USAGE_HEADER "" "Total liabilities"
create_gl "21000" "M00 — Base reserve (header)" 2 $USAGE_HEADER "20000" "Central bank reserve unit; GRU-denominated; non-circulating except authorized issuance"
create_gl "21010" "M00 — Bank reserves (control)" 2 $USAGE_DETAIL "21000" "Control account for M00"
echo "--- Income (FX gains) ---"
create_gl "40000" "Income (header)" 4 $USAGE_HEADER "" "Total income"
create_gl "42000" "FX gains (realized)" 4 $USAGE_DETAIL "40000" "Realized foreign exchange gains"
create_gl "42100" "Unrealized FX gain (P&L)" 4 $USAGE_DETAIL "40000" "Unrealized FX gain (revaluation)"
echo "--- Expenses (FX losses) ---"
create_gl "50000" "Expenses (header)" 5 $USAGE_HEADER "" "Total expenses"
create_gl "51000" "FX losses (realized)" 5 $USAGE_DETAIL "50000" "Realized foreign exchange losses"
create_gl "52100" "Unrealized FX loss (P&L)" 5 $USAGE_DETAIL "50000" "Unrealized FX loss (revaluation)"
echo ""
echo "Done. See CHART_OF_ACCOUNTS.md and FX_AND_VALUATION.md for usage."