Update model data for river and marine ftp to centralize with mms 1.0 setup

This commit is contained in:
ALim Aidrus 2025-11-25 09:42:32 +08:00
parent 033391b770
commit b97aa7ddf9
8 changed files with 210 additions and 174 deletions

View File

@ -101,7 +101,7 @@ class _HomePageState extends State<HomePage> {
);
},
),
title: const Text("MMS Version 3.12.01"),
title: const Text("MMS Version 3.12.03"),
actions: [
IconButton(
icon: const Icon(Icons.person),

View File

@ -308,99 +308,117 @@ class InSituSamplingData {
};
}
/// Creates a single JSON object with all submission data, mimicking 'db.json'
/// Creates a single JSON object with all submission data, mimicking 'db.json'
String toDbJson() {
// This is a direct conversion of the model's properties to a map,
// with keys matching the expected 'db.json' file format.
final data = {
'battery_cap': batteryVoltage == -999.0 ? null : batteryVoltage,
'device_name': sondeId,
'sampling_type': samplingType,
'report_id': reportId,
'sampler_2ndname': secondSampler?['first_name'],
'sample_state': selectedStateName,
'station_id': selectedStation?['man_station_code'],
'tech_id': firstSamplerUserId,
'tech_phonenum': null, // This field was not in the model
'tech_name': firstSamplerName,
'latitude': stationLatitude,
'longitude': stationLongitude,
'record_dt': '$samplingDate $samplingTime',
'do_mgl': oxygenConcentration == -999.0 ? null : oxygenConcentration,
'do_sat': oxygenSaturation == -999.0 ? null : oxygenSaturation,
'ph': ph == -999.0 ? null : ph,
'salinity': salinity == -999.0 ? null : salinity,
'tss': tss == -999.0 ? null : tss,
'temperature': temperature == -999.0 ? null : temperature,
'turbidity': turbidity == -999.0 ? null : turbidity,
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'sample_id': sampleIdCode,
'tarball': "", // <-- MODIFIED: Hardcoded to "N/A"
'weather': weather,
'tide_lvl': tideLevel,
'sea_cond': seaCondition,
'remarks_event': eventRemarks,
'remarks_lab': labRemarks,
// --- Sorted exactly according to your Marine db.json sample ---
'battery_cap': batteryVoltage ?? -999.0,
'device_name': sondeId ?? "",
'sampling_type': samplingType ?? "",
'report_id': reportId ?? "",
'sampler_2ndname': secondSampler?['first_name'] ?? "",
'sample_state': selectedStateName ?? "",
'station_id': selectedStation?['man_station_code'] ?? "",
'tech_id': firstSamplerUserId ?? -999, // Default to -999 for int
'tech_phonenum': "", // Not in model, default to empty string
'tech_name': firstSamplerName ?? "",
'latitude': stationLatitude ?? "",
'longitude': stationLongitude ?? "",
'record_dt': (samplingDate != null && samplingTime != null)
? '$samplingDate $samplingTime'
: "",
// --- Sensor Readings ---
'do_mgl': oxygenConcentration ?? -999.0,
'do_sat': oxygenSaturation ?? -999.0,
'ph': ph ?? -999.0,
'salinity': salinity ?? -999.0,
'tss': tss ?? -999.0,
'temperature': temperature ?? -999.0,
'turbidity': turbidity ?? -999.0,
'tds': tds ?? -999.0,
'electric_conductivity': electricalConductivity ?? -999.0,
// --- Manual/Observations ---
'sample_id': sampleIdCode ?? "",
'tarball': "No", // Field removed from model logic, default to empty
'weather': weather ?? "",
'tide_lvl': tideLevel ?? "",
'sea_cond': seaCondition ?? "",
'remarks_event': eventRemarks ?? "",
'remarks_lab': labRemarks ?? "",
};
// Remove null values before encoding
//data.removeWhere((key, value) => value == null);
// DO NOT UNCOMMENT. Keeps all keys even if values are null/default.
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for basic form info, mimicking 'marine_insitu_basic_form.json'.
String toBasicFormJson() {
final data = {
'tech_name': firstSamplerName,
'sampler_2ndname': secondSampler?['first_name'], // Assuming 'first_name' key
'sample_date': samplingDate,
'sample_time': samplingTime,
'sampling_type': samplingType,
'sample_state': selectedStateName,
'station_id': selectedStation?['man_station_code'], // Marine-specific key
'station_latitude': stationLatitude,
'station_longitude': stationLongitude,
'latitude': currentLatitude,
'longitude': currentLongitude,
'sample_id': sampleIdCode,
// --- Sorted exactly according to your Marine sample ---
'tech_name': firstSamplerName ?? "",
'sampler_2ndname': secondSampler?['first_name'] ?? "",
'sample_date': samplingDate ?? "",
'sample_time': samplingTime ?? "",
'sampling_type': samplingType ?? "",
'sample_state': selectedStateName ?? "",
'sample_category': selectedCategoryName ?? "", // Added to match sample
'station_id': selectedStation?['man_station_code'] ?? "",
'station_latitude': stationLatitude ?? "",
'station_longitude': stationLongitude ?? "",
'latitude': currentLatitude ?? "",
'longitude': currentLongitude ?? "",
'sample_id': sampleIdCode ?? "",
};
// Remove null values before encoding
data.removeWhere((key, value) => value == null);
// DO NOT UNCOMMENT
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for sensor readings, mimicking 'marine_sampling_reading.json'.
String toReadingJson() {
final data = {
'do_mgl': oxygenConcentration == -999.0 ? null : oxygenConcentration,
'do_sat': oxygenSaturation == -999.0 ? null : oxygenSaturation,
'ph': ph == -999.0 ? null : ph,
'salinity': salinity == -999.0 ? null : salinity,
'tds': tds == -999.0 ? null : tds,
'tss': tss == -999.0 ? null : tss,
'temperature': temperature == -999.0 ? null : temperature,
'turbidity': turbidity == -999.0 ? null : turbidity,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'date_sampling_reading': dataCaptureDate,
'time_sampling_reading': dataCaptureTime,
// --- Sorted exactly according to your Marine sample ---
'do_mgl': oxygenConcentration ?? -999.0,
'do_sat': oxygenSaturation ?? -999.0,
'ph': ph ?? -999.0,
'salinity': salinity ?? -999.0,
'tds': tds ?? -999.0,
'tss': tss ?? -999.0,
'temperature': temperature ?? -999.0,
'turbidity': turbidity ?? -999.0,
'electric_conductivity': electricalConductivity ?? -999.0,
'date_sampling_reading': dataCaptureDate ?? "",
'time_sampling_reading': dataCaptureTime ?? "",
};
// Remove null values before encoding
data.removeWhere((key, value) => value == null);
// DO NOT UNCOMMENT
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for manual info, mimicking 'marine_manual_info.json'.
String toManualInfoJson() {
final data = {
'tarball': "", // <-- MODIFIED: Hardcoded to "N/A"
'weather': weather,
'tide_lvl': tideLevel,
'sea_cond': seaCondition,
'remarks_event': eventRemarks,
'remarks_lab': labRemarks,
// --- Sorted exactly according to your Marine sample ---
'tarball': "", // Field removed from model logic, default to empty
'weather': weather ?? "",
'tide_lvl': tideLevel ?? "",
'sea_cond': seaCondition ?? "",
'remarks_event': eventRemarks ?? "",
'remarks_lab': labRemarks ?? "",
};
// Remove null values before encoding
data.removeWhere((key, value) => value == null);
// DO NOT UNCOMMENT
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}

View File

@ -316,91 +316,99 @@ class RiverInSituSamplingData {
};
}
/// Creates a single JSON object with all submission data, mimicking 'db.json'
String toDbJson() {
// This is a direct conversion of the model's properties to a map,
// with keys matching the expected JSON file format.
final data = {
// --- START FIX: Map model properties to correct db.json keys ---
'battery_cap': batteryVoltage == -999.0 ? null : batteryVoltage, // Handle -999
'device_name': sondeId,
'sampling_type': samplingType,
'report_id': reportId,
'sampler_2ndname': secondSampler?['first_name'], // Use first_name as likely user name
'sample_state': selectedStateName,
'station_id': selectedStation?['sampling_station_code'],
'tech_id': firstSamplerUserId,
'tech_name': firstSamplerName,
'latitude': stationLatitude, // Assuming station lat/lon is intended here
'longitude': stationLongitude, // Assuming station lat/lon is intended here
'record_dt': '$samplingDate $samplingTime',
'do_mgl': oxygenConcentration == -999.0 ? null : oxygenConcentration,
'do_sat': oxygenSaturation == -999.0 ? null : oxygenSaturation,
'ph': ph == -999.0 ? null : ph,
'salinity': salinity == -999.0 ? null : salinity,
'temperature': temperature == -999.0 ? null : temperature,
'turbidity': turbidity == -999.0 ? null : turbidity,
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'ammonia': ammonia == -999.0 ? null : ammonia,
'flowrate': flowrateValue,
'odour': '', // Not collected
'floatable': '', // Not collected
'sample_id': sampleIdCode,
'weather': weather,
'remarks_event': eventRemarks,
'remarks_lab': labRemarks,
// --- END FIX ---
// --- Sorted exactly according to your sample ---
'battery_cap': batteryVoltage ?? -999.0,
'device_name': sondeId ?? "",
'sampling_type': samplingType ?? "",
'report_id': reportId ?? "",
'sampler_2ndname': secondSampler?['first_name'] ?? "",
'sample_state': selectedStateName ?? "",
'station_id': selectedStation?['sampling_station_code'] ?? "",
'tech_id': firstSamplerUserId ?? -999, // Default to -999 if no ID
'tech_phonenum': "", // Field present in sample but not in model, defaults to empty
'tech_name': firstSamplerName ?? "",
'latitude': stationLatitude ?? "",
'longitude': stationLongitude ?? "",
'record_dt': (samplingDate != null && samplingTime != null)
? '$samplingDate $samplingTime'
: "",
// --- Sensor Readings ---
'do_mgl': oxygenConcentration ?? -999.0,
'do_sat': oxygenSaturation ?? -999.0,
'ph': ph ?? -999.0,
'salinity': salinity ?? -999.0,
'temperature': temperature ?? -999.0,
'turbidity': turbidity ?? -999.0,
'tds': tds ?? -999.0,
'electric_conductivity': electricalConductivity ?? -999.0,
'flowrate': flowrateValue ?? -999.0,
// --- Manual/Observations ---
'odour': "", // Default empty
'floatable': "", // Default empty
'sample_id': sampleIdCode ?? "",
'weather': weather ?? "",
'remarks_event': eventRemarks ?? "",
'remarks_lab': labRemarks ?? "",
};
// Remove null values before encoding
//data.removeWhere((key, value) => value == null);
// DO NOT UNCOMMENT. We want to keep all keys even if values are default.
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for basic form info, mimicking 'river_insitu_basic_form.json'.
String toBasicFormJson() {
final data = {
// --- START FIX: Map model properties to correct form keys ---
'tech_name': firstSamplerName,
'sampler_2ndname': secondSampler?['first_name'],
'sample_date': samplingDate,
'sample_time': samplingTime,
'sampling_type': samplingType,
'sample_state': selectedStateName,
'station_id': selectedStation?['sampling_station_code'],
'station_latitude': stationLatitude,
'station_longitude': stationLongitude,
'latitude': currentLatitude, // Current location lat
'longitude': currentLongitude, // Current location lon
'sample_id': sampleIdCode,
// --- END FIX ---
// --- Sorted sequence: tech_name -> sampler_2ndname -> date/time -> type -> state -> station info -> location -> sample_id
'tech_name': firstSamplerName ?? "",
'sampler_2ndname': secondSampler?['first_name'] ?? "",
'sample_date': samplingDate ?? "",
'sample_time': samplingTime ?? "",
'sampling_type': samplingType ?? "",
'sample_state': selectedStateName ?? "",
'station_id': selectedStation?['sampling_station_code'] ?? "",
'station_latitude': stationLatitude ?? "",
'station_longitude': stationLongitude ?? "",
'latitude': currentLatitude ?? "", // Current user location lat
'longitude': currentLongitude ?? "", // Current user location lon
'sample_id': sampleIdCode ?? "",
};
// Remove null values before encoding
data.removeWhere((key, value) => value == null);
// REMOVE or COMMENT OUT this line so no keys are deleted
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for sensor readings, mimicking 'river_sampling_reading.json'.
/// Creates a JSON object for sensor readings, mimicking 'river_sampling_reading.json'.
String toReadingJson() {
final data = {
// --- START FIX: Map model properties to correct reading keys ---
'do_mgl': oxygenConcentration == -999.0 ? null : oxygenConcentration,
'do_sat': oxygenSaturation == -999.0 ? null : oxygenSaturation,
'ph': ph == -999.0 ? null : ph,
'salinity': salinity == -999.0 ? null : salinity,
'temperature': temperature == -999.0 ? null : temperature,
'turbidity': turbidity == -999.0 ? null : turbidity,
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'ammonia': ammonia == -999.0 ? null : ammonia,
'flowrate': flowrateValue,
'date_sampling_reading': dataCaptureDate, // Use data capture date/time
'time_sampling_reading': dataCaptureTime, // Use data capture date/time
// --- END FIX ---
// --- Sorted exactly according to your sample ---
'do_mgl': oxygenConcentration ?? -999.0,
'do_sat': oxygenSaturation ?? -999.0,
'ph': ph ?? -999.0,
'salinity': salinity ?? -999.0,
'temperature': temperature ?? -999.0,
'turbidity': turbidity ?? -999.0,
'tds': tds ?? -999.0,
'electric_conductivity': electricalConductivity ?? -999.0,
'flowrate': flowrateValue ?? -999.0,
// --- Date and Time ---
'date_sampling_reading': dataCaptureDate ?? "",
'time_sampling_reading': dataCaptureTime ?? "",
};
// Remove null values before encoding
data.removeWhere((key, value) => value == null);
// REMOVE or COMMENT OUT this line to ensure no keys are skipped/removed
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}

View File

@ -446,7 +446,7 @@ class RiverInvesManualSamplingData {
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'ammonia': ammonia == -999.0 ? null : ammonia,
'flowrate': flowrateValue,
'flowrate': flowrateValue ?? -999.0,
'odour': '', // Not collected
'floatable': '', // Not collected
'sample_id': sampleIdCode,

View File

@ -322,7 +322,7 @@ class RiverManualTriennialSamplingData {
'turbidity': turbidity == -999.0 ? null : turbidity,
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'ammonia': ammonia == -999.0 ? null : ammonia,
//'ammonia': ammonia == -999.0 ? null : ammonia,
'flowrate': flowrateValue,
'odour': '', // Not collected
'floatable': '', // Not collected
@ -335,47 +335,57 @@ class RiverManualTriennialSamplingData {
return jsonEncode(data);
}
/// Creates a JSON object for basic form info, mimicking 'river_triennial_basic_form.json'.
/// Creates a JSON object for basic form info, mimicking 'river_insitu_basic_form.json'.
String toBasicFormJson() {
final data = {
// --- START FIX: Map model properties to correct form keys ---
'tech_name': firstSamplerName,
'sampler_2ndname': secondSampler?['first_name'],
'sample_date': samplingDate,
'sample_time': samplingTime,
'sampling_type': samplingType,
'sample_state': selectedStateName,
'station_id': selectedStation?['sampling_station_code'],
'station_latitude': stationLatitude,
'station_longitude': stationLongitude,
'latitude': currentLatitude, // Current location lat
'longitude': currentLongitude, // Current location lon
'sample_id': sampleIdCode,
// --- END FIX ---
// Keys sorted exactly according to the provided sample
'tech_name': firstSamplerName ?? "",
'sampler_2ndname': secondSampler?['first_name'] ?? "",
'sample_date': samplingDate ?? "",
'sample_time': samplingTime ?? "",
'sampling_type': samplingType ?? "",
'sample_state': selectedStateName ?? "",
'station_id': selectedStation?['sampling_station_code'] ?? "",
'station_latitude': stationLatitude ?? "",
'station_longitude': stationLongitude ?? "",
'latitude': currentLatitude ?? "", // Current user location lat
'longitude': currentLongitude ?? "", // Current user location lon
'sample_id': sampleIdCode ?? "",
};
data.removeWhere((key, value) => value == null);
// REMOVE or COMMENT OUT this line so no keys are deleted
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}
/// Creates a JSON object for sensor readings, mimicking 'river_sampling_reading.json'.
String toReadingJson() {
final data = {
// --- START FIX: Map model properties to correct reading keys ---
'do_mgl': oxygenConcentration == -999.0 ? null : oxygenConcentration,
'do_sat': oxygenSaturation == -999.0 ? null : oxygenSaturation,
'ph': ph == -999.0 ? null : ph,
'salinity': salinity == -999.0 ? null : salinity,
'temperature': temperature == -999.0 ? null : temperature,
'turbidity': turbidity == -999.0 ? null : turbidity,
'tds': tds == -999.0 ? null : tds,
'electric_conductivity': electricalConductivity == -999.0 ? null : electricalConductivity,
'ammonia': ammonia == -999.0 ? null : ammonia,
'flowrate': flowrateValue,
'date_sampling_reading': dataCaptureDate, // Use data capture date/time
'time_sampling_reading': dataCaptureTime, // Use data capture date/time
// --- END FIX ---
// Use ?? operator to default to -999.0 if null
'do_mgl': oxygenConcentration ?? -999.0,
'do_sat': oxygenSaturation ?? -999.0,
'ph': ph ?? -999.0,
'salinity': salinity ?? -999.0,
'temperature': temperature ?? -999.0,
'turbidity': turbidity ?? -999.0,
'tds': tds ?? -999.0,
'electric_conductivity': electricalConductivity ?? -999.0,
// Keep 'ammonia' commented out if it's not used in Triennial,
// otherwise uncomment and use: 'ammonia': ammonia ?? -999.0,
// Flowrate defaults to -999.0 (as requested in previous turn)
'flowrate': flowrateValue ?? -999.0,
// Date and Time default to empty string "" if null
'date_sampling_reading': dataCaptureDate ?? "",
'time_sampling_reading': dataCaptureTime ?? "",
};
data.removeWhere((key, value) => value == null);
// REMOVE or COMMENT OUT this line so keys are NEVER deleted
// data.removeWhere((key, value) => value == null);
return jsonEncode(data);
}

View File

@ -221,7 +221,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
ListTile(
leading: const Icon(Icons.info_outline),
title: const Text('App Version'),
subtitle: const Text('MMS Version 3.12.01'),
subtitle: const Text('MMS Version 3.12.03'),
dense: true,
),
ListTile(

View File

@ -603,7 +603,7 @@ class RiverInSituSamplingService {
mapImage(data.backgroundStationImage, 'background');
mapImage(data.upstreamRiverImage, 'upstream');
mapImage(data.downstreamRiverImage, 'downstream');
mapImage(data.sampleTurbidityImage, 'sample_turbidity');
mapImage(data.sampleTurbidityImage, 'turbidity');
mapImage(data.optionalImage1, 'optional_1');
mapImage(data.optionalImage2, 'optional_2');
mapImage(data.optionalImage3, 'optional_3');

View File

@ -607,9 +607,9 @@ class RiverManualTriennialSamplingService {
// --- START FIX: Include all four JSON files ---
jsonDataMap: {
'db.json': data.toDbJson(),
'river_triennial_basic_form.json': data.toBasicFormJson(), // ADDED
'river_triennial_reading.json': data.toReadingJson(), // ADDED
'river_triennial_manual_info.json': data.toManualInfoJson(), // ADDED
'river_insitu_basic_form.json': data.toBasicFormJson(), // ADDED
'river_sampling_reading.json': data.toReadingJson(), // ADDED
'river_manual_info.json': data.toManualInfoJson(), // ADDED
},
// --- END FIX ---
baseFileName: baseFileName,