fix(csv): export dal browser legge nominale/tolleranze/descrizione da m.subtask (#31)
buildMeasurementCSV leggeva m.subtask_name/unit/nominal/tolerance_plus/ tolerance_minus/operator_name: nessuno di questi campi esiste su MeasurementResponse. I dati reali stanno annidati in m.subtask (description, unit, nominal, utl, ltl - misurati.py:task_complete() li allega lato server). tolleranza + = utl-nominal, tolleranza - = nominal-ltl, solo quando entrambi i lati sono presenti (nessun NaN su tolleranza a un lato solo). Unità dalla quota, "mm" solo se assente. Operatore: measured_by (id), l'unico campo reale - non esiste un nome operatore da nessuna parte in questi dati. Test node in tests/js/test_csv_export.js (stesso pattern di test_numpad.js). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -71,22 +71,38 @@ function csvExport() {
|
||||
let csv = headers.join(this.delimiter) + '\n';
|
||||
|
||||
for (const m of measurements) {
|
||||
// MeasurementResponse (src/backend/models/api/measurement.py) carries
|
||||
// none of subtask_name/unit/nominal/tolerance_plus/tolerance_minus -
|
||||
// that data lives nested under m.subtask (attached server-side in
|
||||
// measure.py's task_complete(), see subtask/task_info enrichment).
|
||||
// Reading the flat, nonexistent names is why every one of these
|
||||
// columns came out empty (#31).
|
||||
const subtask = m.subtask || {};
|
||||
const nominal = subtask.nominal;
|
||||
const tolerancePlus = this.hasNumber(subtask.utl) && this.hasNumber(nominal)
|
||||
? subtask.utl - nominal : null;
|
||||
const toleranceMinus = this.hasNumber(nominal) && this.hasNumber(subtask.ltl)
|
||||
? nominal - subtask.ltl : null;
|
||||
|
||||
const row = [
|
||||
m.id || '',
|
||||
m.subtask_id || '',
|
||||
this.escapeCsvValue(m.subtask_name || ''),
|
||||
this.escapeCsvValue(subtask.description || ''),
|
||||
this.formatNumber(m.value),
|
||||
this.escapeCsvValue(m.unit || 'mm'),
|
||||
this.formatNumber(m.nominal),
|
||||
this.formatNumber(m.tolerance_plus),
|
||||
this.formatNumber(m.tolerance_minus),
|
||||
this.escapeCsvValue(subtask.unit || 'mm'),
|
||||
this.formatNumber(nominal),
|
||||
this.formatNumber(tolerancePlus),
|
||||
this.formatNumber(toleranceMinus),
|
||||
this.formatNumber(m.deviation),
|
||||
m.pass_fail || '',
|
||||
this.escapeCsvValue(m.lot_number || ''),
|
||||
this.escapeCsvValue(m.serial_number || ''),
|
||||
m.input_method || '',
|
||||
this.formatDateTime(m.measured_at),
|
||||
this.escapeCsvValue(m.operator_name || '')
|
||||
// No operator name anywhere on this object (or on
|
||||
// MeasurementResponse) - measured_by is the real field, the
|
||||
// user's id who took the reading.
|
||||
this.escapeCsvValue(this.hasNumber(m.measured_by) ? m.measured_by : '')
|
||||
];
|
||||
csv += row.join(this.delimiter) + '\n';
|
||||
}
|
||||
@@ -163,6 +179,13 @@ function csvExport() {
|
||||
URL.revokeObjectURL(url);
|
||||
},
|
||||
|
||||
/**
|
||||
* True for a value that is actually a usable number (not null/undefined/NaN).
|
||||
*/
|
||||
hasNumber(value) {
|
||||
return typeof value === 'number' && !Number.isNaN(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Format number with Italian decimal separator
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user