---
description: >-
  This page explains the how the user contribute the receipt in the bolbhav from
  the Bolbhav App.
---

# User Flow

Here is the User Flow of the Bolbhav App.

### **Mandi Selection**

1. The initial screen presents a comprehensive list of all mandis currently active in the Bolbhav system, inviting users to actively engage and contribute.
2. Select the mandi where you want to contribute the receipt.
3.  **Mandi** **Discovery**

    Gramhal personalizes user mandi experience by highlighting the mandi most relevant to the user. Here's how it works:

    1. **Previously Engaged Mandi:** First highlight the crop within a mandi that users actively participated in before. This puts frequently visited mandis at the forefront, making it easier to find them and contribute again. Since users interacted with these mandis before, users are more likely to have receipts to upload for them, potentially earning them more silver tokens.
    2. **User Favourite Mandi:** Bolbhav highlights the mandi that users have previously engaged with, suggesting that it's their preferred one, especially since they've already shown interest in viewing prices there.
    3. **Explore Something New:** Finally, Bolbhav presents a remaining mandi for users to discover. This encourages users to explore different mandis.
4. This [**API**](https://bold-moon-807876.postman.co/workspace/Bolbhav-Android-app~337874ea-5b97-4a7a-85db-3f89368f6cf4/request/27013507-20c8a7e5-1ea0-4452-b15b-790198be69c2?ctx=documentation) is used to fetch the active mandis that are registered in the Bolbhav system.
5. **Search Discovery**
   1. The search feature allows users to search for market names in both English and Hindi.
6.  Under each mandi, user can find the current count of receipts uploaded today, indicating the number of receipts associated with that mandi for the present date.\
    \
    **Reason for showing the Receipt count under each mandi.**\
    &#x20;Inform users about the mandi with the highest receipt count and where other users are making significant contributions. This will encourage users to participate more actively in that mandi.\


    **For reference, here is the code snippet.**

    1. In this below code snippet, fetch the receipt count based on the mandi, approved receipt and today's date.

```python
def mandi_receipt_counts(mandi, mandi_receipt_count, user):
    filter_date = datetime.today().date()
    sale_receipts = SaleReceiptModel.query.filter(
        SaleReceiptModel.mandi_id == mandi.id,
        SaleReceiptModel.is_approved == True,
        db.func.date(SaleReceiptModel.receipt_date) == filter_date,
    ).all()
    for receipt in sale_receipts:
        mandi_receipt_count[receipt.mandi_id] = (
            mandi_receipt_count.get(receipt.mandi_id, 0) + 1
        )

    return mandi_receipt_count
```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2FpTMPmwN5ciFFv2ZJDcqk%2Fimage.png?alt=media&#x26;token=528c10a5-1a89-40e2-b5ee-5f44e0939dcf" alt="" width="230"><figcaption><p>Mandi Selection Screen</p></figcaption></figure>

### **Crop Selection**

1. Based on the chosen mandi, a list of crops commonly traded there appears.
   1. Select the specific crop for which the receipt is intended.
   2.  **Crop Discovery**

       Gramhal personalizes user crop corresponding to the mandi experience by highlighting the crop most relevant to user. Here's how it works:

       1. **Top Contribution:** First, highlight the crop within this mandi that the user contributed to the most in the past. This **provides ease** by allowing you to quickly revisit familiar crops and potentially earn more silver tokens for them. Since users are already familiar with the process, uploading receipts for these crops might be faster, making it easier to progress.
       2. **High Potential Earning:** Next up, we'll showcase the crop within this mandi that offers the highest potential silver token reward upon receipt upload. This lets user prioritize crops that could significantly boost user token earnings and those crops which have more tokens, it means either no receipt has been uploaded for them or very few receipts have been uploaded, and receipts should continue to be uploaded for those crops as well. Users can see the next available reward that they may receive for every crop to help them identify high-rewarding receipts and upload them. For Bolbhav, it's a better way to have diversified crop data as rewards will be more for crops having less receipts uploaded.
       3. **Explore Something New:** Finally, Bolbhav presents a random crop corresponding to the mandi for users to discover. Bolbhav surprised users with a less common crop corresponding to the mandi. This gives users a chance to discover unique crops user might not have noticed while scrolling and potentially unlock exciting more silver token earning opportunities!
   3. **Search Discovery**
      1. The search feature allows users to search for market names in both English and Hindi.
   4. This [**API**](https://bold-moon-807876.postman.co/workspace/Bolbhav-Android-app~337874ea-5b97-4a7a-85db-3f89368f6cf4/request/27013507-0255a35a-bed4-44e3-94de-a5410d40ef65?ctx=documentation) is used to fetch the crop corresponding to the mandi which is registered in the Bolbhav system.
   5. **More Crops Button:-**
      1. The user clicks on the More crops button which is at the bottom, and then a new screen appears where the user can select the not active corresponding to the mandi and contribute that crop.
   6. Under each crop, the user can find the current count of receipts uploaded today, indicating the number of receipts associated with that crop corresponding to the mandi for the present date.\
      \
      **Reason for showing the Receipt count under each mandi.**\
      Inform users about the crop corresponding to the mandi with the highest receipt count and where other users are making significant contributions. This will encourage users to participate more actively in that crop.\
      \
      **For reference, here is the code snippet.**\
      In this below code snippet, fetch the receipt count based on the mandi, approved receipt and today's date.

```python
filter_date = datetime.today().date()
    sale_receipts = SaleReceiptModel.query.filter(
        SaleReceiptModel.mandi_id == mandi_id,
        SaleReceiptModel.is_approved
        == True,  # Consider using is_approved directly in the query
        db.func.date(SaleReceiptModel.receipt_date) == filter_date,
    ).all()

    crop_sales_count = {}
    user_contribution_count = {}
    for user_sale_receipt in user_sale_receipts_for_mandi:
        user_contribution_count[user_sale_receipt.crop_id] = user_sale_receipt.count
    for receipt in sale_receipts:
        crop_sales_count[receipt.crop_id] = crop_sales_count.get(receipt.crop_id, 0) + 1

    crops_details = []
    all_child_crops = get_child_crops(crops, sale_receipts, user_contribution_count)
    for crop in crops:
        crop_promised_token_amount = calculate_eligible_tokens(mandi_id, crop.crop_id)
        child_crops = all_child_crops.get(crop.crop_id, [])
        all_child_crop = sorted(
            child_crops,
            key=lambda x: (
                x["user_crop_contribution_count"],
                x["sale_receipts_count"],
            ),
            reverse=True,
        )
        crop_receipt_count = crop_sales_count.get(crop.crop_id, 0)
```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2Fp8TaCv6weB2yxeR0S85P%2Fimage.png?alt=media&#x26;token=0bb104bd-c812-4933-a8ca-9351bdfeabbb" alt="" width="240"><figcaption><p>Crop Selection Screen</p></figcaption></figure>

### **Crop Variety Selection (If crop variety exist):**

1. **Purpose of this screen**
   1. Each parent crop can be readily distinguished from its child crops, simplifying the user's search process. Users can submit receipts by selecting the specific child crop associated with the parent crop.
2. This [**API**](https://bold-moon-807876.postman.co/workspace/Bolbhav-Android-app~337874ea-5b97-4a7a-85db-3f89368f6cf4/request/27013507-0255a35a-bed4-44e3-94de-a5410d40ef65?ctx=documentation) is used to fetch the active mandi which is registered in the Bolbhav system.
3. If the chosen crop has multiple varieties available, an additional screen appears for selecting the specific variety.
   1. If no variety exist for the crop, this step is skipped.
4. Under each child crop, the user can find the current count of receipts uploaded today, indicating the number of receipts associated with that crop corresponding to the mandi for the present date.

**For reference, here is the code snippet.**\
In this below code snippet, fetch the receipt count based on the mandi, approved receipt and today's date.

```python
def get_child_crops(
    crops: int, sale_receipts: SaleReceiptModel, user_contribution_count
):
    all_child_crops = {crop.crop_id: [] for crop in crops}

    child_crops_query = CropModel.query.filter(
        CropModel.parent_crop_id.in_([crop.crop_id for crop in crops]),
        CropModel.is_parent_crop == False,
    ).all()
    crop_sales_count = {}
    for receipt in sale_receipts:
        crop_sales_count[receipt.crop_id] = crop_sales_count.get(receipt.crop_id, 0) + 1
    for child_crop in child_crops_query:
        crop_receipt_count = crop_sales_count.get(child_crop.crop_id, 0)
        all_child_crops.setdefault(child_crop.parent_crop_id, []).append(
            {
                "crop_id": child_crop.crop_id,
                "crop_name": child_crop.crop_name,
                "crop_name_hi": child_crop.crop_name_hi,
                "sale_receipts_count": crop_receipt_count,
                "user_crop_contribution_count": user_contribution_count.get(
                    child_crop.crop_id, 0
                ),
            }
        )

    return all_child_crops
```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2FYhwGcwPFeQP4q28rA1yQ%2Fimage.png?alt=media&#x26;token=197e5ab1-fd92-4291-9169-b95a292fe8f2" alt="" width="179"><figcaption><p>Crop Varity Selection Screen</p></figcaption></figure>

### **Receipt Type:**

1.  The app offers two receipt options: printed and handwritten.

    1. **Printed Receipt:** Enter only the booklet number printed on the receipt.
    2. **Handwritten Receipt:** Enter both the booklet number and the unique receipt ID.

    <figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2FSBzMzyjCwHhsXeQeMeLL%2Fimage.png?alt=media&#x26;token=428b0cc3-1928-494d-b0c7-e6d26f9d299b" alt="" width="179"><figcaption></figcaption></figure>


2. **Duplication Receipt Checking:-**
   1. When the user clicks on the proceed further (जानकारी भरे) then the API call triggers for receipt duplication checking.
   2. This [**API**](https://bold-moon-807876.postman.co/workspace/Bolbhav-Android-app~337874ea-5b97-4a7a-85db-3f89368f6cf4/request/27013507-1b21b09c-6aeb-4cd4-9e4c-0d686985aec7?ctx=documentation) is used to check the duplicate receipt where we are passing the mandi ID, Crop ID, booklet number, receipt ID and current date, based on these attributes the system checks whether this receipt is already present in the system or not.
      1. If the receipt is not present in the system the API returns the empty array.
      2. If the receipt is present in the system then the API returns the receipt information.

```python
 # check duplicate entry start
    if booklet_number and receipt_id and mandi_id:
        existing_record = SaleReceiptModel.query.filter(
            SaleReceiptModel.booklet_number == booklet_number,
            SaleReceiptModel.receipt_id == receipt_id,
            SaleReceiptModel.mandi_id == mandi_id,
            func.date(SaleReceiptModel.receipt_date) == func.date(receipt_date),
        ).first()

        if existing_record:
            return jsonify({"error": "record already exists", "is_duplicate": True})
    # check duplicate entry end
```

1.  **Restrictions**

    1. **Booklet Number**
       1. The booklet number should be a numeric value.&#x20;
       2. The booklet number should be non-decimal.&#x20;
       3. The booklet number should be greater than 0 and not equal to 0.
       4.  **Receipt ID**

           1. The Receipt ID should be a numeric value.
           2. The Receipt ID should be non-decimal.
           3. The Receipt ID should be greater than 0 and not equal to 0.

           **For reference find the below code snippet.**

    <figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2F3Bl7Q3FYi9gvDkxDnHKU%2Fimage.png?alt=media&#x26;token=4cddde37-68a0-4e51-852b-5764c0755d68" alt=""><figcaption><p>Restrictions</p></figcaption></figure>

### **Crop Weight and Price:**

1. Enter the weight of the crop quantity mentioned in the receipt.&#x20;
2. The unit for this is quintals (1 quintal = 100 kgs).
3. Enter the price per quintal of the crop according to the receipt. The unit for this is INR.
4. **Restrictions**
   1. **Quantity**
      1. In the quantity field, users are restricted from inputting decimal numbers exceeding two digits.
      2. The Quantity field should be a numeric value.
   2. **Price**
      1. In the price field, users are restricted from inputting decimal numbers exceeding two digits.
      2. The Price field should be a numeric value.

```typescript
const decimalErrorWeight = 'दशमलव वजन संख्या केवल दो अंकों से अधिक नहीं होनी चाहिए';
const decimalErrorRate = 'दशमलव भाव संख्या केवल दो अंकों से अधिक नहीं होनी चाहिए';

const weightHasMoreThanTwoDecimal = hasMoreThanTwoDecimalDigits(weight);
const rateHasMoreThanTwoDecimal = hasMoreThanTwoDecimalDigits(rate);

  if (!weight || !rate || specialCharRegex.test(weight) || specialCharRegex.test(rate)) {
    if (!weight || !rate) {
      Alert.alert('कृपया सारी जानकारी भर के ही जमा करें।');
      return false;
    }

    if (specialCharRegex.test(rate)) {
      Alert.alert('कृपया भाव की सही जानकारी भरें');
      return false;
    }

    if (specialCharRegex.test(weight)) {
      Alert.alert('कृपया वजन की सही जानकारी भरें');
      return false;
    }

    return false;
  }

  if (parseInt(weight, 10) <= 0) {
    Alert.alert('कृपया वजन की सही जानकारी भरें');
    return false;
  }

  if (parseInt(rate, 10) <= 0) {
    Alert.alert('कृपया भाव की सही जानकारी भरें');
    return false;
  }

  if (weightHasMoreThanTwoDecimal || rateHasMoreThanTwoDecimal) {
    if (weightHasMoreThanTwoDecimal) {
      Alert.alert(decimalErrorWeight);
      return false;
    }
    if (rateHasMoreThanTwoDecimal) {
      Alert.alert(decimalErrorRate);
      return false;
    }
    return false;
}
```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2Ffa22wqIhidyUWDR2Kx1A%2Fimage.png?alt=media&#x26;token=1d183077-db5e-4c15-afdb-9f3696e8efad" alt="" width="235"><figcaption></figcaption></figure>

### **Receipt Image and Terms & Conditions:**

1.  When the user log in and comes to this screen first time, the Bolbhav terms and conditions pop-up will appear, prompting them to accept the Bolbhav terms and conditions.\


    <figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2Fe7qGZAooCQmRvP1ZRw7C%2Fimage.png?alt=media&#x26;token=b162be40-0b44-4d62-b3ae-c561ae36b2cb" alt="" width="270"><figcaption></figcaption></figure>
2. Capture a clear image of the entire sales receipt using the device's camera.
3. Ensure all details on the receipt are visible in the image.
4. Accepting the Bolbhav terms and conditions is mandatory to submit the receipt.
5.  **Restrictions**

    1. Users are limited to uploading images that are no larger than 10MB.
       1.  Users can only upload image files in the format specified below.

           ```json
           ['jpg', 'jpeg', 'png'
           ```

    **For reference, find the below code for the image validation.**

```typescript
const filename = image.uri.split('/').pop();
const fileExtension = filename.split('.').pop().toLowerCase();
    if (!allowedExtensions.includes(fileExtension)) {
      Alert.alert('फोटो फाइल फॉर्मेट गलत है');
      return false;
    }
    if (image.fileSize > maxAllowedSize) {
      Alert.alert('कृपया 10 एमबी से कम का फोटो का चयन करें');
      return false;
    }
```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2FZxmkG0JSWNW92PghZOyo%2Fimage.png?alt=media&#x26;token=5485e451-9221-4a51-aba5-89fa277dae39" alt="" width="231"><figcaption></figcaption></figure>

### **Receipt Owner (optional):**

1. If the receipt belongs to another farmer (the one who sold the produce), enter their phone number.&#x20;
2. Upon successful validation of the receipt, the owner earns 5 silver tokens as a reward.&#x20;
3. If there's no receipt owner, submit the contribution without entering a phone number.
4. **Restrictions**&#x20;
   1. Users can only submit the receipt owner's mobile number if the mobile number is equal and not more than and not less than 10 digits.
      1. The receipt owner's mobile number should not be present in the Bolbhav system.
5.  When the receipt owner's mobile number is submitted then the below WhatsApp message is triggered to the receipt owner's mobile number.

    ```python
    नमस्ते! 🙏🏽

    आपकी मंडी नीलामी पर्ची को हाल ही में बोलभाव ऐप पर जमा किया गया है।

    बोलभाव एक ऐसा मंच है जहाँ हज़ारों लोग अपनी नीलामी पर्चियाँ साझा करते हैं। अपनी पर्ची साझा करके आपने लाइव मंडी भाव की जानकारी सब तक पहुँचाने में मदद की है।👏🏽

    बोलभाव को इस लिंक से इंस्टॉल करें और अपनी और अन्यों की पर्चियाँ देखें:
    ```

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2F3f78XaHyS8FxB42KMi8W%2Fimage.png?alt=media&#x26;token=96842dca-77e3-4dd7-8ccc-1d47832258e3" alt="" width="209"><figcaption></figcaption></figure>

### **Receipt Submission:**

1. Once all details are entered and the image captured, submit the receipt details in the bolbhav system.
2. The Bolbhav team will validate the receipt information for accuracy.
3. When the user clicks on this \`**इसी फसल की और पर्ची जमा करें**\` button then user is redirected to the enter booklet and receipt ID screen with the same mandi and crop.
4. When the user clicks on this \`**दूसरे फसल की पर्ची जमा करें**\` button then user is redirected to the mandi selection screen which is the first screen of the Receipt Contribution Journey.

<figure><img src="https://3898150257-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrjNYs8KmxBlZvBKyEb2T%2Fuploads%2Fe5TRfV6wBJQmb77HbCFz%2Fimage.png?alt=media&#x26;token=9b99e735-cbed-42e5-8d63-b99a56e315fc" alt="" width="243"><figcaption><p>Receipt Submission Screen</p></figcaption></figure>

