endrizzimarco / FreshFarm

An application connecting farmers to consumers seeking fresh-produce. Mark achieved: 100
https://freshfarm.purpleflower-f3a7934e.northeurope.azurecontainerapps.io/#/
MIT License
0 stars 1 forks source link

Testing CosmosDb #11

Open abdullahzahid10 opened 1 year ago

abdullahzahid10 commented 1 year ago

Hi, I'm playing around with the cosmos DB.

If you can view my branch you can see 'No data available'. showing under the table in the farmers dashboard.

def main(req: func.HttpRequest) -> func.HttpResponse:
    # Initialize the Cosmos DB client
    endpoint = 'https://freshfarmdb.documents.azure.com:443/'
    key = '4g8dCbTnj1b3PPEVdmbEDmrCahKDYW1xvdlBnZQhL5Szl1tkRCUEUzH4IDgLP2dyIh4VyUQXtM1fACDbEEKA5A=='
    client = CosmosClient(endpoint, key)

    # Get a reference to the sales container
    database_name = 'FreshFarmDB'
    container_name = 'Sales'
    database = client.get_database_client(database_name)
    container = database.get_container_client(container_name)

    # Execute a query to retrieve sales data
    query = 'SELECT * FROM c'
    items = container.query_items(query, enable_cross_partition_query=True)

    # Format the sales data as needed
    sales_data_formatted = []
    for item in items:
        sale = {
            'farmerId': item['farmerId'],
            'customerName': item['customerName'],
            'type': item['type'],
            'collectionTime': item['collectionTime'],
            'price': item['price'],
        }
        sales_data_formatted.append(sale)

    # Return the formatted sales data as a JSON response
    return func.HttpResponse(sales_data_formatted)

The above is my azure function. Can you see if my credentials are okay or not, because im unable to debug the problem? The code below is the table which is displayed in farmers dashboard.

<template>
  <q-table
    :data="salesData"
    :columns="columns"
    v-model:pagination="pagination"
    :rows-per-page-options="[10, 25, 50, 100]"
  />
</template>

<script>
export default {
  name: 'SalesTable',
  data() {
    return {
      salesData: [],
      pagination: {
        rowsPerPage: 10
      },
      columns: [
        {
          name: 'farmerId',
          label: 'Farmer ID',
          align: 'left',
          field: 'farmerId'
        },
        {
          name: 'customerName',
          label: 'Customer Name',
          align: 'left',
          field: 'customerName'
        },
        {
          name: 'type',
          label: 'Type',
          align: 'left',
          field: 'type'
        },
        {
          name: 'collectionTime',
          label: 'Collection Time',
          align: 'left',
          field: 'collectionTime'
        },
        {
          name: 'price',
          label: 'Price',
          align: 'left',
          field: 'price'
        }
      ]
    }
  },
  mounted() {
    this.fetchSalesData()
  },
  methods: {
    async fetchSalesData() {
      try {
        const response = await fetch('/api/get-sales-data')
        const data = await response.json()
        this.salesData = data
      } catch (error) {
        console.error(error)
      }
    }
  }
}
</script>
endrizzimarco commented 1 year ago

Be careful to not hardcode credentials in code. People will easily steal it by crawling our github otherwise.

In regards to the function, you can copy the code from the read-offers function which reads all items in the offers table. For credentials, a connection string is used in functions.json: "CosmosDBConnectionString". I'll paste relevant the code here:

    {
      "type": "cosmosDB",
      "direction": "in",
      "name": "doc",
      "databaseName": "FreshFarmDB",
      "collectionName": "Offers",
      "createIfNotExists": "true",
      "connectionStringSetting": "CosmosDBConnectionString",
      "sqlQuery": "SELECT * from c"
    }

If you are wondering where that "CosmosDBConnectionString" comes from, it is saved as an environment variable in the function app for python. In your case, you'd need to access data from both the sales and offers databases so you'd need two of those configs for the two databases, as well as an additional connection string for the sales database.

Other things to keep in mind:

abdullahzahid10 commented 1 year ago

