upload method

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

Implementation

Future<List<Event>?> 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<Event> events = await this
      .where(attribute: 'synced', value: false)
      .where(attribute: 'dirty', value: true)
      .get();

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

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

  List<String> eventIds = [];
  List<String> eventProgramStageIds = [];
  events.forEach((event) {
    eventIds.add(event.id as String);

    eventProgramStageIds.removeWhere((id) => id == event.programStage);
    eventProgramStageIds.add(event.programStage);
  });

  List<EventDataValue> eventDataValues = await EventDataValueQuery()
      .whereIn(attribute: 'event', values: eventIds, merge: false)
      .get();

  List<ProgramStage> programStages =
      await ProgramStageQuery().byIds(eventProgramStageIds).get();

  final eventUploadPayload = events.map((event) {
    event.dataValues = eventDataValues
        .where((dataValue) => dataValue.event == event.id)
        .toList();
    event.programStage = programStages
        .lastWhere((programStage) => programStage.id == event.programStage)
        .toJson();
    return Event.toUpload(event);
  }).toList();

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

  callback(
      RequestProgress(
          resourceName: this.apiResourceName as String,
          message:
              'Upload for ${events.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;

  events.forEach((event) {
    final importSummary = importSummaries.lastWhere((summary) =>
        summary['reference'] != null && summary['reference'] == event.id);

    if (importSummary != null) {
      availableItemCount++;
      final syncFailed = importSummary['status'] == 'ERROR';
      event.synced = !syncFailed;
      event.dirty = true;
      event.syncFailed = syncFailed;
      event.lastSyncDate = DateTime.now().toIso8601String().split('.')[0];
      event.lastSyncSummary = importSummary.toString();
      queue.add(() => EventQuery().setData(event).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 EventQuery().byIds(eventIds).get();
}