151 lines
6.2 KiB
Dart
151 lines
6.2 KiB
Dart
// lib/services/river_api_service.dart
|
|
|
|
import 'dart:io';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
import 'package:environment_monitoring_app/services/base_api_service.dart';
|
|
import 'package:environment_monitoring_app/services/telegram_service.dart';
|
|
// NOTE: RiverApiService still needs RiverInSituSamplingData import for its handle alert method,
|
|
// but since the model file wasn't provided directly, we assume it's correctly handled by the caller/context.
|
|
|
|
class RiverApiService {
|
|
final BaseApiService _baseService;
|
|
final TelegramService _telegramService;
|
|
RiverApiService(this._baseService, this._telegramService);
|
|
|
|
Future<Map<String, dynamic>> getManualStations() {
|
|
return _baseService.get('river/manual-stations');
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getTriennialStations() {
|
|
return _baseService.get('river/triennial-stations');
|
|
}
|
|
|
|
// MODIFIED: Method now returns granular status tracking for API and Images.
|
|
Future<Map<String, dynamic>> submitInSituSample({
|
|
required Map<String, String> formData,
|
|
required Map<String, File?> imageFiles,
|
|
required List<Map<String, dynamic>>? appSettings,
|
|
}) async {
|
|
Map<String, dynamic> finalResult = {
|
|
'success': false,
|
|
'status': 'L1', // Default: Local Failure (Data failed)
|
|
'api_status': 'NOT_ATTEMPTED',
|
|
'image_upload_status': 'NOT_ATTEMPTED',
|
|
'message': 'Submission failed.',
|
|
'reportId': null,
|
|
};
|
|
|
|
// --- Step 1: Submit Form Data as JSON ---
|
|
debugPrint("Step 1: Submitting River In-Situ form data...");
|
|
final dataResult = await _baseService.post('river/manual/sample', formData);
|
|
|
|
finalResult['api_status'] = dataResult['success'] == true ? 'SUCCESS' : 'FAILED';
|
|
|
|
if (dataResult['success'] != true) {
|
|
finalResult['message'] = dataResult['message'] ?? 'Failed to submit river in-situ data (API failed).';
|
|
return finalResult;
|
|
}
|
|
|
|
// Update status and reportId upon successful data submission
|
|
final recordId = dataResult['data']?['r_man_id'];
|
|
finalResult['reportId'] = recordId?.toString();
|
|
|
|
if (recordId == null) {
|
|
finalResult['api_status'] = 'FAILED';
|
|
finalResult['message'] = 'Data submitted, but server did not return a record ID.';
|
|
return finalResult;
|
|
}
|
|
|
|
final filesToUpload = <String, File>{};
|
|
imageFiles.forEach((key, value) {
|
|
if (value != null) filesToUpload[key] = value;
|
|
});
|
|
|
|
// --- Step 2: Upload Image Files ---
|
|
if (filesToUpload.isEmpty) {
|
|
debugPrint("No images to upload. Finalizing submission.");
|
|
finalResult['image_upload_status'] = 'NOT_REQUIRED';
|
|
|
|
// Final Status: S3 (Success, Data Only)
|
|
finalResult['success'] = true;
|
|
finalResult['status'] = 'S3';
|
|
finalResult['message'] = 'Data submitted successfully. No images were attached.';
|
|
|
|
_handleInSituSuccessAlert(formData, appSettings, isDataOnly: true);
|
|
return finalResult;
|
|
}
|
|
|
|
debugPrint("Step 2: Uploading ${filesToUpload.length} images...");
|
|
final imageResult = await _baseService.postMultipart(
|
|
endpoint: 'river/manual/images', // Separate endpoint for images
|
|
fields: {'r_man_id': recordId.toString()}, // Link images to the submitted record ID
|
|
files: filesToUpload,
|
|
);
|
|
|
|
finalResult['image_upload_status'] = imageResult['success'] == true ? 'SUCCESS' : 'FAILED';
|
|
|
|
if (imageResult['success'] != true) {
|
|
// Data submitted successfully, but images failed (L2/L4 equivalent)
|
|
finalResult['success'] = true; // API data transfer was still successful
|
|
finalResult['status'] = 'L2_PENDING_IMAGES';
|
|
finalResult['message'] = 'Data submitted, but image upload failed: ${imageResult['message']}';
|
|
|
|
_handleInSituSuccessAlert(formData, appSettings, isDataOnly: true); // Alert for data only
|
|
return finalResult;
|
|
}
|
|
|
|
// --- Step 3: Full Success ---
|
|
finalResult['success'] = true;
|
|
finalResult['status'] = 'S2'; // S2 means Data+Images submitted
|
|
finalResult['message'] = 'Data and images submitted successfully.';
|
|
|
|
_handleInSituSuccessAlert(formData, appSettings, isDataOnly: false);
|
|
return finalResult;
|
|
}
|
|
|
|
// MODIFIED: Method now requires appSettings and calls the updated TelegramService.
|
|
Future<void> _handleInSituSuccessAlert(Map<String, String> formData, List<Map<String, dynamic>>? appSettings, {required bool isDataOnly}) async {
|
|
try {
|
|
final submissionType = isDataOnly ? "(Data Only)" : "(Data & Images)";
|
|
final stationName = formData['r_man_station_name'] ?? 'N/A';
|
|
final stationCode = formData['r_man_station_code'] ?? 'N/A';
|
|
final submissionDate = formData['r_man_date'] ?? DateFormat('yyyy-MM-dd').format(DateTime.now());
|
|
final submitter = formData['first_sampler_name'] ?? 'N/A';
|
|
final sondeID = formData['r_man_sondeID'] ?? 'N/A';
|
|
final distanceKm = double.tryParse(formData['r_man_distance_difference'] ?? '0') ?? 0;
|
|
final distanceMeters = (distanceKm * 1000).toStringAsFixed(0);
|
|
final distanceRemarks = formData['r_man_distance_difference_remarks'] ?? 'N/A';
|
|
|
|
final buffer = StringBuffer()
|
|
..writeln('✅ *River In-Situ Sample ${submissionType} Submitted:*')
|
|
..writeln()
|
|
..writeln('*Station Name & Code:* $stationName ($stationCode)')
|
|
..writeln('*Date of Submitted:* $submissionDate')
|
|
..writeln('*Submitted by User:* $submitter')
|
|
..writeln('*Sonde ID:* $sondeID')
|
|
..writeln('*Status of Submission:* Successful');
|
|
|
|
if (distanceKm > 0 || (distanceRemarks.isNotEmpty && distanceRemarks != 'N/A')) {
|
|
buffer
|
|
..writeln()
|
|
..writeln('🔔 *Alert:*')
|
|
..writeln('*Distance from station:* $distanceMeters meters');
|
|
if (distanceRemarks.isNotEmpty && distanceRemarks != 'N/A') {
|
|
buffer.writeln('*Remarks for distance:* $distanceRemarks');
|
|
}
|
|
}
|
|
|
|
final String message = buffer.toString();
|
|
|
|
// MODIFIED: Pass the appSettings list to the TelegramService methods.
|
|
final bool wasSent = await _telegramService.sendAlertImmediately('river_in_situ', message, appSettings);
|
|
if (!wasSent) {
|
|
await _telegramService.queueMessage('river_in_situ', message, appSettings);
|
|
}
|
|
} catch (e) {
|
|
debugPrint("Failed to handle River Telegram alert: $e");
|
|
}
|
|
}
|
|
} |