Features / Farming models & harvest

ATM model (Anytime Money plot)

Records a farmer's ATM plot: a small raised-bed plot with many vegetables and a few pulses that earns income all year. "ATM = Anytime Money" is inferred from the APCNF/RySS programme; the code only says "ATM model", so confirm with the product team.

FactsheetFarming models & harvest
Who uses it
Field staff / CRP (regular cadre)Unit-in-charge / FMT (via farmer profile)
How you get here
Farmer profile > Options grid > ATM tile. Also reachable from the Sync Error log.
Tables
farming_model, ie_flat_entity
APIs
7 calls today, 10 App Service operations
Offline
Fully offline. Saves to farming_model and queues IE_ATM POST / POST_IMAGE in the sync ledger; ATMWorker uploads later. Down-sync happens on the Option and Data Setup screens in chunks of 30 IE ids, after which isATMFetched is set.

Screens

ScreenWhat it doesSource
ATM listShows the farmer's ATM records that are not fully harvested, with Edit, Geofencing and Harvest buttons per card.app/src/main/java/org/platformcommons/urvi/view/atm/ATMActivity.kt
Add / Edit ATMForm to create a new ATM or edit an existing one.app/src/main/java/org/platformcommons/urvi/view/atm/AddATMActivity.kt
Select ATM cropMulti-select chip picker for vegetable or pulse crops.app/src/main/java/org/platformcommons/urvi/view/atm/SelectATMCropFragment.kt

What it captures

