fix(csv-import): Normalize source unit representation and update CI workflows
- Changed source unit representation from "kJ" to "kj" for consistency across CSV templates and migrations. - Updated CI workflow to enhance testing conditions, ensuring tests run in the correct environment based on deployment context. - Improved job steps for backend testing and syntax checking by utilizing deployed application directories, streamlining the CI process.
This commit is contained in:
parent
0d0ab62674
commit
bb6eefc837
|
|
@ -36,9 +36,7 @@ INSERT INTO csv_field_mappings (
|
||||||
},
|
},
|
||||||
"kcal": {
|
"kcal": {
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"source_unit": "kJ",
|
"source_unit": "kj",
|
||||||
"target_unit": "kcal",
|
|
||||||
"conversion_factor": 0.239,
|
|
||||||
"decimal_separator": ","
|
"decimal_separator": ","
|
||||||
},
|
},
|
||||||
"fat_g": {
|
"fat_g": {
|
||||||
|
|
|
||||||
|
|
@ -8,54 +8,83 @@ on:
|
||||||
types: [completed]
|
types: [completed]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pytest-backend-csv:
|
pytest-backend:
|
||||||
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Run backend pytest suite in deployed container
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
# Debian 12 ARM64 runner hat fuer 3.12 oft kein setup-python Build.
|
|
||||||
# 3.11 ist dort breit verfuegbar und fuer unsere Tests ausreichend.
|
|
||||||
python-version: "3.11"
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
run: |
|
||||||
pip install -r backend/requirements.txt -r backend/requirements-dev.txt
|
EVENT_NAME="${{ github.event_name }}"
|
||||||
- name: Pytest — CSV-Import & Parser (Smoke)
|
REF_NAME="${{ github.ref_name }}"
|
||||||
run: |
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
cd backend
|
APP_DIR="/home/lars/docker/bodytrack"
|
||||||
python -m pytest tests/test_csv_parser_core.py tests/test_csv_import_executor.py tests/test_mapping_suggest.py -q --tb=short
|
COMPOSE_FILE="docker-compose.yml"
|
||||||
|
|
||||||
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
||||||
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
||||||
|
fi
|
||||||
|
elif [ "$REF_NAME" = "develop" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
COMPOSE_FILE="docker-compose.dev-env.yml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$APP_DIR"
|
||||||
|
docker compose -f "$COMPOSE_FILE" exec -T backend sh -lc "
|
||||||
|
pip install -r /app/requirements-dev.txt &&
|
||||||
|
cd /app &&
|
||||||
|
python -m pytest \
|
||||||
|
tests/test_csv_parser_core.py \
|
||||||
|
tests/test_csv_import_executor.py \
|
||||||
|
tests/test_mapping_suggest.py \
|
||||||
|
tests/test_placeholder_metadata.py \
|
||||||
|
tests/test_placeholder_metadata_v2.py \
|
||||||
|
-q --tb=short
|
||||||
|
"
|
||||||
|
|
||||||
lint-backend:
|
lint-backend:
|
||||||
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Check backend syntax on deployed app
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
- name: Check backend syntax
|
|
||||||
run: |
|
run: |
|
||||||
python -m py_compile backend/main.py
|
EVENT_NAME="${{ github.event_name }}"
|
||||||
|
REF_NAME="${{ github.ref_name }}"
|
||||||
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack"
|
||||||
|
|
||||||
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
||||||
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
fi
|
||||||
|
elif [ "$REF_NAME" = "develop" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 -m py_compile "$APP_DIR/backend/main.py"
|
||||||
echo "✓ Backend syntax OK"
|
echo "✓ Backend syntax OK"
|
||||||
|
|
||||||
build-frontend:
|
build-frontend:
|
||||||
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Build frontend on deployed app
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: "20"
|
|
||||||
- name: Build frontend
|
|
||||||
run: |
|
run: |
|
||||||
cd frontend
|
EVENT_NAME="${{ github.event_name }}"
|
||||||
|
REF_NAME="${{ github.ref_name }}"
|
||||||
|
RUN_WORKFLOW="${{ github.event.workflow_run.name }}"
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack"
|
||||||
|
|
||||||
|
if [ "$EVENT_NAME" = "workflow_run" ]; then
|
||||||
|
if [ "$RUN_WORKFLOW" = "Deploy Development" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
fi
|
||||||
|
elif [ "$REF_NAME" = "develop" ]; then
|
||||||
|
APP_DIR="/home/lars/docker/bodytrack-dev"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$APP_DIR/frontend"
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
echo "✓ Frontend build OK"
|
echo "✓ Frontend build OK"
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,7 @@ SELECT
|
||||||
},
|
},
|
||||||
"kcal": {
|
"kcal": {
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"source_unit": "kJ",
|
"source_unit": "kj",
|
||||||
"target_unit": "kcal",
|
|
||||||
"conversion_factor": 0.239,
|
|
||||||
"decimal_separator": ","
|
"decimal_separator": ","
|
||||||
},
|
},
|
||||||
"fat_g": {"type": "float", "decimal_separator": ","},
|
"fat_g": {"type": "float", "decimal_separator": ","},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
-- Migration 046: FDDB-Systemvorlage — kcal ohne legacy conversion_factor/target_unit (Issue #21, source_unit-Registry)
|
||||||
|
-- Doppelte Umrechnung (kj-Faktor * 0.239) wurde fälschlich gespeichert; target_unit ist nur für duration vorgesehen.
|
||||||
|
|
||||||
|
UPDATE csv_field_mappings
|
||||||
|
SET type_conversions = jsonb_set(
|
||||||
|
type_conversions,
|
||||||
|
'{kcal}',
|
||||||
|
((type_conversions->'kcal') - 'conversion_factor' - 'target_unit')
|
||||||
|
|| jsonb_build_object('source_unit', 'kj')
|
||||||
|
)
|
||||||
|
WHERE is_system = true
|
||||||
|
AND profile_id IS NULL
|
||||||
|
AND module = 'nutrition'
|
||||||
|
AND mapping_name = 'FDDB Export (Standard)'
|
||||||
|
AND (type_conversions->'kcal') IS NOT NULL
|
||||||
|
AND (
|
||||||
|
(type_conversions->'kcal') ? 'conversion_factor'
|
||||||
|
OR (type_conversions->'kcal') ? 'target_unit'
|
||||||
|
);
|
||||||
|
|
@ -182,7 +182,11 @@ export default function AdminCsvTemplateEditorPage() {
|
||||||
const opts = modMeta?.fields?.[fieldKey]?.source_unit_options || []
|
const opts = modMeta?.fields?.[fieldKey]?.source_unit_options || []
|
||||||
const canonical = opts.find((o) => o.is_canonical)?.id || opts[0]?.id
|
const canonical = opts.find((o) => o.is_canonical)?.id || opts[0]?.id
|
||||||
const su = tc[fieldKey]?.source_unit
|
const su = tc[fieldKey]?.source_unit
|
||||||
if (su && opts.some((o) => o.id === su)) return su
|
if (su != null && su !== '') {
|
||||||
|
const sid = String(su).toLowerCase()
|
||||||
|
const hit = opts.find((o) => o.id === sid)
|
||||||
|
if (hit) return hit.id
|
||||||
|
}
|
||||||
return canonical || ''
|
return canonical || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,6 +209,8 @@ export default function AdminCsvTemplateEditorPage() {
|
||||||
} else {
|
} else {
|
||||||
base.source_unit = sourceUnitId
|
base.source_unit = sourceUnitId
|
||||||
}
|
}
|
||||||
|
delete base.target_unit
|
||||||
|
delete base.conversion_factor
|
||||||
tc[fieldKey] = base
|
tc[fieldKey] = base
|
||||||
setTypeConversionsText(JSON.stringify(tc, null, 2))
|
setTypeConversionsText(JSON.stringify(tc, null, 2))
|
||||||
setError(null)
|
setError(null)
|
||||||
|
|
@ -586,7 +592,9 @@ export default function AdminCsvTemplateEditorPage() {
|
||||||
<div className="form-label">3b. Quelleinheit (optional)</div>
|
<div className="form-label">3b. Quelleinheit (optional)</div>
|
||||||
<p style={{ fontSize: 13, color: 'var(--text2)', marginTop: 8, lineHeight: 1.55 }}>
|
<p style={{ fontSize: 13, color: 'var(--text2)', marginTop: 8, lineHeight: 1.55 }}>
|
||||||
Ziel-Einheit kommt aus dem Datenmodell (z. B. kcal, g, kg, km). Hier nur angeben, falls die CSV
|
Ziel-Einheit kommt aus dem Datenmodell (z. B. kcal, g, kg, km). Hier nur angeben, falls die CSV
|
||||||
abweicht (z. B. FDDB kJ → kcal, Makros in kg → g, Gewicht in lb → kg).
|
abweicht (z. B. FDDB kJ → kcal, Makros in kg → g, Gewicht in lb → kg). Beim Ändern hier werden
|
||||||
|
pro Feld <code>conversion_factor</code> und <code>target_unit</code> entfernt (verhindert
|
||||||
|
Doppel-Umrechnung); bei Bedarf wieder in Abschnitt 4 ergänzen.
|
||||||
</p>
|
</p>
|
||||||
<div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 12 }}>
|
<div style={{ marginTop: 14, display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||||
{unitTargets.map(({ field: fkey, options }) => (
|
{unitTargets.map(({ field: fkey, options }) => (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user