The Health Campaign Management (HCM) latest version field worker's app is part of the DIGIT Health Platform. It empowers frontline teams to manage health campaigns efficiently, even in low or no network coverage areas. With its offline-first functionality and configurable design, the app is built to address the unique needs of field workers, ensuring seamless data collection, beneficiary management, and campaign tracking.
-
Offline Mode: Perform all tasks without active internet connectivity.
-
Four New Modules: Enable efficient task execution for frontline workers.
-
Configurable Design: Adaptable to various campaign needs through server-based configurations.
-
Multi-Round Campaign Support: Manage multiple campaign cycles with eligibility checks, delivery tracking, and side-effect recording.
-
Sync Mechanism: Bidirectional sync (up and down) ensures consistent data between the app and server.
-
Beneficiary Data Management: Optimized retrieval and duplication prevention for beneficiary records.
-
Permission-Based Access: Data sync tailored to user roles and assigned projects.
The high-level architecture of the app is divided into three core parts:
-
Frontend: Built using Flutter for a multi-platform, user-friendly experience.
-
Backend Services: Syncs with MDMS, localisation, and other backend services.
-
Database: Combines SQLite and ISAR for flexible offline data storage.
-
Flutter: Framework to build multi-platform apps.
-
SQLite: SQL offline database for structured data.
-
ISAR: NoSQL offline database for high-performance storage.
-
Dio: HTTP client for network communication.
-
Works seamlessly in low/no network coverage areas.
-
Highly configurable, with settings managed through MDMS.
-
Designed for Android devices, ensuring compatibility with users who have low-tech literacy.
-
Sync Down: Fetch configurations and data from the server (e.g., localisation, master data).
-
Sync Up: Upload collected data to the server.
-
Login & Sync: Syncing can only occur while the user is online.
Key configurations include:
-
Offline-first or online-only mode.
-
Backend service URLs and endpoints (no app rebuild required for updates).
-
Data refresh intervals for previously fetched configurations.
-
Supported languages and localisation data.
All offline actions are logged and processed during sync-up to ensure data consistency and integrity.
A network manager component abstracts the online/offline logic, enabling seamless data handling by other app components.
Ensures the local device database is updated with the latest beneficiary data while preventing duplicate records.
Key Features:
-
Uses offset and limit for efficient pagination.
-
Adapts batch size based on internet speed.
-
Essential for reducing redundancy within the same boundary.
Use Case:
- Particularly useful in multi-user scenarios where teams operate in the same geographical boundary.
Supports tracking and delivery processes across multiple cycles.
Key Features:
-
Fetches configurations dynamically from MDMS.
-
Checks eligibility criteria based on age and project configurations.
-
Tracks delivery status, side effects, and referrals.
-
Resets statuses (e.g., Beneficiary Refused) for each new cycle.
Delivery Status Tracking:
-
Not Eligible: Fails age or cycle eligibility criteria.
-
Beneficiary Refused: User declined the delivery.
-
Beneficiary Referred: Referred to a health facility.
-
Visited: Delivery successfully completed.
-
Not Visited: Delivery not completed.
As a part of the release, we have extracted the features of the Frontline Worker's App as individual packages:
These are the packages which are created for this.
To get started with any package, follow these steps:
Add the following dependencies in your pubspec.yaml file:
dependencies:
<package_name>: ^latest_version
To integrate this package with the HCM Application, locate the main function for integration in the respective tool's import file. For example, health-campaign-field-worker-app/tools/<package_name>_imports.dart
.
health-campaign-field-worker-app/tools/<package_name>_imports.dart
This will automatically handle:
β
Imports
β
Mapper initializers
β
Route configuration
β
Initial data setup
β
Repository initialization
Ensure you are in the correct project directory:
apps/health_campaign_field_worker_app
Run the following command:
dart run build_runner build --delete-conflicting-outputs
This will add the package route to router.gr.dart.
After running the build command, install the application on your device to have the module integrated with your base app.
To ensure proper data synchronization, follow any additional steps for down-syncing or up-syncing based on your use case.
By following these general steps, you can successfully integrate and use any of the packages within your application.
The Closed Household package is a new module built as a Flutter package (closed_household
). It will be a dependency for the Registration and Delivery package.
π€ Distributor
-
Create a Closed Household: Enables creating a closed household record.
-
Update Task: Updates the task if a closed household is registered.
Integrating with the HCM Application: Getting Started
This package provides a way to register a household and individual members and deliver the resources to the registered households.
π€ DISTRIBUTOR
-
Register new households and individuals: Register new records for households and individuals.
-
Search existing households and individuals: Easily search for already registered records.
-
Update existing records: Modify details for existing households and individuals.
-
Record service delivery: Track healthcare interventions delivered to households and individuals for a single-round campaign.
-
Auto-calculation of resources: Automatically calculate resources to be delivered to a household or individual based on the configured rules.
Integrating with the HCM Application: Getting Started
If you need to downsync registration-delivery data during boundary selection, modify project_beneficiaries_downsync.dart by including the following repositories:
final LocalRepository<HouseholdModel, HouseholdSearchModel> householdLocalRepository;
final LocalRepository<HouseholdMemberModel, HouseholdMemberSearchModel> householdMemberLocalRepository;
final LocalRepository<ProjectBeneficiaryModel, ProjectBeneficiarySearchModel> projectBeneficiaryLocalRepository;
final LocalRepository<TaskModel, TaskSearchModel> taskLocalRepository;
final LocalRepository<SideEffectModel, SideEffectSearchModel> sideEffectLocalRepository;
final LocalRepository<ReferralModel, ReferralSearchModel> referralLocalRepository;
Next, locate the method:
networkManager.writeToEntityDb
Ensure it includes the repositories:
householdLocalRepository,
householdMemberLocalRepository,
projectBeneficiaryLocalRepository,
taskLocalRepository,
sideEffectLocalRepository,
referralLocalRepository,
These changes will enable the down sync of registration & delivery data.
When users downsync data by passing project ID & boundary code, the server returns responses only for the selected boundary.
-
Household
-
Individual
-
House Member
1οΈβ£ Updating project-specific data
2οΈβ£ Creating new project-specific data
-
Beneficiary (Mandatory)
-
Task & related entities (Optional)
To enable better data access, we introduce filters:
-
Registered
-
Unregistered
-
Closed
-
Combination of Filters
-
Proximity Enabled Search
-
Search by Name
A query builder is used to fetch results dynamically (example below for an individual-based project).
- Captured on the Household Location screen.
-
Entered on the Member Screen.
-
Stored in the Additional Fields Object of the Household Member entity.
-
A new screen has been added to capture household structure.
-
Structure data is fetched from MDMS and displayed as a card selection UI.
-
The selected value is stored in the Additional Details Object in the Household Entity.
-
A new module named closed_household has been built.
-
This will be a dependency of the registration and delivery package.
For household-based flows, a feature has been introduced to capture reasons for unsuccessful deliveries.
Once all the above modifications are implemented, rerun:
dart run build_runner build --delete-conflicting-outputs
This ensures proper integration of Registration & Delivery within the HCM app.
This package enables the user to manage the stocks of a health campaign. The user can record the stocks received, issued, returned, damaged, and lost.
π€ DISTRIBUTOR π€ WAREHOUSE_MANAGER
- Manage Stocks: Record the receipt, issue, return, damage, and loss of stocks.
- Stock Reconciliation: Reconcile the stock data.
- View Reports: View the reports of the stocks.
Integrating with the HCM Application: Getting Started
This module will enable the health facility supervisors to track referrals made by on-field health workers to different health facilities digitally via the Digit HCM app.
π€ HEALTH_FACILITY_WORKER
-
Track referrals made by on-field health workers: Enables tracking of all referrals to various health facilities.
-
Capture beneficiary referral details: Includes the reason for referrals, diagnosis, and any further applicable details.
-
Detailed record keeping: Ensures all referral cases are documented digitally for better monitoring.
Integrating with the HCM Application: Getting Started
The Attendance Management package is a comprehensive solution for tracking and managing attendance within the Digit HCM app.
π€ SUPERVISOR
-
Attendance Pages:
The package includes several UI pages for attendance management:-
mark_attendance.dart -- Allows users to mark attendance.
-
manage_attendance.dart -- Provides an interface for managing and updating attendance records.
-
session_select.dart -- Enables users to select attendance sessions conveniently.
-
Integrating with the HCM Application: Getting Started
Navigate to the Project Bloc, where attendance data should be fetched after login.
Add the following repositories:
final RemoteRepository<AttendanceRegisterModel, AttendanceRegisterSearchModel>
attendanceRemoteRepository;
final LocalRepository<AttendanceRegisterModel, AttendanceRegisterSearchModel>
attendanceLocalRepository;
final LocalRepository<AttendanceLogModel, AttendanceLogSearchModel>
attendanceLogLocalRepository;
final RemoteRepository<AttendanceLogModel, AttendanceLogSearchModel>
attendanceLogRemoteRepository;
Find the section where project staff search is handled.
Modify the try-catch block to fetch attendance data based on role:
if (context.loggedInUserRoles
.where(
(role) => role.code == RolesType.districtSupervisor.toValue(),
)
.toList()
.isNotEmpty) {
final individual = await individualRemoteRepository.search(
IndividualSearchModel(
userUuid: [projectStaff.userId.toString()],
),
);
final attendanceRegisters = await attendanceRemoteRepository.search(
AttendanceRegisterSearchModel(
staffId: individual.first.id,
referenceId: projectStaff.projectId,
),
);
await attendanceLocalRepository.bulkCreate(attendanceRegisters);
for (final register in attendanceRegisters) {
if (register.attendees != null &&
(register.attendees ?? []).isNotEmpty) {
try {
final individuals = await individualRemoteRepository.search(
IndividualSearchModel(
id: register.attendees!
.map((e) => e.individualId!)
.toList(),
),
);
await individualLocalRepository.bulkCreate(individuals);
final logs = await attendanceLogRemoteRepository.search(
AttendanceLogSearchModel(
registerId: register.id,
),
);
await attendanceLogLocalRepository.bulkCreate(logs);
} catch (_) {
emit(state.copyWith(
loading: false,
syncError: ProjectSyncErrorType.project,
));
return;
}
}
}
}
Ensure you are still in:
apps/health_campaign_field_worker_app
Then, run the build runner command again:
dart run build_runner build --delete-conflicting-outputs
This will ensure the package route is properly integrated into router.gr.dart.
The digit_data_model
package is a comprehensive data modeling library for the project. It defines various classes, enums, and functions used throughout the project. The package is written in Dart and is primarily used in Flutter applications.
-
Data Models -- Provides predefined models like
DataModel
,EntityModel
,EntitySearchModel
,AdditionalFields
,AuditDetails
, etc. -
Model Provider -- Includes a
ModelProvider
abstract class and aModelProviderRegistry
to register and retrieve models. -
Data Model Type Enum -- Defines a
DataModelType
enum representing different model types. -
Mapping Annotations -- Uses
dart_mappable
for generating mapping code, enabling JSON serialization/deserialization. -
Data Repositories -- Provides
DataRepository
,RemoteRepository
, andLocalRepository
for handling data operations. -
SQL Store -- Uses
Drift
for SQLite database integration with reactive persistence. -
Schema Versioning -- Supports database migrations through schema versioning.
Integrating with the HCM Application: Getting Started
Below are some examples of how you can use this package:
class ExampleSearchModel extends EntitySearchModel {
ExampleSearchModel({
required this.employeeId,
required this.attendanceDate,
required this.status,
});
}
class ExampleAdditionalFields extends AdditionalFields {
ExampleAdditionalFields({
required this.field1,
required this.field2,
});
}
class ExampleLocalRepository
extends LocalRepository<ExampleModel, ExampleSearchModel> {
ExampleLocalRepository(super.sql, super.opLogManager);
}
class ExampleRemoteRepository
extends RemoteRepository<ExampleModel, ExampleSearchModel> {
ExampleRemoteRepository(super.apiClient, super.opLogManager);
}
Digit_dss is a Flutter package designed to facilitate the seamless integration of dynamic dashboards into your mobile application. This package allows developers to configure and render various types of charts directly from a dashboard configuration, enabling a flexible and customizable approach to data visualization.
- Dynamic charts configuration\
- Support for Metric Charts\
- Support for Table Charts
π€ DISTRICT_SUPERVISOR
Integrating with the HCM Application: Getting Started
The Complaints Package provides a streamlined way for users to register complaints related to health campaigns. It enables users to:
βοΈ File complaints specifying the type and detailed information
βοΈ Choose from predefined categories to classify complaints
βοΈ Access past complaint records
π€ DISTRIBUTOR
-
π Register complaints easily
-
π Access past complaint records for tracking
-
π Choose from predefined categories to classify complaints
Integrating with the HCM Application: Getting Started
The Survey Form Package enables users to fill out questionnaires efficiently. It provides a user-friendly interface for submitting responses, ensuring that health campaign-related feedback and data are collected accurately.
π€ DISTRIBUTOR
βοΈ Selection Box, Check-Box, and Text Fields to support various data types
βοΈ Accurately captures employee-specific boundaries for relevant survey responses
βοΈ Allows employees to view their submitted responses
Integrating with the HCM Application: Getting Started
The Sync Service Package provides access to sync-related configurations and listeners, ensuring seamless data synchronization. It includes key components such as SyncEntityMapperListener, syncDownRetryCount, and persistenceConfiguration.
βοΈ SyncBloc: Handles refresh and sync operations
βοΈ SyncEntityMapperListener: Defines methods for sync entity mapping
βοΈ SyncService: Performs sync operations like performSync
, writeToEntityDB
, and getPendingSyncRecordsCount
βοΈ Repositories: Manages local and remote repositories with getRemoteForType
and getLocalForType
βοΈ Sync Operations: PerformSyncDown
and PerformSyncUp
for bidirectional sync
βοΈ Models: Bandwidth Model
Integrating with the HCM Application: Getting Started
class CustomSyncRegistry implements SyncUpOperation {
CustomSyncRegistry({this.remote});
}
class SyncServiceMapper extends SyncEntityMapperListener {
// Implement required methods
}
The DIGIT Scanner Package is used for scanning QR codes and GS1 barcodes in Flutter applications.
βοΈ Scan QR Codes & GS1 Barcodes
βοΈ Manage Scanner State using Bloc
βοΈ Navigate to Scanner Page with Custom Parameters
βοΈ Listen & Retrieve Scanned Codes Easily
Integrating with the HCM Application: Getting Started
BlocProvider(
create: (_) => DigitScannerBloc(const DigitScannerState()),
),
context.read<DigitScannerBloc>().add(
const DigitScannerEvent.handleScanner(),
);
context.router.push(
DigitScannerRoute(
quantity: 1, // Max number of codes to be scanned
isGS1code: false, // Set to true for GS1 barcode scanning
singleValue: true, // Set to false for scanning multiple codes
),
);
BlocListener<DigitScannerBloc, DigitScannerState>(
listener: (context, scannerState) {
if (scannerState.qrCodes.isNotEmpty) {
// Handle scanned codes
}
},
child: BlocBuilder<DigitScannerBloc, DigitScannerState>(
builder: (context, scannerState) {
if (scannerState.qrCodes.isNotEmpty) {
return Text(scannerState.qrCodes.last);
} else {
return Container();
}
},
),
);
The Digit Showcase Package provides an easy way to highlight or showcase widgets in your Flutter application. It helps guide users by visually emphasizing UI elements.
βοΈ Highlight widgets dynamically
βοΈ Guide users through the UI with visual cues
βοΈ Enable automatic scrolling to showcased widgets
βοΈ Supports localization for messages
Integrating with the HCM Application: Getting Started
ShowcaseWidget(
enableAutoScroll: true,
builder: Builder(
builder: (context) {
// Your widget tree
},
),
);
final date = ShowcaseItemBuilder(
messageLocalizationKey: i18.showcase_date.date,
);
date.buildWith(
child: Text('Date'),
);
Showcase is configured using showcaseview. A fork is created
at packages/digit_showcase
to handle customizations.
Add constants to lib/utils/i18_key_constants.dart
const checklistDataShowcase = ChecklistDataShowcase();
class ChecklistDataShowcase {
const ChecklistDataShowcase();
String get date {
return 'CHECKLIST_DATA_SHOWCASE_DATE';
}
String get administrativeUnit {
return 'CHECKLIST_DATA_SHOWCASE_ADMINISTRATIVE_UNIT';
}
}
checklist_data.dart
part of 'showcase_constants.dart';
class _ChecklistDataShowcaseData {
static final _ChecklistDataShowcaseData _instance =
_ChecklistDataShowcaseData._();
_ChecklistDataShowcaseData._();
factory _ChecklistDataShowcaseData() => _instance;
List<ShowcaseItemBuilder> get showcaseData =>
[
date,
administrativeUnit,
];
final date = ShowcaseItemBuilder(
messageLocalizationKey: i18.checklistDataShowcase.date,
);
final administrativeUnit = ShowcaseItemBuilder(
messageLocalizationKey: i18.checklistDataShowcase.administrativeUnit,
);
}
showcase_constants.dart
import '../../../utils/i18_key_constants.dart' as i18;
import '../showcase_wrappers.dart';
part 'survey_form_data.dart';
final checklistDataShowcaseData = _ChecklistDataShowcaseData();
showcase_button.dart
import 'package:digit_showcase/showcase_widget.dart';
import 'package:flutter/material.dart';
import '../../router/app_router.dart';
import '../../utils/i18_key_constants.dart' as i18;
import '../localized.dart';
import 'config/showcase_constants.dart';
class ShowcaseButton extends LocalizedStatefulWidget {
final Iterable<GlobalKey>? showcaseFor;
const ShowcaseButton({super.key, this.showcaseFor});
@override
LocalizedState<ShowcaseButton> createState() => _ShowcaseButtonState();
}
class _ShowcaseButtonState extends LocalizedState<ShowcaseButton> {
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: () {
if (widget.showcaseFor?.isNotEmpty == true) {
ShowcaseWidget.of(context).startShowCase(
widget.showcaseFor!.toList(),
);
return;
}
final current = context.router.current.name;
final paths = _showcasePathsForRoute(current);
if (paths == null) return;
if (paths.isEmpty) return;
ShowcaseWidget.of(context).startShowCase(paths.toList());
},
child: Row(
children: [
Text(localizations.translate(i18.common.coreCommonHelp)),
const Icon(Icons.help_outline),
],
),
);
}
Iterable<GlobalKey>? _showcasePathsForRoute(String routeName) {
return switch (routeName) {
// Add this config
ChecklistBoundaryViewRoute.name =>
checklistDataShowcaseData.showcaseData.map((e) => e.showcaseKey),
_ => null,
};
}
}
class _ChecklistBoundaryViewPageState extends LocalizedState<ChecklistBoundaryViewPage> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
body: ScrollableContent(
header: const Column(children: [
BackNavigationHelpHeaderWidget(
// Add showcase button
showcaseButton: ShowcaseButton(),
),
]),
footer: DigitCard(
child: DigitElevatedButton(
onPressed: () => context.router.push(ChecklistViewRoute()),
child: Text(localizations.translate(
i18.common.coreCommonContinue,
)),
),
),
slivers: [
SliverToBoxAdapter(
child: DigitCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
localizations.translate(
i18.checklist.checklistDetailLabel,
),
style: theme.textTheme.displayMedium,
),
// Wrap with showcase wrapper
checklistDataShowcaseData.date.buildWith(
child: DigitTextField(
readOnly: true,
label: localizations.translate(
i18.checklist.checklistdate,
),
suffixIcon: const Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.date_range_outlined,
),
),
controller: TextEditingController(
text: DateFormat('dd MMMM yyyy').format(DateTime.now()),
),
),
),
],
),
),
),
],
),
);
}
}
![Showcase](https://private-user-images.githubusercontent.com/172242434/408979832-61ac10fa-5cbf-4b13-970a-d3f33f4cc346.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk5MTc5MTEsIm5iZiI6MTczOTkxNzYxMSwicGF0aCI6Ii8xNzIyNDI0MzQvNDA4OTc5ODMyLTYxYWMxMGZhLTVjYmYtNGIxMy05NzBhLWQzZjMzZjRjYzM0Ni5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjE4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxOFQyMjI2NTFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kOWVlODcxZTNlOGJkNzlmMDFhZTZmMmYxM2ZiMTNhNTE4MDNmODJiZjQ2Mzc0Y2RlNjJkZjBkNjM0YTI1YzM4JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.LhD0duPTX5QdgFJkNH1AKHdiUqsOGWYmL_Ul9k_aAlY)
![Showcase](https://private-user-images.githubusercontent.com/172242434/408980452-5cc40377-8c2e-4d03-8c73-609bcfd89a28.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk5MTc5MTEsIm5iZiI6MTczOTkxNzYxMSwicGF0aCI6Ii8xNzIyNDI0MzQvNDA4OTgwNDUyLTVjYzQwMzc3LThjMmUtNGQwMy04YzczLTYwOWJjZmQ4OWEyOC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjE4JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxOFQyMjI2NTFaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1kNjc0YzI5NzZhNzFjZTg1Y2QwY2U0NmMxZDkyNWQzMzI2MzFmMzEyOGUzYWU2Zjk2OGM1OGU4ZmY2ZjNlYmM0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.Jetax-Vo9Lv-OrhwrLbWKG5AUa4iBB7woJ2ygMJD4FU)
Currently, the app is configured to run only on PersistenceConfiguration.offlineFirst
mode. With the offline first
approach the local data store is considered as the Source of truth. Data persisted in the local data store is synced
to the remote data store.
The following steps describe the data creation process:
- The user initiates the data creation by performing a Submit action.
- The UI receives the action and requests the repository from the Network Manager.
- The Network Manager returns the Local repository.
- The UI creates the data and stores it in the Local repository.
- The Local repository creates an entry in the OpLog.
- Success is returned to the UI.
- The Local repository persists the data in the SQLite database.
- Success is returned to the UI.
The following steps describe the manual synchronization process:
-
The user initiates the manual sync by selecting the Sync now option.
-
The UI sends a SyncSyncUpEvent to the Sync Bloc.
-
The Sync Bloc performs the sync operation.
-
The Network Manager retrieves the items to be synced down from the Local repository.
-
The Local repository queries the OpLog for pending down sync operations and returns a list of OpLog entries.
-
The network manager groups the OpLog entries by type.
-
For each entry group:
- The network manager sends a Bulk Search request to the Remote repository using the Client Reference IDs.
- The Remote repository returns the remote entities with Server Generated IDs.
- The network manager updates the server-generated ID in the OpLog and returns success.
- The network manager updates the server-generated ID in the SQLite database and returns success.
-
Success is returned to complete the sync down process.
-
The network manager retrieves the items to be synced up from the Local repository.
-
The Local repository queries the OpLog for pending up sync operations and returns a list of OpLog entries.
-
The network manager groups the OpLog entries by type and data operation.
-
For each entry group:
- If it is a CREATE operation:
- The network manager sends a Bulk create request to the Remote repository and returns success.
- If it is an UPDATE operation:
- The network manager sends a Bulk update request to the Remote repository and returns success.
- If it is a DELETE operation:
- The network manager sends a Bulk delete request to the Remote repository and returns success.
- If it is a SINGLE_CREATE operation:
- The network manager sends a Single create request to the Remote repository and returns success.
- If it is a CREATE operation:
-
Success is returned to complete the sync up process.
The source code is available on GitHub: Health Campaign Field Worker App Repository
-
Flutter SDK (latest stable version)
-
Android device or emulator
-
Clone the repository:
git clone https://github.com/egovernments/health-campaign-field-worker-app.git
-
Navigate to the project directory:
cd health-campaign-field-worker-app
-
Install dependencies:
flutter pub get
-
Create a
.env
file and add the following environment variables:BASE_URL= MDMS_API_PATH= TENANT_ID= ACTIONS_API_PATH= SYNC_DOWN_RETRY_COUNT= RETRY_TIME_INTERVAL= CONNECT_TIMEOUT= RECEIVE_TIMEOUT= SEND_TIMEOUT= HIERARCHY_TYPE="MICROPLAN" CHECK_BANDWIDTH_API="/project/check/bandwidth" ENV_NAME="DEMO"
-
Run the app:
flutter run
Contributions are welcome! Follow these steps to contribute:
-
Fork the repository.
-
Create a feature branch:
git checkout -b feature-name
-
Commit your changes:
git commit -m "Add some feature"
-
Push to the branch:
git push origin feature-name
-
Open a pull request.
For more detailed documentation, visit the DIGIT Health Platform.