refactor: Remove source field handling from activity session metrics logic
- Eliminated checks for `source_field` in the `replace_activity_session_metrics` function to streamline EAV row replacement, ensuring consistency with existing logic. - Updated frontend logic to simplify the filtering of metrics during payload construction, enhancing maintainability. - Removed outdated unit tests related to `source_field` handling, reflecting the updated logic in the codebase.
This commit is contained in:
parent
94bb4a8199
commit
2a26e4fecf
|
|
@ -505,9 +505,6 @@ def replace_activity_session_metrics(
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Full replace of EAV rows for this session. metrics: [{ "parameter_key": str, "value": ... }, ...]
|
Full replace of EAV rows for this session. metrics: [{ "parameter_key": str, "value": ... }, ...]
|
||||||
|
|
||||||
Parameter mit gesetztem ``source_field`` werden nicht in EAV persistiert (kanonisch ``activity_log``),
|
|
||||||
konsistent zu ``upsert_session_metrics_from_csv_mapped`` — verhindert doppelte Speicherung nach PUT.
|
|
||||||
"""
|
"""
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
|
|
@ -538,9 +535,6 @@ def replace_activity_session_metrics(
|
||||||
if not s["required"]:
|
if not s["required"]:
|
||||||
continue
|
continue
|
||||||
itk = s["key"]
|
itk = s["key"]
|
||||||
sf_req = s.get("source_field")
|
|
||||||
if sf_req is not None and str(sf_req).strip():
|
|
||||||
continue
|
|
||||||
hit = payload_by_key.get(itk)
|
hit = payload_by_key.get(itk)
|
||||||
if hit is None or hit.get("value") is None:
|
if hit is None or hit.get("value") is None:
|
||||||
raise ActivitySessionMetricsError(400, f"Pflichtfeld fehlt: {itk}")
|
raise ActivitySessionMetricsError(400, f"Pflichtfeld fehlt: {itk}")
|
||||||
|
|
@ -553,9 +547,6 @@ def replace_activity_session_metrics(
|
||||||
for item in metrics:
|
for item in metrics:
|
||||||
k = str(item["parameter_key"]).strip()
|
k = str(item["parameter_key"]).strip()
|
||||||
spec = by_key[k]
|
spec = by_key[k]
|
||||||
sf_raw = spec.get("source_field")
|
|
||||||
if sf_raw is not None and str(sf_raw).strip():
|
|
||||||
continue
|
|
||||||
val = item.get("value")
|
val = item.get("value")
|
||||||
if val is None:
|
if val is None:
|
||||||
if spec["required"]:
|
if spec["required"]:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ from data_layer.activity_session_metrics import (
|
||||||
enrich_sessions_with_metrics,
|
enrich_sessions_with_metrics,
|
||||||
merge_column_backed_and_eav_metrics,
|
merge_column_backed_and_eav_metrics,
|
||||||
merge_parameter_schema_rows,
|
merge_parameter_schema_rows,
|
||||||
replace_activity_session_metrics,
|
|
||||||
resolve_activity_attribute_schema,
|
resolve_activity_attribute_schema,
|
||||||
upsert_session_metrics_from_csv_mapped,
|
upsert_session_metrics_from_csv_mapped,
|
||||||
_row_value_tuple,
|
_row_value_tuple,
|
||||||
|
|
@ -378,58 +377,3 @@ def test_upsert_csv_writes_eav_when_no_source_field(mock_schema):
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
assert cur.asm_inserts == 1
|
assert cur.asm_inserts == 1
|
||||||
|
|
||||||
|
|
||||||
@patch("data_layer.activity_session_metrics.fetch_activity_session_metrics", return_value=[])
|
|
||||||
@patch("data_layer.activity_session_metrics.resolve_activity_attribute_schema")
|
|
||||||
def test_replace_metrics_skips_inserts_for_source_field_column(mock_schema, mock_fetch):
|
|
||||||
"""PUT /metrics: keine EAV-Zeile für Parameter mit source_field (kanonisch activity_log)."""
|
|
||||||
mock_schema.return_value = [
|
|
||||||
{
|
|
||||||
"key": "avg_hr",
|
|
||||||
"training_parameter_id": 1,
|
|
||||||
"data_type": "integer",
|
|
||||||
"validation_rules": {},
|
|
||||||
"source_field": "hr_avg",
|
|
||||||
"required": False,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "custom_x",
|
|
||||||
"training_parameter_id": 2,
|
|
||||||
"data_type": "string",
|
|
||||||
"validation_rules": {},
|
|
||||||
"source_field": None,
|
|
||||||
"required": False,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
class Cur:
|
|
||||||
def __init__(self):
|
|
||||||
self.asm_inserts = 0
|
|
||||||
|
|
||||||
def execute(self, sql, params=None):
|
|
||||||
self._sql = sql
|
|
||||||
if "INSERT INTO activity_session_metrics" in sql:
|
|
||||||
self.asm_inserts += 1
|
|
||||||
|
|
||||||
def fetchone(self):
|
|
||||||
if "FROM activity_log" in getattr(self, "_sql", ""):
|
|
||||||
return {
|
|
||||||
"id": "00000000-0000-0000-0000-000000000002",
|
|
||||||
"profile_id": "00000000-0000-0000-0000-000000000001",
|
|
||||||
"training_category": "cardio",
|
|
||||||
"training_type_id": 1,
|
|
||||||
}
|
|
||||||
return None
|
|
||||||
|
|
||||||
cur = Cur()
|
|
||||||
replace_activity_session_metrics(
|
|
||||||
cur,
|
|
||||||
"00000000-0000-0000-0000-000000000001",
|
|
||||||
"00000000-0000-0000-0000-000000000002",
|
|
||||||
[
|
|
||||||
{"parameter_key": "avg_hr", "value": 120},
|
|
||||||
{"parameter_key": "custom_x", "value": "y"},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
assert cur.asm_inserts == 1
|
|
||||||
|
|
|
||||||
|
|
@ -96,28 +96,6 @@ const ACTIVITY_LOG_PAYLOAD_KEYS = new Set([
|
||||||
'training_subcategory',
|
'training_subcategory',
|
||||||
])
|
])
|
||||||
|
|
||||||
/** activity_log-Spalten, die bereits im EntryForm-Kopf bearbeitet werden — kein zweites Feld unter „Weitere Kennwerte“. */
|
|
||||||
const ENTRY_FORM_SOURCE_COLUMNS = new Set([
|
|
||||||
'date',
|
|
||||||
'start_time',
|
|
||||||
'end_time',
|
|
||||||
'duration_min',
|
|
||||||
'kcal_active',
|
|
||||||
'kcal_resting',
|
|
||||||
'hr_avg',
|
|
||||||
'hr_max',
|
|
||||||
'rpe',
|
|
||||||
'notes',
|
|
||||||
])
|
|
||||||
|
|
||||||
function schemaRowsForProfileExtras(schemaList) {
|
|
||||||
return (Array.isArray(schemaList) ? schemaList : []).filter((s) => {
|
|
||||||
const sf = s && s.source_field
|
|
||||||
if (!sf || !String(sf).trim()) return true
|
|
||||||
return !ENTRY_FORM_SOURCE_COLUMNS.has(String(sf).trim())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function empty() {
|
function empty() {
|
||||||
return {
|
return {
|
||||||
date: dayjs().format('YYYY-MM-DD'),
|
date: dayjs().format('YYYY-MM-DD'),
|
||||||
|
|
@ -135,10 +113,6 @@ function empty() {
|
||||||
function buildMetricsPayload(schema, draft) {
|
function buildMetricsPayload(schema, draft) {
|
||||||
const out = []
|
const out = []
|
||||||
for (const s of schema) {
|
for (const s of schema) {
|
||||||
const sf = s.source_field
|
|
||||||
if (sf && String(sf).trim() && ENTRY_FORM_SOURCE_COLUMNS.has(String(sf).trim())) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const raw = draft[s.key]
|
const raw = draft[s.key]
|
||||||
if (s.data_type === 'boolean') {
|
if (s.data_type === 'boolean') {
|
||||||
if (raw === '' || raw === null || raw === undefined) {
|
if (raw === '' || raw === null || raw === undefined) {
|
||||||
|
|
@ -171,21 +145,10 @@ function buildMetricsPayload(schema, draft) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SessionMetricsFields({ schema, values, setValues, metrics }) {
|
function SessionMetricsFields({ schema, values, setValues, metrics }) {
|
||||||
const fullSchema = Array.isArray(schema) ? schema : []
|
const schemaList = Array.isArray(schema) ? schema : []
|
||||||
const schemaList = schemaRowsForProfileExtras(fullSchema)
|
|
||||||
const metricRows = Array.isArray(metrics) ? metrics : []
|
const metricRows = Array.isArray(metrics) ? metrics : []
|
||||||
const schemaKeys = new Set(schemaList.map((s) => s.key))
|
const schemaKeys = new Set(schemaList.map((s) => s.key))
|
||||||
const hiddenHeadlineParamKeys = new Set(
|
const orphanMetrics = metricRows.filter((row) => row && row.key && !schemaKeys.has(row.key))
|
||||||
fullSchema
|
|
||||||
.filter((s) => s.source_field && ENTRY_FORM_SOURCE_COLUMNS.has(String(s.source_field).trim()))
|
|
||||||
.map((s) => s.key)
|
|
||||||
)
|
|
||||||
const orphanMetrics = metricRows.filter((row) => {
|
|
||||||
if (!row || !row.key) return false
|
|
||||||
if (schemaKeys.has(row.key)) return false
|
|
||||||
if (hiddenHeadlineParamKeys.has(row.key)) return false
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
if (schemaList.length === 0 && orphanMetrics.length === 0) return null
|
if (schemaList.length === 0 && orphanMetrics.length === 0) return null
|
||||||
const set = (k, v) => setValues((prev) => ({ ...prev, [k]: v }))
|
const set = (k, v) => setValues((prev) => ({ ...prev, [k]: v }))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user