Hi, yes I will take care of the harcode in the code and place all the hardcode in a .env file. I made some changes but im still getting no data available. I checked chatgpt and it said there were no issues with the code and check with azure functions or cosmodb is working fine which looks like it is. I made changes from the example given.

init.py:

import logging
import azure.functions as func
import json

def main(req: func.HttpRequest, doc: func.DocumentList) -> func.HttpResponse:
    items = []
    for doc in doc:
        items.append(doc.to_dict())

    # Format the sales data as needed
    sales_data_formatted = []
    for item in items:
        sale = {
            'farmerId': item['farmerId'],
            'customerName': item['customerName'],
            'type': item['type'],
            'collectionTime': item['collectionTime'],
            'price': item['price'],
        }
        sales_data_formatted.append(sale)

    return func.HttpResponse(
            json.dumps(sales_data_formatted),
            status_code=200,
            mimetype="application/json")

functions.json

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "cosmosDB",
      "direction": "in",
      "name": "doc",
      "databaseName": "FreshFarmDB",
      "collectionName": "Offers",
      "createIfNotExists": "true",
      "connectionStringSetting": "CosmosDBConnectionString",
      "sqlQuery": "SELECT * from c"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

Farmersdashboard.vue:

<template>
  <q-table
    :data="sales_data_formatted"
    :columns="columns"
    v-model:pagination="pagination"
    :rows-per-page-options="[10, 25, 50, 100]"
  />
</template>

<script>
export default {
  name: 'SalesTable',
  data() {
    return {
      sales_data_formatted: [],
      pagination: {
        rowsPerPage: 10
      },
      columns: [
        {
          name: 'farmerId',
          label: 'Farmer ID',
          align: 'left',
          field: 'farmerId'
        },
        {
          name: 'customerName',
          label: 'Customer Name',
          align: 'left',
          field: 'customerName'
        },
        {
          name: 'type',
          label: 'Type',
          align: 'left',
          field: 'type'
        },
        {
          name: 'collectionTime',
          label: 'Collection Time',
          align: 'left',
          field: 'collectionTime'
        },
        {
          name: 'price',
          label: 'Price',
          align: 'left',
          field: 'price'
        },
        {
          name: 'id',
          label: 'ID',
          align: 'left',
          field: 'id'
        }
      ]
    }
  },
  mounted() {
    this.fetchSalesData()
  },
  methods: {
    async fetchSalesData() {
      try {
        const response = await fetch('/api/get-sales-data')
        const data = await response.json()
        this.sales_data_formatted = data
      } catch (error) {
        console.error(error)
      }
    }
  }
}
</script>

The code is now similar to the examples given but im not sure why it still says no data available. Also on this link https://portal.azure.com/#@com3014group11.onmicrosoft.com/resource/subscriptions/df4ddb4f-d337-4a4d-be8e-50e5a0996b2a/resourceGroups/freshfarm/providers/Microsoft.Web/sites/python3-functions/functionsList the trigger is set to CosmosDB rather than Httptrigger, maybe this could be a reason why?

I have also pushed my latest code to my branch

endrizzimarco commented 1 year ago

Are you getting no data available from the frontend?

From Azure, I am getting a 500 internal error when I call your function. Probably because it is trying to access data elements that is not there for every item. Change the code with item.get("customerName", "") for all of them and hopefully that fixes it. Otherwise keep testing from the Azure console, you can also look at logs to see the exact error

abdullahzahid10 commented 1 year ago

Yes on the frontend im getting no data available.

Screenshot 2023-04-10 at 15 47 10

So im testing them out on the azure plugin and I have 2 questions. Do i make the changes on the .py file or the .json file which you suggested and also when I change the code and saving it it is not updating when i open the code in azure, is there a specific button i need to press to push the code on azure for me to test the functions.

endrizzimarco commented 1 year ago

On the .py file, when you access dictionary elements. For the changes to take affect you need to push the code to github, there is a pipeline running which will deploy to azure.

abdullahzahid10 commented 1 year ago

thanks, sorry for the late response slipped out of my mind, but i got the hang of it and nearly done