release: v2.2.81 contacts visibility and telephony/date/deploy fixes
This commit is contained in:
parent
8ec9400b15
commit
25530c7c94
29
RELEASE_NOTES_v2.2.81.md
Normal file
29
RELEASE_NOTES_v2.2.81.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Release Notes v2.2.81
|
||||
|
||||
Dato: 2026-05-04
|
||||
|
||||
## Fixes
|
||||
|
||||
- Kontakter: Stabiliseret paginering i `/api/v1/contacts` ved at tilfoeje deterministisk tie-break (`ORDER BY ... , c.id`).
|
||||
- Kontakter: Fjernet skrøbelig frontend query-key short-circuit i kontaktlisten, som kunne medfoere at listen ikke blev genindlaest korrekt efter afbrudte requests.
|
||||
- Telefoni: Rettet datofilter i `/api/v1/telefoni/calls` saa `date_to` er inklusiv hele dagen.
|
||||
- Telefoni: Validerer nu tydeligt `date_from`/`date_to` format (`YYYY-MM-DD`) med 422 ved ugyldig input.
|
||||
- Deployment: `updateto.sh` bruger nu dynamiske containernavne baseret paa `STACK_NAME` i stedet for hardcoded `-prod`.
|
||||
|
||||
## Beroerte filer
|
||||
|
||||
- `app/contacts/backend/router_simple.py`
|
||||
- `app/contacts/frontend/contacts.html`
|
||||
- `app/modules/telefoni/backend/router.py`
|
||||
- `updateto.sh`
|
||||
- `VERSION`
|
||||
|
||||
## Drift
|
||||
|
||||
Hvis stacken koerer som `v2`, deploy med:
|
||||
|
||||
```bash
|
||||
sudo -iu bmcadmin
|
||||
cd /srv/podman/bmc_hub_v2
|
||||
./updateto.sh v2.2.81
|
||||
```
|
||||
@ -140,7 +140,7 @@ async def get_contacts(
|
||||
{where_sql}
|
||||
GROUP BY c.id, c.first_name, c.last_name, c.email, c.phone, c.mobile,
|
||||
c.title, c.department, c.user_company, c.is_active, c.created_at, c.updated_at
|
||||
ORDER BY company_count DESC, c.last_name, c.first_name
|
||||
ORDER BY company_count DESC, c.last_name, c.first_name, c.id
|
||||
LIMIT %s OFFSET %s
|
||||
"""
|
||||
params.extend([limit, offset])
|
||||
|
||||
@ -813,7 +813,6 @@ let searchQuery = '';
|
||||
let totalContacts = 0;
|
||||
let searchTimeout = null;
|
||||
let currentRequestController = null;
|
||||
let lastLoadedQueryKey = '';
|
||||
let availableCompanies = [];
|
||||
let selectedCompanyIds = new Set();
|
||||
let currentContactsData = [];
|
||||
@ -941,12 +940,6 @@ async function loadContacts() {
|
||||
params.append('is_active', 'false');
|
||||
}
|
||||
|
||||
const queryKey = `${currentPage}|${pageSize}|${searchQuery}|${currentFilter}`;
|
||||
if (queryKey === lastLoadedQueryKey) {
|
||||
return;
|
||||
}
|
||||
lastLoadedQueryKey = queryKey;
|
||||
|
||||
const response = await fetch(`/api/v1/contacts?${params}`, { signal: currentRequestController.signal });
|
||||
const data = await response.json();
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import logging
|
||||
import base64
|
||||
import ipaddress
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Optional
|
||||
from urllib.error import URLError, HTTPError
|
||||
from urllib.request import Request as UrlRequest, urlopen
|
||||
@ -653,15 +653,29 @@ async def list_calls(
|
||||
where = []
|
||||
params = []
|
||||
|
||||
parsed_date_from = None
|
||||
parsed_date_to = None
|
||||
if date_from:
|
||||
try:
|
||||
parsed_date_from = datetime.strptime(date_from, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=422, detail="Invalid date_from format, expected YYYY-MM-DD")
|
||||
if date_to:
|
||||
try:
|
||||
# Make date_to inclusive for the whole selected day.
|
||||
parsed_date_to = datetime.strptime(date_to, "%Y-%m-%d") + timedelta(days=1)
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=422, detail="Invalid date_to format, expected YYYY-MM-DD")
|
||||
|
||||
if user_id is not None:
|
||||
where.append("t.bruger_id = %s")
|
||||
params.append(user_id)
|
||||
if date_from:
|
||||
if parsed_date_from is not None:
|
||||
where.append("t.started_at >= %s")
|
||||
params.append(date_from)
|
||||
if date_to:
|
||||
where.append("t.started_at <= %s")
|
||||
params.append(date_to)
|
||||
params.append(parsed_date_from)
|
||||
if parsed_date_to is not None:
|
||||
where.append("t.started_at < %s")
|
||||
params.append(parsed_date_to)
|
||||
if without_case:
|
||||
where.append("t.sag_id IS NULL")
|
||||
|
||||
|
||||
33
updateto.sh
Normal file → Executable file
33
updateto.sh
Normal file → Executable file
@ -17,6 +17,9 @@ if [ "${EUID:-$(id -u)}" -eq 0 ]; then
|
||||
fi
|
||||
|
||||
PODMAN_COMPOSE_FILE="docker-compose.prod.yml"
|
||||
STACK_NAME="${STACK_NAME:-prod}"
|
||||
POSTGRES_CONTAINER="bmc-hub-postgres-${STACK_NAME}"
|
||||
API_CONTAINER="bmc-hub-api-${STACK_NAME}"
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "❌ Fejl: Ingen version angivet"
|
||||
@ -103,7 +106,7 @@ fi
|
||||
# Guard against host port conflicts before attempting startup
|
||||
POSTGRES_BIND_ADDR="${POSTGRES_BIND_ADDR:-127.0.0.1}"
|
||||
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
|
||||
if podman ps --format '{{.Names}} {{.Ports}}' | grep -E "${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}->5432/tcp" | grep -v "bmc-hub-postgres-prod" >/dev/null 2>&1; then
|
||||
if podman ps --format '{{.Names}} {{.Ports}}' | grep -E "${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}->5432/tcp" | grep -v "$POSTGRES_CONTAINER" >/dev/null 2>&1; then
|
||||
echo "❌ Fejl: Portkonflikt på ${POSTGRES_BIND_ADDR}:${POSTGRES_PORT} (Postgres host-port)"
|
||||
echo " Sæt en ledig port i .env, fx POSTGRES_PORT=5433"
|
||||
podman ps --format 'table {{.Names}}\t{{.Ports}}'
|
||||
@ -111,11 +114,11 @@ if podman ps --format '{{.Names}} {{.Ports}}' | grep -E "${POSTGRES_BIND_ADDR}:$
|
||||
fi
|
||||
|
||||
# Also detect stopped containers reserving legacy port mappings in config (rootlessport conflicts)
|
||||
if podman ps -a --format '{{.Names}} {{.Ports}}' | grep -E "${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}->5432/tcp" | grep -v "bmc-hub-postgres-prod" >/dev/null 2>&1; then
|
||||
if podman ps -a --format '{{.Names}} {{.Ports}}' | grep -E "${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}->5432/tcp" | grep -v "$POSTGRES_CONTAINER" >/dev/null 2>&1; then
|
||||
echo "⚠️ Finder gamle containere med portbinding ${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}; forsøger oprydning..."
|
||||
podman ps -a --format '{{.Names}} {{.Ports}}' \
|
||||
| grep -E "${POSTGRES_BIND_ADDR}:${POSTGRES_PORT}->5432/tcp" \
|
||||
| grep -v "bmc-hub-postgres-prod" \
|
||||
| grep -v "$POSTGRES_CONTAINER" \
|
||||
| awk '{print $1}' \
|
||||
| while read -r holder; do
|
||||
[ -z "$holder" ] && continue
|
||||
@ -140,14 +143,14 @@ if ! podman-compose -f "$PODMAN_COMPOSE_FILE" build --no-cache && podman-compose
|
||||
fi
|
||||
|
||||
# Validate that key containers are actually running after startup
|
||||
if ! podman ps --format '{{.Names}}' | grep -q '^bmc-hub-postgres-prod$'; then
|
||||
echo "❌ Fejl: bmc-hub-postgres-prod kører ikke efter startup"
|
||||
if ! podman ps --format '{{.Names}}' | grep -q "^${POSTGRES_CONTAINER}$"; then
|
||||
echo "❌ Fejl: ${POSTGRES_CONTAINER} kører ikke efter startup"
|
||||
podman ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! podman ps --format '{{.Names}}' | grep -q '^bmc-hub-api-prod$'; then
|
||||
echo "❌ Fejl: bmc-hub-api-prod kører ikke efter startup"
|
||||
if ! podman ps --format '{{.Names}}' | grep -q "^${API_CONTAINER}$"; then
|
||||
echo "❌ Fejl: ${API_CONTAINER} kører ikke efter startup"
|
||||
podman ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
exit 1
|
||||
fi
|
||||
@ -165,7 +168,7 @@ done
|
||||
|
||||
if [ "$HEALTH_OK" != "true" ]; then
|
||||
echo "❌ Fejl: API health fejlede på http://localhost:${API_PORT}/health"
|
||||
podman logs --tail 120 bmc-hub-api-prod || true
|
||||
podman logs --tail 120 "$API_CONTAINER" || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -175,7 +178,7 @@ echo "📁 Syncer migrations fra container til host..."
|
||||
SYNC_OK=false
|
||||
for i in {1..20}; do
|
||||
rm -rf ./migrations_temp
|
||||
if podman cp bmc-hub-api-prod:/app/migrations ./migrations_temp 2>/dev/null; then
|
||||
if podman cp "$API_CONTAINER":/app/migrations ./migrations_temp 2>/dev/null; then
|
||||
rm -rf ./migrations
|
||||
mv ./migrations_temp ./migrations
|
||||
chmod -R 755 ./migrations
|
||||
@ -188,7 +191,7 @@ for i in {1..20}; do
|
||||
done
|
||||
|
||||
if [ "$SYNC_OK" != "true" ]; then
|
||||
echo "❌ Fejl: Kunne ikke sync'e migrations fra bmc-hub-api-prod:/app/migrations"
|
||||
echo "❌ Fejl: Kunne ikke sync'e migrations fra ${API_CONTAINER}:/app/migrations"
|
||||
echo " Afbryder for at undgå kørsel af gamle migrations"
|
||||
exit 1
|
||||
fi
|
||||
@ -216,7 +219,7 @@ if [ "${RUN_MIGRATIONS:-false}" = "true" ]; then
|
||||
fi
|
||||
|
||||
for i in {1..30}; do
|
||||
if podman exec bmc-hub-postgres-prod pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then
|
||||
if podman exec "$POSTGRES_CONTAINER" pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
echo "⏳ Venter på postgres... ($i/30)"
|
||||
@ -224,11 +227,11 @@ if [ "${RUN_MIGRATIONS:-false}" = "true" ]; then
|
||||
done
|
||||
|
||||
echo "📄 Kører alle migrations fra /docker-entrypoint-initdb.d (sorteret)..."
|
||||
podman exec bmc-hub-postgres-prod sh -lc "ls -1 /docker-entrypoint-initdb.d/*.sql 2>/dev/null | sort" \
|
||||
podman exec "$POSTGRES_CONTAINER" sh -lc "ls -1 /docker-entrypoint-initdb.d/*.sql 2>/dev/null | sort" \
|
||||
| while read -r file; do
|
||||
[ -z "$file" ] && continue
|
||||
echo "➡️ $file"
|
||||
podman exec -i bmc-hub-postgres-prod psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -f "$file"
|
||||
podman exec -i "$POSTGRES_CONTAINER" psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" -f "$file"
|
||||
done
|
||||
|
||||
echo "✅ Migrations kørt"
|
||||
@ -240,14 +243,14 @@ fi
|
||||
echo ""
|
||||
echo "📋 Logs fra startup:"
|
||||
echo "================================"
|
||||
podman logs --tail 50 bmc-hub-api-prod
|
||||
podman logs --tail 50 "$API_CONTAINER"
|
||||
|
||||
echo ""
|
||||
echo "✅ Deployment fuldført!"
|
||||
echo ""
|
||||
echo "🔍 Tjek status med:"
|
||||
echo " podman-compose -f $PODMAN_COMPOSE_FILE ps"
|
||||
echo " podman logs -f bmc-hub-api-prod"
|
||||
echo " podman logs -f ${API_CONTAINER}"
|
||||
echo ""
|
||||
echo "🌐 Test health endpoint:"
|
||||
echo " curl http://localhost:${API_PORT}/health"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user