fix: VSM/QSM-financing data not saved
This commit is contained in:
parent
4ca18da706
commit
d9c7356a65
@ -405,8 +405,10 @@ def _payload_from_form_json(form_json: Dict[str, Any], variant: Optional[str]) -
|
|||||||
# Detect variant if AUTO or not specified
|
# Detect variant if AUTO or not specified
|
||||||
if variant is None or variant == "AUTO":
|
if variant is None or variant == "AUTO":
|
||||||
detected_variant = core.detect_variant(form_json)
|
detected_variant = core.detect_variant(form_json)
|
||||||
|
print(f"DEBUG - Variant auto-detected as: {detected_variant}")
|
||||||
else:
|
else:
|
||||||
detected_variant = variant
|
detected_variant = variant
|
||||||
|
print(f"DEBUG - Variant explicitly set to: {detected_variant}")
|
||||||
mapped = core.map_form_to_payload(form_json, detected_variant)
|
mapped = core.map_form_to_payload(form_json, detected_variant)
|
||||||
model = core.payload_to_model(mapped)
|
model = core.payload_to_model(mapped)
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
@ -469,6 +471,9 @@ def create_application(
|
|||||||
# Rate-Limit nach IP
|
# Rate-Limit nach IP
|
||||||
rate_limit_ip(x_forwarded_for or "")
|
rate_limit_ip(x_forwarded_for or "")
|
||||||
|
|
||||||
|
# Debug: Log received variant parameter
|
||||||
|
print(f"DEBUG CREATE - Received variant parameter: '{variant}'")
|
||||||
|
|
||||||
# Payload beschaffen
|
# Payload beschaffen
|
||||||
payload: Dict[str, Any]
|
payload: Dict[str, Any]
|
||||||
raw_form: Optional[Dict[str, Any]] = None
|
raw_form: Optional[Dict[str, Any]] = None
|
||||||
@ -483,6 +488,9 @@ def create_application(
|
|||||||
try:
|
try:
|
||||||
raw = base64.b64decode(form_json_b64)
|
raw = base64.b64decode(form_json_b64)
|
||||||
raw_form = json.loads(raw.decode("utf-8"))
|
raw_form = json.loads(raw.decode("utf-8"))
|
||||||
|
# Debug: Log raw form data for financing fields
|
||||||
|
financing_fields = {k: v for k, v in raw_form.items() if 'financing' in k.lower() or 'qsm' in k.lower() or 'vsm' in k.lower()}
|
||||||
|
print(f"DEBUG CREATE - Raw form financing fields: {json.dumps(financing_fields, indent=2, default=str)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"Invalid form_json_b64: {e}")
|
raise HTTPException(status_code=400, detail=f"Invalid form_json_b64: {e}")
|
||||||
payload, detected_variant = _payload_from_form_json(raw_form, variant or "AUTO")
|
payload, detected_variant = _payload_from_form_json(raw_form, variant or "AUTO")
|
||||||
@ -494,6 +502,12 @@ def create_application(
|
|||||||
if pa_meta.get("id"):
|
if pa_meta.get("id"):
|
||||||
raise HTTPException(status_code=400, detail="pa-id already set; use update endpoint")
|
raise HTTPException(status_code=400, detail="pa-id already set; use update endpoint")
|
||||||
|
|
||||||
|
# Debug: Log financing fields specifically
|
||||||
|
pa_data = payload.get("pa", {})
|
||||||
|
project_data = pa_data.get("project", {})
|
||||||
|
financing_data = project_data.get("financing", {})
|
||||||
|
print(f"DEBUG CREATE - Financing data: {json.dumps(financing_data, indent=2, default=str)}")
|
||||||
|
|
||||||
# Erzeugen in TX
|
# Erzeugen in TX
|
||||||
try:
|
try:
|
||||||
with db.begin():
|
with db.begin():
|
||||||
@ -638,12 +652,21 @@ def update_application(
|
|||||||
try:
|
try:
|
||||||
raw = base64.b64decode(form_json_b64)
|
raw = base64.b64decode(form_json_b64)
|
||||||
raw_form = json.loads(raw.decode("utf-8"))
|
raw_form = json.loads(raw.decode("utf-8"))
|
||||||
|
# Debug: Log raw form data for financing fields
|
||||||
|
financing_fields = {k: v for k, v in raw_form.items() if 'financing' in k.lower() or 'qsm' in k.lower() or 'vsm' in k.lower()}
|
||||||
|
print(f"DEBUG UPDATE - Raw form financing fields: {json.dumps(financing_fields, indent=2, default=str)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=f"Invalid form_json_b64: {e}")
|
raise HTTPException(status_code=400, detail=f"Invalid form_json_b64: {e}")
|
||||||
payload, _ = _payload_from_form_json(raw_form, variant or app_row.variant)
|
payload, _ = _payload_from_form_json(raw_form, variant or app_row.variant)
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=400, detail="Provide either PDF file or form_json_b64")
|
raise HTTPException(status_code=400, detail="Provide either PDF file or form_json_b64")
|
||||||
|
|
||||||
|
# Debug: Log financing fields specifically
|
||||||
|
pa_data = payload.get("pa", {})
|
||||||
|
project_data = pa_data.get("project", {})
|
||||||
|
financing_data = project_data.get("financing", {})
|
||||||
|
print(f"DEBUG UPDATE - Financing data: {json.dumps(financing_data, indent=2, default=str)}")
|
||||||
|
|
||||||
# Immer mit bestehender ID, Key NICHT in DB-Payload speichern
|
# Immer mit bestehender ID, Key NICHT in DB-Payload speichern
|
||||||
render = _inject_meta_for_render(payload, app_row.pa_id, None) # Key nicht neu ausgeben
|
render = _inject_meta_for_render(payload, app_row.pa_id, None) # Key nicht neu ausgeben
|
||||||
store_payload = _sanitize_payload_for_db(payload)
|
store_payload = _sanitize_payload_for_db(payload)
|
||||||
@ -886,6 +909,13 @@ def get_application(
|
|||||||
}
|
}
|
||||||
return StreamingResponse(io.BytesIO(pdf_bytes), media_type="application/pdf", headers=headers)
|
return StreamingResponse(io.BytesIO(pdf_bytes), media_type="application/pdf", headers=headers)
|
||||||
|
|
||||||
|
# Debug: Log financing data from database
|
||||||
|
if app_row.payload_json:
|
||||||
|
pa_data = app_row.payload_json.get("pa", {})
|
||||||
|
project_data = pa_data.get("project", {})
|
||||||
|
financing_data = project_data.get("financing", {})
|
||||||
|
print(f"DEBUG GET - Financing data from DB: {json.dumps(financing_data, indent=2, default=str)}")
|
||||||
|
|
||||||
# Sonst JSON
|
# Sonst JSON
|
||||||
return {
|
return {
|
||||||
"pa_id": app_row.pa_id,
|
"pa_id": app_row.pa_id,
|
||||||
|
|||||||
@ -929,7 +929,7 @@ const AdminDashboard: React.FC = () => {
|
|||||||
zIndex: 1100,
|
zIndex: 1100,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
maxWidth: "calc(100vw - 120px)",
|
maxWidth: "calc(100vw - 300px)",
|
||||||
margin: "0 auto",
|
margin: "0 auto",
|
||||||
pointerEvents: "none", // Allow clicks through the container
|
pointerEvents: "none", // Allow clicks through the container
|
||||||
}}
|
}}
|
||||||
|
|||||||
177
test_financing.py
Normal file
177
test_financing.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to debug financing fields issue in STUPA PDF API
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import base64
|
||||||
|
import requests
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
# Test data with financing fields
|
||||||
|
def create_test_form_data() -> Dict[str, Any]:
|
||||||
|
"""Create test form data with financing fields"""
|
||||||
|
return {
|
||||||
|
# Basic fields
|
||||||
|
"pa-first-name": {"/V": "Test"},
|
||||||
|
"pa-last-name": {"/V": "User"},
|
||||||
|
"pa-email": {"/V": "test@example.com"},
|
||||||
|
"pa-project-name": {"/V": "Test Project"},
|
||||||
|
"pa-start-date": {"/V": "2025-01-01"},
|
||||||
|
"pa-end-date": {"/V": "2025-06-30"},
|
||||||
|
"pa-participants": {"/V": 10},
|
||||||
|
"pa-project-description": {"/V": "Test description"},
|
||||||
|
"pa-requested-amount-euro-sum": {"/V": 1000},
|
||||||
|
|
||||||
|
# Cost positions
|
||||||
|
"pa-cost-1-name": {"/V": "Test Cost"},
|
||||||
|
"pa-cost-1-amount-euro": {"/V": 1000},
|
||||||
|
|
||||||
|
# QSM Financing fields - this is what should be saved but might be missing
|
||||||
|
"pa-qsm-financing": {"/V": "vwv-3-2-1-1"},
|
||||||
|
"pa-qsm-stellenfinanzierungen": {"/V": True},
|
||||||
|
"pa-qsm-studierende": {"/V": True},
|
||||||
|
"pa-qsm-individuell": {"/V": True},
|
||||||
|
|
||||||
|
# VSM Financing fields
|
||||||
|
"pa-vsm-financing": {"/V": "lhg-01"},
|
||||||
|
"pa-vsm-aufgaben": {"/V": True},
|
||||||
|
"pa-vsm-individuell": {"/V": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_create_application():
|
||||||
|
"""Test creating an application with financing fields"""
|
||||||
|
print("=== Testing CREATE Application ===")
|
||||||
|
|
||||||
|
form_data = create_test_form_data()
|
||||||
|
form_json = json.dumps(form_data)
|
||||||
|
form_json_b64 = base64.b64encode(form_json.encode('utf-8')).decode('utf-8')
|
||||||
|
|
||||||
|
# Test QSM variant
|
||||||
|
print("\n--- Testing QSM Application ---")
|
||||||
|
response = requests.post(
|
||||||
|
"http://localhost:8000/applications",
|
||||||
|
params={
|
||||||
|
"return_format": "json",
|
||||||
|
"variant": "QSM"
|
||||||
|
},
|
||||||
|
data={
|
||||||
|
"form_json_b64": form_json_b64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Status Code: {response.status_code}")
|
||||||
|
if response.status_code == 200:
|
||||||
|
# Check if we got JSON or PDF
|
||||||
|
content_type = response.headers.get('content-type', '')
|
||||||
|
if 'application/json' in content_type:
|
||||||
|
data = response.json()
|
||||||
|
print(f"Created Application: {data['pa_id']}")
|
||||||
|
print(f"Key: {data['pa_key']}")
|
||||||
|
return data['pa_id'], data['pa_key']
|
||||||
|
else:
|
||||||
|
# PDF response, extract from headers
|
||||||
|
pa_id = response.headers.get('X-PA-ID')
|
||||||
|
pa_key = response.headers.get('X-PA-KEY')
|
||||||
|
print(f"Created Application: {pa_id}")
|
||||||
|
print(f"Key: {pa_key}")
|
||||||
|
return pa_id, pa_key
|
||||||
|
else:
|
||||||
|
print(f"Error: {response.text}")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def test_update_application(pa_id: str, pa_key: str):
|
||||||
|
"""Test updating an application with financing fields"""
|
||||||
|
print(f"\n=== Testing UPDATE Application {pa_id} ===")
|
||||||
|
|
||||||
|
# Create form data with updated financing fields
|
||||||
|
form_data = create_test_form_data()
|
||||||
|
# Change financing code to test if it saves
|
||||||
|
form_data["pa-qsm-financing"] = {"/V": "vwv-3-2-1-2"} # Different value
|
||||||
|
|
||||||
|
form_json = json.dumps(form_data)
|
||||||
|
form_json_b64 = base64.b64encode(form_json.encode('utf-8')).decode('utf-8')
|
||||||
|
|
||||||
|
response = requests.put(
|
||||||
|
f"http://localhost:8000/applications/{pa_id}",
|
||||||
|
params={
|
||||||
|
"return_format": "json"
|
||||||
|
},
|
||||||
|
data={
|
||||||
|
"form_json_b64": form_json_b64
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-PA-KEY": pa_key
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Status Code: {response.status_code}")
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Error: {response.text}")
|
||||||
|
|
||||||
|
def test_get_application(pa_id: str, pa_key: str):
|
||||||
|
"""Test retrieving an application to check if financing fields are saved"""
|
||||||
|
print(f"\n=== Testing GET Application {pa_id} ===")
|
||||||
|
|
||||||
|
response = requests.get(
|
||||||
|
f"http://localhost:8000/applications/{pa_id}",
|
||||||
|
headers={
|
||||||
|
"X-PA-KEY": pa_key
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Status Code: {response.status_code}")
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# Check financing fields - correct payload structure
|
||||||
|
payload = data.get('payload', {})
|
||||||
|
pa = payload.get('pa', {})
|
||||||
|
project = pa.get('project', {})
|
||||||
|
financing = project.get('financing', {})
|
||||||
|
|
||||||
|
print(f"\nFinancing data in response:")
|
||||||
|
print(json.dumps(financing, indent=2))
|
||||||
|
|
||||||
|
# Check specific fields
|
||||||
|
qsm = financing.get('qsm', {})
|
||||||
|
vsm = financing.get('vsm', {})
|
||||||
|
|
||||||
|
print(f"\nQSM financing code: {qsm.get('code')}")
|
||||||
|
print(f"QSM flags: {qsm.get('flags')}")
|
||||||
|
print(f"VSM financing code: {vsm.get('code')}")
|
||||||
|
print(f"VSM flags: {vsm.get('flags')}")
|
||||||
|
|
||||||
|
# Check if fields are missing (the main issue)
|
||||||
|
if not qsm.get('code') and not vsm.get('code'):
|
||||||
|
print("\n❌ ISSUE FOUND: No financing code saved!")
|
||||||
|
else:
|
||||||
|
print("\n✅ Financing code found")
|
||||||
|
|
||||||
|
if not qsm.get('flags') and not vsm.get('flags'):
|
||||||
|
print("❌ ISSUE FOUND: No financing flags saved!")
|
||||||
|
else:
|
||||||
|
print("✅ Financing flags found")
|
||||||
|
else:
|
||||||
|
print(f"Error: {response.text}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run all tests"""
|
||||||
|
print("🧪 Testing Financing Fields Issue")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# Create application
|
||||||
|
pa_id, pa_key = test_create_application()
|
||||||
|
|
||||||
|
if pa_id and pa_key:
|
||||||
|
# Update application
|
||||||
|
test_update_application(pa_id, pa_key)
|
||||||
|
|
||||||
|
# Check if data was saved correctly
|
||||||
|
test_get_application(pa_id, pa_key)
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("🔍 Check the API logs with: docker compose logs api | grep DEBUG")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user