ph_crop_varieties

Offline Flutter lookups for Philippine crop varieties using the PCIC/PABS reference data bundled with the package.

The package filters varieties using a crop line code, exact region, and growth stage. The farmer then selects a variety name from that list, and the returned CropVariety.varietyId is the value a consuming application can place in its on-premises PABS payload.

Features

  • Works offline with a bundled JSON asset
  • Filters by exact region and normalized line code and growth stage
  • Discovers the available growth stages for a line code and region
  • Resolves the selected variety name to its source variety ID
  • Allows the same variety ID across regions, stages, or distinct choices
  • Removes only completely identical choices from lookup results
  • Caches parsed data after the first successful load
  • Reports malformed data and ambiguous exact selections explicitly

Installation

Until the package is published, use a local path dependency:

dependencies:
  ph_crop_varieties:
    path: ../flutter-pg-crop-varieties

Then import its public library:

import 'package:ph_crop_varieties/ph_crop_varieties.dart';

Basic usage

final repository = CropVarietyRepository();

final growthStages = await repository.getGrowthStages(
  lineCode: 'CR',
  region: 1,
); // [days100, days110, days120, days130]

final varieties = await repository.getVarieties(
  lineCode: 'CR',
  region: 1,
  growthStage: 'days120',
);

final selected = await repository.findVariety(
  lineCode: 'CR',
  region: 1,
  growthStage: 'days120',
  varietyName: 'PSB Cn-01 (USMARC 104)',
);

final varietyIdForPabs = selected?.varietyId; // 406

getGrowthStages returns an immutable list in numeric day order. getVarieties returns an immutable, alphabetically sorted list. Both return an empty list when there are no matching records. findVariety returns null when the selected name is absent.

Use getVarieties with the first three parameters to populate the farmer's variety choices. Use findVariety with all four parameters, including the farmer-selected varietyName, to resolve the specific source varietyId.

Manual four-parameter verification

Developers can run the manual lookup test with values supplied from the command line. This exercises the bundled production data and prints the exact record that will supply the PABS variety ID.

From the package root in PowerShell, run:

flutter test `
  --reporter expanded `
  --dart-define=LINE_CODE=CR `
  --dart-define=REGION=1 `
  --dart-define=GROWTH_STAGE=days120 `
  --dart-define="VARIETY_NAME=PSB Cn-01 (USMARC 104)" `
  tool\manual_variety_lookup_test.dart

The result includes:

Resolved crop variety:
  lineCode: CR
  region: 1
  growthStage: days120
  varietyName: PSB Cn-01 (USMARC 104)
  varietyId: 406

Change the four --dart-define values to test another farmer selection. The test fails with a clear message when a parameter is missing or invalid, when the complete selection does not exist, or when the complete selection is ambiguous.

Lookup contract

Use these three values to populate a variety dropdown:

  • lineCode: RC for rice or CR for corn
  • region: the exact integer region belonging to the selected farm
  • growthStage: the exact source category, such as days100, days110, days120, or days130

Use the returned typed object as the selection. The complete selection key is:

lineCode + region + growthStage + varietyName

The ID is not globally unique and is not used by itself to filter the dropdown. Duplicate IDs are valid when the records apply to different regions, growth stages, or names.

If the same complete selection key maps to different IDs, findVariety throws CropVarietyDataException instead of choosing an arbitrary ID. An unrelated ambiguous key elsewhere in the source data does not prevent valid lookups.

Region handling

Region values are never inferred or remapped. Every Region value is used exactly as supplied in lib/data/varieties_clean.json.

The current data has no Region 10 records, so Region 10 lookups return an empty list. Adding valid Region 10 records to the JSON makes them available automatically without a code mapping change.

Future Farmers App integration

The future RCCR integration should:

  1. Map rice to RC and corn to CR.
  2. Resolve the region from the farmer's registered address.
  3. Ask the package for available growth stages, then varieties matching the selected stage.
  4. Keep the selected CropVariety object.
  5. Store selected.varietyName as the displayed form value.
  6. Store selected.varietyId as lot.pabsVarietyId.
  7. Send that existing varietyId field through the mobile and backend payload to PABS.

The package does not make network calls or send data to PABS. It supplies the authoritative source ID to the consuming application.

Custom JSON loader

Tests or trusted consumers can inject JSON while retaining the same validation and lookup behavior:

final repository = CropVarietyRepository.fromJsonLoader(
  () async => trustedJsonString,
);

Data updates

Keep lib/data/varieties_clean.json as valid standard JSON. Do not add JavaScript-style comments, remap regions, renumber IDs, or remove legitimate duplicate IDs. Run the full test suite after every data update:

flutter test

Validation

dart format --set-exit-if-changed .
flutter analyze
flutter test
dart pub publish --dry-run

The last command validates the package archive; it does not publish the package.

Libraries

ph_crop_varieties
Offline Philippine crop-variety lookup models and services.