FieldTypeRequiredValidationOptions from
Upload ImageImage (camera or gallery)NoCompressed and stored locally; a separate image upload is queued when a new image is picked.Device camera / gallery
Select landBottom-sheet pickerIf farmer is not C5 (hidden for C5)Shows survey code (prefix dropped), total acres and leased acres if any. A disabled land blocks saving with a "land disabled" dialog.Farmer's land assets
ATM Land (Acre's)?DecimalYesMust not be 0. Up to 2 whole digits and 2 decimals (0.01-99.99). Must fit the land limit (see rules). For non-C5 it appears only after land is chosen.User input
Raised Beds (4 ft beds, 1 ft furrows implemented?)Yes/NoYesFixed options
Vegetable Crops ("List the 15-18 vegetable crops")Multi-select chipsYesAt least 1. The 15-18 count is not enforced. Crops already added are excluded; ZBNF_FIELD_BEANS is always excluded.Product Master, major type PRODUCT_MAJOR_TYPE.VEGETABLES_LEAFY_TUBERS, Telugu or English names
Relay Cropping + Provide detailsYes/No + textIf at least 1 vegetable is selected (details required if Yes)Whole block is visible only when at least 1 vegetable is selected. Choosing No clears and disables details.User input
Maize CultivationYes/NoYesFixed options
Pulse Crops ("Specify the 2-3 pulse crops")Multi-select chipsNoThe 2-3 count is not enforced.Product Master, major type PRODUCT_MAJOR_TYPE.PULSES
Practices (NF Practices)Checkbox listYesAt least 1. The "A Grade" practice is removed from the list. Always stored as English names joined by " , " (local names are translated back via the practice code).Practice Master, user's language with English fallback
Income Generation ("Farm income generation started from the first") + detailsYes/No + numericYes (details required if Yes)The details input accepts numbers only although its hint says "Provide Details".User input

Rules

Conditions from the code, rewritten as plain decision rules.

WhenThen
Remote config PORTFOLIO_APP_CONFIG.ATM_EXTERNAL_SWITCH = 0 and the ATM tile is tappedToast "no entries allowed"; screen does not open.
Farmer has no categoryToast "update category".
Farmer category is C4 (not a farmer)Toast "C4 farmer has no access".
Farmer category is C5 (landless / kitchen garden)ATM opens with no land check; land picker is hidden.
Farmer has land but none of it is authenticatedToast "please authenticate land".
Every crop line item of an ATM is HARVEST_STATUS.COMPLETEDThat ATM is hidden from the list.
Several versions share the same titleIdOnly the version with the newest appCreatedAt is shown.
Farmer is C5 and already has an ATMAdd button is hidden (C5 gets at most one ATM).
Remote config KEY_GEOFENCING_FOR_ATM_SWITCH is not 0Geofencing button shows on each card: green with tick = synced, yellow with cloud = captured not synced, red = none.
Remote config PORTFOLIO_APP_CONFIG.HARVEST_ATM_EXTERNAL_SWITCH = 1Harvest button shows on each card.
Harvest is tapped and the ATM has no server idToast "Please sync ATM before adding harvest data".
Sync error is ERR_PLATFORM_ASSET_CHECKSUM_MISMATCHCard banner "Land details changed <current acres>".
Sync error is ERR_PLATFORM_ASSET_TOTAL_QUANTITY_LIMIT_EXCEEDCard banner "The entered ATM exceeds the total land you have."
Computing remaining landRemaining = (selected land total acres, or online total available land) - (current-season Crop Actual acres on this land, excluding fully harvested crops, counting only line items with the latest actual start date) - (sum of landSize of the latest version of every ATM on this land).
Farmer is C5ATM land must be <= 0.5 acre.
New ATM, or edit where the land changedATM land must be <= remaining land.
Edit on the same landATM land must be <= previous ATM size + remaining land.
Land limit is brokenToast "Land limit exceed."
Any required field is emptyToast "Please add all the data".
All validation passes"Confirm submission" dialog, then save.
An old ATM row stores crops as comma-separated names (vegetableCrops / pulseCrops) and is openedApp converts names into VEGETABLE / PULSE line items, saves, and queues a PATCH if the row is already on the server.
Chosen land already has a geofence and the ATM has noneThe land's geofence is copied to the ATM.
ATM is savedA new farming_model row is written every time (same appId and titleId on edit, new uuid and appCreatedAt), ie_flat_entity.hasATM = true, ledger IE_ATM / POST (depends on farmer IE POST if farmer unsynced, and on land POST if not C5 and land unsynced), plus IE_ATM / POST_IMAGE if an image was picked.

API contracts

Each call opens to its use case, headers, request and response bodies, and errors.

App Service v2: operationUse
GET /configTyped config bundle (ETag)
GET /farmers/snapshotCursor-paged hydrated farmer snapshot
GET /farmers/changesDelta sync: upserts and tombstones since a cursor
GET /farmers/{farmerId}/metricsOwned, leased, used and available acres
GET /farmers/{farmerId}/farming-modelsA farmer's ATM plots and DKG answers
POST /sync/batchApply an ordered batch of offline mutations
POST /filesCreate a file upload (resumable or single-shot)
GET /files/{fileId}File metadata and signed download URL
PATCH /files/{fileId}Append a chunk to a resumable upload
HEAD /files/{fileId}Current offset of a resumable upload

Behaviour notes

  • "ATM = Anytime Money" is inferred from programme context, not stated in code. Stored as farming_model.modelType = "MODEL_TYPE.ATM".
  • The list has one collapsible section "ATM : <current month>"; the multi-tab design was never used.
  • Before POST the worker fills owningEntityId from aliasId and assetId from the asset code if missing.
  • Possible bug · unverified down-sync (OptionViewModel / DataSetupViewModel) builds a list that excludes ATMs with pending sync, then inserts the unfiltered list, overwriting pending local edits.
  • Possible bug · unverified opening the list writes to the database and queues PATCHes for legacy rows (read with side effects).
  • Possible bug · unverified every edit creates a new uuid and full POST of a new version, so history grows unbounded.
  • Possible bug · unverified Income generation details is numeric-only with a hard-coded hint and a truncated label.

Improve in the rewrite

  • Show the land math on screen: total minus Crop Actual minus other ATMs equals available.
  • Decide whether the 15-18 vegetable and 2-3 pulse counts should be enforced; label them as guidance if not.
  • Move the 0.5-acre C5 limit and the ZBNF_FIELD_BEANS exclusion into config.
  • Replace toast-only validation with inline field errors.
  • Run the legacy crop-name migration once (e.g. on upgrade), not on every screen open.
  • Only skip pending-sync rows when merging down-synced ATMs.