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
| Screen | What it does | Source |
|---|---|---|
| ATM list | Shows 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 ATM | Form to create a new ATM or edit an existing one. | app/src/main/java/org/platformcommons/urvi/view/atm/AddATMActivity.kt |
| Select ATM crop | Multi-select chip picker for vegetable or pulse crops. | app/src/main/java/org/platformcommons/urvi/view/atm/SelectATMCropFragment.kt |
What it captures
| Field | Type | Required | Validation | Options from |
|---|---|---|---|---|
| Upload Image | Image (camera or gallery) | No | Compressed and stored locally; a separate image upload is queued when a new image is picked. | Device camera / gallery |
| Select land | Bottom-sheet picker | If 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)? | Decimal | Yes | Must 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/No | Yes | Fixed options | |
| Vegetable Crops ("List the 15-18 vegetable crops") | Multi-select chips | Yes | At 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 details | Yes/No + text | If 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 Cultivation | Yes/No | Yes | Fixed options | |
| Pulse Crops ("Specify the 2-3 pulse crops") | Multi-select chips | No | The 2-3 count is not enforced. | Product Master, major type PRODUCT_MAJOR_TYPE.PULSES |
| Practices (NF Practices) | Checkbox list | Yes | At 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") + details | Yes/No + numeric | Yes (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.
| When | Then |
|---|---|
| Remote config PORTFOLIO_APP_CONFIG.ATM_EXTERNAL_SWITCH = 0 and the ATM tile is tapped | Toast "no entries allowed"; screen does not open. |
| Farmer has no category | Toast "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 authenticated | Toast "please authenticate land". |
| Every crop line item of an ATM is HARVEST_STATUS.COMPLETED | That ATM is hidden from the list. |
| Several versions share the same titleId | Only the version with the newest appCreatedAt is shown. |
| Farmer is C5 and already has an ATM | Add button is hidden (C5 gets at most one ATM). |
| Remote config KEY_GEOFENCING_FOR_ATM_SWITCH is not 0 | Geofencing 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 = 1 | Harvest button shows on each card. |
| Harvest is tapped and the ATM has no server id | Toast "Please sync ATM before adding harvest data". |
| Sync error is ERR_PLATFORM_ASSET_CHECKSUM_MISMATCH | Card banner "Land details changed <current acres>". |
| Sync error is ERR_PLATFORM_ASSET_TOTAL_QUANTITY_LIMIT_EXCEED | Card banner "The entered ATM exceeds the total land you have." |
| Computing remaining land | Remaining = (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 C5 | ATM land must be <= 0.5 acre. |
| New ATM, or edit where the land changed | ATM land must be <= remaining land. |
| Edit on the same land | ATM land must be <= previous ATM size + remaining land. |
| Land limit is broken | Toast "Land limit exceed." |
| Any required field is empty | Toast "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 opened | App 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 none | The land's geofence is copied to the ATM. |
| ATM is saved | A 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.
| Today: call | Use | Replaced by |
|---|---|---|
GET /gateway/portfolio-service/api/v1/farming-model/ownerEntities?ownerEntityIds=&ownerEntityType=ENTITY_TYPE.IE | Download farming models (ATM/DKG) for a chunk of farmers. | |
GET /gateway/portfolio-service/api/v1/farming-model/attachment/bulk?farmingModelIds= | Download farming-model attachments in bulk. | |
GET /gateway/asset-service/api/v1/assets/{assetId} | Refetch one asset from the server to repair a sync error. | |
GET /gateway/portfolio-service/api/v1/farming-model/ownerEntities/actual?ownerEntityId&ownerEntityType&date&appCreatedAt | Refresh a farmer's current farming model (ATM). | |
GET /rtld/api/dataset/v1/execute?name=PlusOneGetATMNFUsedAcreageByIEID | Get acreage already used by ATM/natural farming, used to validate entries. | |
POST /gateway/portfolio-service/api/v1/farming-model | Create a farming model (ATM / DKG). | |
POST /gateway/portfolio-service/api/v1/farming-model/attachment/custom | Upload an ATM photo or ATM KML geofence. |
| App Service v2: operation | Use |
|---|---|
GET /config | Typed config bundle (ETag) |
GET /farmers/snapshot | Cursor-paged hydrated farmer snapshot |
GET /farmers/changes | Delta sync: upserts and tombstones since a cursor |
GET /farmers/{farmerId}/metrics | Owned, leased, used and available acres |
GET /farmers/{farmerId}/farming-models | A farmer's ATM plots and DKG answers |
POST /sync/batch | Apply an ordered batch of offline mutations |
POST /files | Create 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.