upload method

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

Implementation

Future<List<Event>?> upload(Function(RequestProgress, bool) callback,
    {Dio? dioTestClient, String? resource}) 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)
      .withDataValues()
      .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 = events.map((event) => event.id as String).toList();

  final eventUploadPayload = [];
  for (Event event in events) {
    if (event.programStage != null) {
      ProgramStage programStage = await ProgramStageQuery(database: database)
          .byId(event.programStage)
          .getOne();
      dynamic eventPayload = Event.toUpload(event);
      eventPayload['program'] = programStage.program;
      eventUploadPayload.add(eventPayload);
    } else {
      dynamic eventPayload = Event.toUpload(event);
      eventUploadPayload.add(eventPayload);
    }
  }

  final response = await HttpClient.post(
      resource ?? 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.runtimeType == String
      ? [
          {
            "responseType": "ImportSummary",
            "status": "ERROR",
            "reference": "",
            "enrollments": {
              "responseType": "ImportSummary",
              "status": "ERROR",
              "imported": 0,
              "updated": 0,
              "ignored": 1,
              "deleted": 0,
              "importSummaries:": [],
              "total": 0
            },
            "importCount": {
              "imported": 0,
              "updated": 0,
              "ignored": 1,
              "deleted": 0
            },
            "total": 0,
            "importSummaries:": [],
            "conflicts": [
              {
                "object": "Server.ERROR",
                "value": '${response.body.toString()}: ${response.statusCode}'
              }
            ]
          }
        ]
      : response.body['status'] != null &&
              response.body['status'] == 'OK' &&
              response.body['validationReport'] != null
          ? [
              {
                "responseType": "ImportSummary",
                "status": "SUCCESS",
                "reference": eventIds[0],
                "enrollments": {
                  "responseType": "ImportSummary",
                  "status": "ERROR",
                  "imported": 0,
                  "updated": 1,
                  "ignored": 0,
                  "deleted": 0,
                  "importSummaries:": [
                    {
                      "responseType": "ImportSummary",
                      "status": "SUCCESS",
                      "importCount": {
                        "imported": 0,
                        "updated": 1,
                        "ignored": 0,
                        "deleted": 0
                      },
                      "conflicts": [],
                      "reference": "a6vUjBH0UUj"
                    }
                  ],
                  "total": 0
                },
                "importCount": {
                  "imported": 1,
                  "updated": 1,
                  "ignored": 0,
                  "deleted": 0
                },
                "total": 1,
                "importSummaries:": [],
                "conflicts": []
              }
            ]
          : (response.body?['response']?['importSummaries'] ?? []).toList();

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

  if (instanceVersion != null && instanceVersion! >= 38) {
    final lastestVersionResponse =
        LatestVersionResponse.fromJson(response.body);

    final objectReport = lastestVersionResponse
        .bundleReport?.typeReportMap?.event?.objectReports;

    events.forEach((event) {
      final importSummary =
          objectReport?.lastWhere((summary) => summary.uid == event.id);
      if (importSummary != null) {
        availableItemCount++;
        final syncFailed = lastestVersionResponse.status == 'ERROR';
        event.synced = !syncFailed;
        event.dirty = true;
        event.syncFailed = syncFailed;
        event.lastSyncDate = DateTime.now().toIso8601String();
        event.lastUpdated = DateTime.now().toIso8601String();
        queue.add(() => EventQuery(database: database).setData(event).save());
      }
    });
  } else {
    events.forEach((event) {
      final importSummary = importSummaries.lastWhere(
        (summary) =>
            summary['reference'] != null && summary['reference'] == event.id,
        orElse: () => null,
      );

      if (importSummary != null) {
        availableItemCount++;
        final syncFailed = importSummary['status'] == 'ERROR';
        event.synced = !syncFailed;
        event.dirty = true;
        event.syncFailed = syncFailed;
        event.lastSyncDate = DateTime.now().toIso8601String();
        event.lastUpdated = DateTime.now().toIso8601String();
        event.lastSyncSummary = EventImportSummary.fromJson(importSummary);

        queue.add(() => EventQuery(database: database).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(database: database).byIds(eventIds).get();
}