The Idea

I work at my school's makerspace. We use monday.com to track ALL of our tasks. From keeping the space clean, to making sure each machine has it's proper maintenance. When I joined the space, I noticed one thing that we were trying to do, but just couldn't get right: we had a board with all of our 3D printer's filaments (in grams). We also had our online and in person submission boards, where we would track the 3D prints. So I had an idea: what if I could use the Monday API to find which prints have been paid for, and subtract that from the weight of that printer (tracked on a separate board).

Execution and Code

As an IT major, and a self taught programmer for 7+ years, I got to work. The first challenge was seeing how the Monday API worked; what data can we get, and what data can we send? The Monday API is surprisingly good at allowing you to pick apart what data you need.

The first thing I did was I checked for all of the printer's total weights. This would be my test to see if my idea could work.

def check_weights():
    query2 = '{boards(ids:[' + boards['master'] + ']) { name items { name column_values{text} } } }'
    data = {'query': query2}

    r = requests.post(url=apiUrl, json=data, headers=headers)
    resp = r.json()["data"]["boards"][0]["items"]
    weights = {}
    for i in range(len(resp)):
        if not resp[i]["column_values"][master['weight']]["text"]:
            weights[resp[i]["name"]] = 0
        else:
            weights[resp[i]["name"]] = float(
                resp[i]["column_values"][master['weight']]["text"])

    return weights

This allowed me to define the board ID of our "master" board at the top of the file (I left out the specific ID for security reasons), and store it in a dictionary. I can later access each printer's weight using it's name.

Once I was able to do that, I got started working on the code that would see which 3D printers actually needed updating:

def check_todo():  # method for checking to-do prints from hybrid and online systems
    hybridIds = {}
    subids = {}
    query = '{boards(ids:[' + boards['hybrid'] + ']) { name items { name column_values{text} } } }'  # Query for hybrid board
    data = {'query': query}
    r = requests.post(url=apiUrl, json=data, headers=headers)  # post method
    resp = r.json()["data"]["boards"][0]["items"]  # pull data from JSON response
    dictionary = {}
    for i in range(len(resp)):
        if str(resp[i]["column_values"][hybridMaster['internal']]["text"]).lower() != "true" and str(resp[i]["column_values"][hybridMaster['payment']][
                                                                                   "text"]).lower() == "paid":
            printer = resp[i]["column_values"][hybridMaster['printer']]["text"]
            weight = resp[i]["column_values"][hybridMaster['weight']]["text"]
            if printer in dictionary:  # placed in case multiple jobs have the same printer (so all weight is properly subtracted
                dictionary[printer] = float(dictionary[printer]) + float(weight)
            else:
                dictionary[printer] = weight

            if printer not in hybridIds:  # if the printer ID from the hybrid board hasn't been tracked
                hybridIds[printer] = resp[i]["column_values"][hybridMaster['id']]["text"]
            else:
                hybridIds[printer] = hybridIds[printer] + "," + resp[i]["column_values"][hybridMaster['id']][
                    "text"]

    query2 = '{boards(ids:[' + boards['submission'] + ']) { name items { name column_values{text} } } }'  # query for submission board
    data2 = {'query': query2}
    r2 = requests.post(url=apiUrl, json=data2, headers=headers)  # post method
    resp2 = r2.json()["data"]["boards"][0]["items"]  # pull data from JSON resp2onse
    for i in range(len(resp2)):
        if str(resp2[i]["column_values"][submission['internal']]["text"]).lower() != "true" and str(resp2[i]["column_values"][submission['payment']][
                                                                                   "text"]).lower() == "queued":
            printer = resp2[i]["column_values"][submission['printer']]["text"]
            weight = resp2[i]["column_values"][submission['weight']]["text"]
            if printer in dictionary:  # placed in case multiple jobs have the same printer (so all weight is properly subtracted
                dictionary[printer] = float(dictionary[printer]) + float(weight)
            else:
                dictionary[printer] = weight

            if printer not in subids:  # if the printer ID from the online submission board hasn't been tracked
                subids[printer] = resp2[i]["column_values"][submission['id']][
                    "text"]
            else:
                subids[printer] = subids[printer] + "," + resp2[i]["column_values"][submission['id']][
                    "text"]

    return dictionary, hybridIds, subids

This returned 3 dictionaries, one with the weight that needs to be subtracted from each printer, one that has the IDs for the rows on our Hybrid board (so that we can mark them as done or ("True") as seen in the video), and one that does the same for our other submissions board.

Then, all I needed to do was push all of the updates live:

