Home / Help Center / pos-app-grocery / grocery / Mandi Rates
🥬 grocery

Mandi Rates

Mandi Rates is where a grocery or kirana shop records the day's wholesale/market ("mandi") buying price for produce and other items — vegetables, fruits, grains, dairy and spices — and can push that rate straight into a product's cost price and selling price with one click.

📍 Menu path: Grocery → Mandi Rates
👤 Who uses it: All roles with the Billing feature enabled

Overview

Every row is a rate for one item on one specific date — the page defaults to today but you can pick any past date to view or backfill rates.

Rates are grouped into six categories (Vegetable, Fruit, Grain, Dairy, Spice, Other), each with its own colour, so the table is easy to scan visually.

The standout feature is "Set Price": pick a mandi rate row, search for the matching product, choose a margin percentage, and the page computes and applies a new cost price + selling price to that product in one step — this is the fastest way to keep produce pricing current with daily market moves.

Before You Start

Step-by-Step Guide

1 Add today's mandi rates

  1. Open Grocery → Mandi Rates. The date field defaults to today; change it if you are backfilling an earlier day.
  2. Click "+ Add Rate", fill in Item Name, Category, Unit and Rate (Notes is optional), then click "Add Rate" to save.
  3. Repeat for each item you buy that day — vegetables and fruits are the categories most kirana stores update daily.

2 Edit or delete a rate

  1. Click "Edit" on any row to reopen the form with its values pre-filled — the Item Name field is locked while editing so you cannot accidentally rename it into a different item.
  2. Update Category, Unit, Rate or Notes as needed and click "Update".
  3. Click "Del" on a row to remove it entirely; you will be asked to confirm before it is deleted.

3 Filter and search the rate list

  1. Use the category chips (All, Vegetable, Fruit, Grain, Dairy, Spice, Other) to filter the table to one category at a time — click an already-active chip again to clear the filter back to All.
  2. Use the search box on the right to filter by item name as you type.
  3. Change the date field at any time to jump to a different day's rate sheet.

4 Apply a mandi rate to a product's price

  1. Click "Set Price" on the rate row you want to apply.
  2. The product search is pre-filled with the item's name — pick the matching product from the dropdown results (or search for a different one).
  3. Set the Margin % (defaults to 20%); the "New selling price" preview updates instantly as rate × (1 + margin/100), rounded to 2 decimals.
  4. Click "Update Price" — this sets the product's Cost Price to the mandi rate and its Selling Price to the computed value in one call.

Every Field & Button, Explained

Field / ButtonWhat it does
Item NameThe produce/item name (e.g. Tomato, Onion, Rice). Locked and non-editable once a rate row exists for that name+date — to rename, delete the row and add a new one.
CategoryOne of Vegetable, Fruit, Grain, Dairy, Spice or Other — drives both the colour coding and the category filter chips/counts.
Unitkg, g, dozen, piece, litre, packet or bundle — shown next to the rate everywhere it is displayed.
RateThe wholesale/mandi buying price for one unit on the selected date. Must be a valid number ≥ 0.
NotesOptional free-text note per rate row (e.g. "Nashik supply", "Grade A only").
Set Price — Margin %Percentage markup applied on top of the mandi rate to compute the product's new selling price; defaults to 20%.
Set Price — New selling priceLive preview: mandi rate × (1 + margin% / 100), rounded to 2 decimals — this is what gets written as the product's Price when you click Update Price.

Tips & Best Practices

Troubleshooting & FAQ

I cannot find the product I want in "Set Price".
The search matches the product's exact name/SKU as stored in Products — if the mandi item name and product name differ noticeably (e.g. "Tomato" vs "Tomato Hybrid 1kg"), try searching a shorter keyword.
Editing a rate does not seem to change the item name.
This is expected — the Item Name field is intentionally locked while editing, since rates are matched by item name + date internally. Delete the row and add a new one if you need a different name.
I added a rate for an item that already had one today — did it duplicate?
No — adding a rate for an item name that already has an entry for that date updates the existing row instead of creating a duplicate.
Can I see a price history / trend for one item?
Not yet from this screen — there is no chart or history view wired into the UI at the moment, even though the rates themselves are kept for every past date you have entered.

🧑‍💻 Developer Notes

Source component(s):

  • frontend-app/pos-app-grocery/src/pages/grocery/MandiRatePage.jsx

Backend endpoints used:

  • GET /grocery/mandi
  • POST /grocery/mandi
  • DELETE /grocery/mandi/:id
  • GET /grocery/mandi/history (implemented server-side; not yet called by any frontend page)
  • GET /products (search)
  • PUT /products/:id

Related tables (db-core repositories):

  • GroceryMandiRate
  • Product

Rates are upserted server-side by matching itemName + date (+ store/tenant), not by row id — this is why the Item Name field is locked during edit. Every read/write/delete on GroceryMandiRate is scoped by both storeId and tenantId; previously only storeId was checked, which meant two different single-store tenants (storeId null for both) could read, silently overwrite, or delete each other's mandi rates for the same item/date — this has been fixed by adding a tenantId condition to all four grocery.js functions (getMandiRates, upsertMandiRate, deleteMandiRate, getMandiHistory) and to the delete route, which previously passed no tenant/store scope at all.