upload method

Future<List<TrackedEntityInstance>?> upload(
  1. dynamic callback(
    1. RequestProgress,
    2. bool
    ), {
  2. Dio? dioTestClient,
})

Implementation

Future<List<TrackedEntityInstance>?> upload(
    Function(RequestProgress, bool) callback,
    {Dio? dioTestClient}) async {
  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Retrieving ${this.apiResourceName?.toLowerCase()} from phone database....',
          status: '',
          percentage: 0),
      false);
  List<TrackedEntityInstance> trackedEntityInstances = await this
      .where(attribute: 'synced', value: false)
      .where(attribute: 'dirty', value: true)
      .get();

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              '${trackedEntityInstances.length} ${this.apiResourceName?.toLowerCase()} retrieved successfully',
          status: '',
          percentage: 50),
      false);

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Uploading ${trackedEntityInstances.length} ${this.apiResourceName?.toLowerCase()} into the server...',
          status: '',
          percentage: 51),
      false);

  final List<String> trackedEntityInstanceIds = trackedEntityInstances
      .map((trackedEntityInstance) => trackedEntityInstance.id as String)
      .toList();

  List<TrackedEntityAttributeValue> attributes =
      await TrackedEntityAttributeValueQuery()
          .whereIn(
              attribute: 'trackedEntityInstance',
              values: trackedEntityInstanceIds,
              merge: false)
          .get();

  List<Enrollment> enrollments = await EnrollmentQuery()
      .whereIn(
          attribute: 'trackedEntityInstance',
          values: trackedEntityInstanceIds,
          merge: false)
      .get();

  final trackedEntityInstanceUploadPayload =
      trackedEntityInstances.map((trackedEntityInstance) {
    trackedEntityInstance.attributes = attributes
        .where((attribute) =>
            attribute.trackedEntityInstance == trackedEntityInstance.id)
        .toList();

    trackedEntityInstance.enrollments = enrollments
        .where((enrollment) =>
            enrollment.trackedEntityInstance == trackedEntityInstance.id)
        .toList();

    return TrackedEntityInstance.toUpload(trackedEntityInstance);
  }).toList();

  final response = await HttpClient.post(this.apiResourceName as String,
      {'trackedEntityInstances': trackedEntityInstanceUploadPayload},
      database: this.database, dioTestClient: dioTestClient);

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Upload for ${trackedEntityInstances.length} ${this.apiResourceName?.toLowerCase()} is completed.',
          status: '',
          percentage: 75),
      true);

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message: 'Saving import summaries into the phone database...',
          status: '',
          percentage: 76),
      true);

  final List<dynamic> importSummaries =
      (response.body?['response']?['importSummaries'] ?? []).toList();

  final queue = Queue(parallel: 50);
  num availableItemCount = 0;

  trackedEntityInstances.forEach((trackedEntityInstance) {
    final importSummary = importSummaries.lastWhere(
        (summary) => summary['reference'] == trackedEntityInstance.id,
        orElse: (() => null));

    if (importSummary != null) {
      availableItemCount++;
      final syncFailed = importSummary['status'] == 'ERROR';
      trackedEntityInstance.synced = !syncFailed;
      trackedEntityInstance.dirty = true;
      trackedEntityInstance.syncFailed = syncFailed;
      trackedEntityInstance.lastSyncDate =
          DateTime.now().toIso8601String().split('.')[0];
      trackedEntityInstance.lastSyncSummary = importSummary.toString();
      queue.add(() =>
          TrackedEntityInstanceQuery().setData(trackedEntityInstance).save());
    }
  });

  if (availableItemCount == 0) {
    queue.cancel();
  } else {
    await queue.onComplete;
  }

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message: 'Import summaries saved succussfully',
          status: '',
          percentage: 100),
      true);

  return await TrackedEntityInstanceQuery()
      .byIds(trackedEntityInstanceIds)
      .get();
}