feat(molde): tarefas do financeiro
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
# =============================================================================
|
||||
# Os tres processos do Financeiro que ninguem dispara sozinho: sem eles nasce
|
||||
# mensalidade nenhuma (dia 1, 06h), nota fiscal nenhuma processa (de hora em
|
||||
# hora) e a conciliacao nunca roda (6 em 6 horas). O financeiro nao tem
|
||||
# @Scheduled de proposito: com mais de uma replica, duas varreduras correriam.
|
||||
#
|
||||
# NO MOLDE desde 2026-09-29. Antes so os quatro tenants antigos tinham isto, e
|
||||
# um tenant VENDIDO nascia sem cobrar os alunos. O client `operacao` e o Secret
|
||||
# `operacao-credentials` nascem no provisionamento (EtapaSelarSegredos +
|
||||
# ClientDaOperacao, captacao 4.20).
|
||||
#
|
||||
# Tenant sem o financeiro no plano (bronze): o runtime responde 403 "plano nao
|
||||
# contratado" e o script termina OK ("nada a fazer") — nao e falha, e nao
|
||||
# alerta. Comprado o modulo avulso, as mesmas tarefas passam a valer sozinhas.
|
||||
# =============================================================================
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: financeiro-cron
|
||||
namespace: {{TENANT}}-prod
|
||||
data:
|
||||
disparar.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
: "${KEYCLOAK_URL:?falta KEYCLOAK_URL}"
|
||||
: "${ALVO:?falta ALVO}"
|
||||
: "${CLIENT_SECRET:?falta CLIENT_SECRET}"
|
||||
: "${ISSUER_HOST:?falta ISSUER_HOST}"
|
||||
|
||||
echo "[$(date -u +%FT%TZ)] alvo: ${ALVO}"
|
||||
|
||||
i=0
|
||||
until curl -sS -o /dev/null -m 5 "${KEYCLOAK_URL}" 2>/dev/null; do
|
||||
i=$((i+1))
|
||||
if [ "$i" -ge 24 ]; then
|
||||
echo "ERRO: ${KEYCLOAK_URL} inalcancavel depois de 2 min." >&2
|
||||
echo " Se for pod novo, e a politica de rede ainda nao programada;" >&2
|
||||
echo " se persistir, confira o Service keycloak e a deny-cross-tenant." >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 5
|
||||
done
|
||||
|
||||
RESP="$(printf 'grant_type=client_credentials&client_id=operacao&client_secret=%s' \
|
||||
"${CLIENT_SECRET}" \
|
||||
| curl -sS --fail-with-body -X POST "${KEYCLOAK_URL}" \
|
||||
-H 'Content-Type: application/x-www-form-urlencoded' \
|
||||
-H 'X-Forwarded-Proto: https' \
|
||||
-H 'X-Forwarded-Port: 443' \
|
||||
-H "X-Forwarded-Host: ${ISSUER_HOST}" -d @-)"
|
||||
|
||||
TOKEN="$(printf '%s' "${RESP}" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')"
|
||||
if [ -z "${TOKEN}" ]; then
|
||||
echo "ERRO: nao consegui token pelo client 'operacao'." >&2
|
||||
echo " Confira o Secret operacao-credentials e se o client existe no realm." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Sem --fail-with-body: o codigo e lido aqui, para separar "plano nao
|
||||
# contratado" (tenant bronze sem o financeiro — nada a fazer, NAO e falha)
|
||||
# de erro de verdade. Antes, todo bronze gerava um KubeJobFailed por hora
|
||||
# (demo, 2026-09-28) e cada alerta gastava a cota de e-mail.
|
||||
CODIGO="$(printf 'header = "Authorization: Bearer %s"\n' "${TOKEN}" \
|
||||
| curl -sS -K - -X POST "${ALVO}" -o /tmp/saida.json -w '%{http_code}')"
|
||||
echo "${CODIGO}"
|
||||
echo "resposta:"
|
||||
cat /tmp/saida.json
|
||||
echo
|
||||
if [ "${CODIGO}" = "403" ] && grep -q "plano nao contratado" /tmp/saida.json; then
|
||||
echo "financeiro fora do plano deste tenant: nada a fazer."
|
||||
exit 0
|
||||
fi
|
||||
case "${CODIGO}" in
|
||||
2*) ;;
|
||||
*) echo "ERRO: ${ALVO} respondeu ${CODIGO}." >&2; exit 1 ;;
|
||||
esac
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: financeiro-mensalidades
|
||||
namespace: {{TENANT}}-prod
|
||||
spec:
|
||||
schedule: "0 6 1 * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 900
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: disparar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
export ALVO="http://runtime-operacao/api/financeiro/matriculas/gerar-mensalidades?competencia=$(date +%Y-%m)"
|
||||
exec /bin/sh /script/disparar.sh
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/{{REALM}}/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: financeiro-cron
|
||||
defaultMode: 0555
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: financeiro-notas
|
||||
namespace: {{TENANT}}-prod
|
||||
spec:
|
||||
schedule: "15 * * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 600
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: disparar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/disparar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/{{REALM}}/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: ALVO
|
||||
value: http://runtime-operacao/api/financeiro/notas/processar?limite=50
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: financeiro-cron
|
||||
defaultMode: 0555
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: financeiro-conciliacao
|
||||
namespace: {{TENANT}}-prod
|
||||
spec:
|
||||
schedule: "30 */6 * * *"
|
||||
timeZone: America/Sao_Paulo
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
jobTemplate:
|
||||
spec:
|
||||
activeDeadlineSeconds: 900
|
||||
backoffLimit: 2
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: disparar
|
||||
image: docker.io/curlimages/curl:8.9.1
|
||||
imagePullPolicy: Never
|
||||
command: ["/bin/sh", "/script/disparar.sh"]
|
||||
env:
|
||||
- name: KEYCLOAK_URL
|
||||
value: http://keycloak.plataforma-prod.svc:8080/realms/{{REALM}}/protocol/openid-connect/token
|
||||
- name: ISSUER_HOST
|
||||
value: auth.athleticmap.com
|
||||
- name: ALVO
|
||||
value: http://runtime-operacao/api/financeiro/conciliacao?limiteEventos=100&limiteCobrancas=100
|
||||
- name: CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: operacao-credentials
|
||||
key: client-secret
|
||||
resources:
|
||||
requests: { cpu: 10m, memory: 32Mi }
|
||||
limits: { cpu: 200m, memory: 64Mi }
|
||||
volumeMounts:
|
||||
- name: script
|
||||
mountPath: /script
|
||||
volumes:
|
||||
- name: script
|
||||
configMap:
|
||||
name: financeiro-cron
|
||||
defaultMode: 0555
|
||||
Reference in New Issue
Block a user