def push_updates(update, hybridids, subids):  # push updates to board
    for i in update:
        query = 'mutation ($id: Int!)' \
                '{change_column_value' \
                '(board_id:' + boards['master'] + '' \
                ',item_id:$id,' \
                'column_id:"numbers",' \
                'value:"' + str(update[i]) + '") {id}}'  # mutation query
        vars1 = {"id": int(internalIDs[i])}  # append variables to query
        data = {'query': query, 'variables': vars1}
        requests.post(url=apiUrl, json=data, headers=headers)  # post request

        if i in hybridids and "," not in hybridids.get(i):  # if hybrid is one printer type
            query2 = 'mutation ($hybridID: Int!, $data: JSON!) {' \
                     'change_column_value(' \
                     'board_id:' + boards['hybrid'] + ',' \
                     'item_id:$hybridID,' \
                     'column_id:"status_15",' \
                     'value:$data)' \
                     ' {id}' \
                     '}'
            vars2 = {'hybridID': int(hybridids.get(i)),
                     'data': "{\"label\": \"True\"}"}  # JSON data for updating a status. this format is required by Monday API
            data2 = {'query': query2, 'variables': vars2}
            requests.post(url=apiUrl, json=data2, headers=headers)
        elif i in hybridids:
            ids = str(hybridids.get(i)).split(",")
            for currID in ids:
                query2 = 'mutation ($hybridID: Int!, $data: JSON!) {' \
                         'change_column_value(' \
                         'board_id:' + boards['hybrid'] + ',' \
                         'item_id:$hybridID,' \
                         'column_id:"status_15",' \
                         'value:$data)' \
                         ' {id}' \
                         '}'
                vars2 = {'hybridID': int(currID),
                         'data': "{\"label\": \"True\"}"}
                data2 = {'query': query2, 'variables': vars2}
                requests.post(url=apiUrl, json=data2, headers=headers)

        if i in subids and "," not in subids.get(i):  # if submission board is one printer type
            query2 = 'mutation ($subID: Int!, $data: JSON!) {' \
                     'change_column_value(' \
                     'board_id:' + boards['submission'] + ',' \
                     'item_id:$subID,' \
                     'column_id:"status_15",' \
                     'value:$data)' \
                     ' {id}' \
                     '}'
            vars2 = {'hybridID': int(subids.get(i)),
                     'data': "{\"label\": \"True\"}"}  # JSON data for updating a status. this format is required by Monday API
            data2 = {'query': query2, 'variables': vars2}
            requests.post(url=apiUrl, json=data2, headers=headers)
        elif i in subids:
            ids = str(subids.get(i)).split(",")
            for currID in ids:
                query2 = 'mutation ($subID: Int!, $data: JSON!) {' \
                         'change_column_value(' \
                         'board_id:' + boards['submission'] + ',' \
                         'item_id:$subID,' \
                         'column_id:"status_15",' \
                         'value:$data)' \
                         ' {id}' \
                         '}'
                vars2 = {'hybridID': int(currID),
                         'data': "{\"label\": \"True\"}"}
                data2 = {'query': query2, 'variables': vars2}
                requests.post(url=apiUrl, json=data2, headers=headers)
        query3 = 'mutation ($id: Int!, $status: JSON!)' \
                 '{change_column_value' \
                 '(board_id:' + boards['master'] + '' \
                 ',item_id:$id,' \
                 'column_id:"status",' \
                 'value:$status) {id}}'

        insert = "{\"label\": \"In Progress\"}"
        if update[i] <= 50:  # amount for "Low" spools
            if update[i] <= 0:  # amount for "empty" spools
                insert = "{\"label\": \"Empty\"}"
            else:
                insert = "{\"label\": \"Low\"}"
        vars3 = {"id": int(internalIDs[i]),
                 "status": insert}
        data3 = {'query': query3, 'variables': vars3}
        requests.post(url=apiUrl, json=data3, headers=headers)

This sent out a post request to all 3 boards to update the data we need. It sets the marked prints as checked so that the program does not account for them multiple times, it updates the amount of grams left on each printer, and it even changes a status so that staff can easily look at this board to know when certain items need to be replaced! This is just the general overview, while the code has been cleaned up since it was written it functions the same as when I wrote the initial write-up of the project. There is a full 11+ page write-up of this program here.

Closing Thoughts

Overall, I am very happy with the result of this project. It allows us to maintain our backend system nicely with Monday.com's API, as well as helps all of the staff and students be able to keep track of what 3D printers need to be changed, and which ones can stay on for a little longer.

Built With

Share this project:

Updates