11-22-2024 UPDATE

This commit is contained in:
Jadowyne Ulve 2024-11-22 17:04:03 -06:00
parent e21fab65ea
commit 05a6fbddb6
17 changed files with 803 additions and 106 deletions

Binary file not shown.

Binary file not shown.

125
api.py
View File

@ -184,6 +184,25 @@ def pagninate_transactions():
return jsonify({'transactions': transactions, "end": math.ceil(count/limit)}) return jsonify({'transactions': transactions, "end": math.ceil(count/limit)})
@database_api.route("/getTransaction")
def get_transaction():
id = int(request.args.get('id', 1))
database_config = config()
site_name = session['selected_site']
transaction = []
with psycopg2.connect(**database_config) as conn:
try:
with conn.cursor() as cur:
sql = f"SELECT * FROM {site_name}_transactions WHERE id=%s;"
cur.execute(sql, (id, ))
transaction = list(cur.fetchone())
except (Exception, psycopg2.DatabaseError) as error:
print(error)
print(transaction)
return jsonify(transaction=transaction)
@database_api.route("/getLocations") @database_api.route("/getLocations")
def get_locations(): def get_locations():
zone_name = request.args.get('zone', 1) zone_name = request.args.get('zone', 1)
@ -298,9 +317,39 @@ def addItem():
conn.commit() conn.commit()
with psycopg2.connect(**database_config) as conn:
try:
with conn.cursor() as cur:
cur.execute(f"SELECT primary_location FROM {site_name}_logistics_info WHERE id={logistics_info_id};")
location = cur.fetchone()[0]
payload = [
datetime.datetime.now(),
logistics_info_id,
barcode,
name,
"SYSTEM",
0.0,
"Item Added to System!",
1,
json.dumps({'location': location})
]
main.addTransaction(
conn=conn,
site_name=site_name,
payload=payload,
location=location,
logistics_info_id=logistics_info_id,
barcode=barcode,
qty=0.0)
except (Exception, psycopg2.DatabaseError) as error:
print(error)
conn.rollback()
return jsonify({'state': str(error)})
main.add_transaction(site_name, barcode, qty=0, user_id=1, description="Added Item to System!")
@ -328,19 +377,30 @@ def updateItem():
y = f"{', '.join(['%s' for _ in keys])}" y = f"{', '.join(['%s' for _ in keys])}"
sql = f"UPDATE {table} SET {x} = {y} WHERE id={item_id};" sql = f"UPDATE {table} SET {x} = {y} WHERE id={item_id};"
return sql sqltwo = f"SELECT {', '.join(keys)} FROM {table} WHERE id={item_id};"
return sql, sqltwo
if request.method == "POST": if request.method == "POST":
site_name = session['selected_site'] site_name = session['selected_site']
item_id = request.get_json()['id'] item_id = request.get_json()['id']
logistics_info_id = request.get_json()['logistics_info_id'] data = request.get_json()
logistics_info_id = request.get_json()['logistics_info_id']
food_info_id = request.get_json()['food_info_id'] food_info_id = request.get_json()['food_info_id']
item_info_id = request.get_json()['item_info_id'] item_info_id = request.get_json()['item_info_id']
updated = request.get_json()['updated'] updated = request.get_json()['updated']
item_info = request.get_json()['item_info'] item_info = request.get_json()['item_info']
food_info = request.get_json()['food_info'] food_info = request.get_json()['food_info']
logistics_info = request.get_json()['logistics_info'] logistics_info = data['logistics_info']
save_data = {}
for k, v in updated.items():
save_data[f"{k}_new"] = v;
for k, v in item_info.items():
save_data[f"{k}_new"] = v;
for k, v in food_info.items():
save_data[f"{k}_new"] = v;
for k, v in logistics_info.items():
save_data[f"{k}_new"] = v;
database_config = config() database_config = config()
@ -349,25 +409,64 @@ def updateItem():
with conn.cursor() as cur: with conn.cursor() as cur:
if updated != {}: if updated != {}:
values = transformValues(updated.values()) values = transformValues(updated.values())
sql = manufactureSQL(updated.keys(), item_id, f"{site_name}_items") sql, sqltwo = manufactureSQL(updated.keys(), item_id, f"{site_name}_items")
cur.execute(sqltwo)
old_data = dict(zip(updated.keys(), cur.fetchone()))
for k, v in old_data.items():
save_data[f"{k}_old"] = v;
cur.execute(sql, values) cur.execute(sql, values)
if item_info != {}: if item_info != {}:
values = transformValues(item_info.values()) values = transformValues(item_info.values())
sql = manufactureSQL(item_info.keys(), item_info_id, f"{site_name}_item_info") sql, sqltwo = manufactureSQL(item_info.keys(), item_info_id, f"{site_name}_item_info")
cur.execute(sqltwo)
old_data = dict(zip(item_info.keys(), cur.fetchone()))
for k, v in old_data.items():
save_data[f"{k}_old"] = v;
cur.execute(sql, values) cur.execute(sql, values)
if food_info != {}: if food_info != {}:
values = transformValues(food_info.values()) values = transformValues(food_info.values())
sql = manufactureSQL(food_info.keys(), food_info_id, f"{site_name}_food_info") sql, sqltwo = manufactureSQL(food_info.keys(), food_info_id, f"{site_name}_food_info")
cur.execute(sqltwo)
old_data = dict(zip(food_info.keys(), cur.fetchone()))
for k, v in old_data.items():
save_data[f"{k}_old"] = v;
cur.execute(sql, values) cur.execute(sql, values)
if logistics_info != {}: if logistics_info != {}:
values = transformValues(logistics_info.values()) values = transformValues(logistics_info.values())
sql = manufactureSQL(logistics_info.keys(), logistics_info_id, f"{site_name}_logistics_info") sql, sqltwo = manufactureSQL(logistics_info.keys(), logistics_info_id, f"{site_name}_logistics_info")
cur.execute(sqltwo)
old_data = dict(zip(logistics_info.keys(), cur.fetchone()))
for k, v in old_data.items():
save_data[f"{k}_old"] = v;
cur.execute(sql, values) cur.execute(sql, values)
cur.execute(f"SELECT barcode FROM {site_name}_items WHERE id={item_id};") cur.execute(f"SELECT {site_name}_items.barcode, {site_name}_items.item_name, {site_name}_logistics_info.primary_location FROM {site_name}_items LEFT JOIN {site_name}_logistics_info ON {site_name}_items.logistics_info_id = {site_name}_logistics_info.id WHERE {site_name}_items.id={item_id};")
barcode = cur.fetchone()[0] barcode, name, primary_location = cur.fetchone()
print(barcode) payload = [
main.add_transaction(site_name, barcode, 0, 1, "SYSTEM", "Item data was update!", data=request.get_json()) datetime.datetime.now(),
logistics_info_id,
barcode,
name,
"SYSTEM",
0.0,
"Updated Item!",
1,
json.dumps(save_data)
]
main.addTransaction(
conn=conn,
site_name=site_name,
payload=payload,
location=primary_location,
logistics_info_id=logistics_info_id,
barcode=barcode,
qty=0.0
)
except (Exception, psycopg2.DatabaseError) as error: except (Exception, psycopg2.DatabaseError) as error:
print(error) print(error)
conn.rollback() conn.rollback()

182
main.py
View File

@ -159,84 +159,108 @@ def add_zone(site_name, name):
conn.rollback() conn.rollback()
return error return error
def add_transaction(site_name, barcode, qty, user_id, transaction_type = "info", description = "", data = {}, location=None): def setLogisticsDataTransaction(conn, site_name, location, logistics_info_id, qty):
database_config = config() """Sets the logistic_info for site at info_id
with psycopg2.connect(**database_config) as conn:
Args:
conn (Object): psycopg2.connector
site_name (str): name of site where data is manipulated
location (str): location to be add or append to data
logistics_info_id (int): logistics data to be manipulated
qty (float): qty to be added or appended
Returns:
str: success/error
"""
with open(f"sites/{site_name}/sql/unique/logistics_transactions.sql", "r+") as file:
sql = file.read()
try:
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute(f"SELECT item_name, logistics_info_id FROM {site_name}_items WHERE barcode=%s;", (barcode, )) cur.execute(f"SELECT quantity_on_hand, location_data FROM {site_name}_logistics_info WHERE id=%s;", (logistics_info_id, ))
item = cur.fetchone() quantity_on_hand, location_data = cur.fetchone()
location_data[location] = location_data.get(location, 0) + qty
quantity_on_hand = float(quantity_on_hand + qty)
cur.execute(sql, (quantity_on_hand, json.dumps(location_data), logistics_info_id))
except Exception as error:
conn.rollback()
return error
return "success"
def setLocationData(conn, site_name, location, barcode, qty):
"""Sets location data to include barcode: qty as k:v pair
Args:
site_name (string): Name of the site to manipulate location data on
location (string): location in said site to manipulate locationd data on
barcode (string): Barcode to add or append to
qty (float): quantity to add or append to
Returns:
str: error/success
"""
with open(f"sites/{site_name}/sql/unique/set_location_data.sql", "r+") as file:
sql = file.read()
try:
with conn.cursor() as cur: with conn.cursor() as cur:
cur.execute(f"SELECT location_data, quantity_on_hand, primary_location, barcode FROM {site_name}_logistics_info WHERE id=%s;", (item[1],)) cur.execute(f"SELECT id, items FROM {site_name}_locations WHERE uuid=%s;", (location, ))
logistics_info = cur.fetchone() loc_id, items = cur.fetchone()
items[barcode] = items.get(barcode, 0) + qty
cur.execute(sql, (json.dumps(items), loc_id))
except Exception as error:
conn.rollback()
return error
return "success"
new_trans = copy.deepcopy(transaction_payload) def insertTransaction(conn, site_name, payload):
new_trans["timestamp"] = datetime.datetime.now() """Insert a transaction into the site name using a payload
new_trans["logistics_info_id"] = item[1]
new_trans["barcode"] = barcode
new_trans["user_id"] = user_id
new_trans["name"] = item[0]
new_trans["transaction_type"] = transaction_type
new_trans["description"] = description
new_trans["quantity"] = qty
new_trans["data"] = data
[timestamp, logistics_info_id, barcode, name, transaction_type,
quantity, description, user_id, data]
sql = f"INSERT INTO {site_name}_transactions(timestamp, logistics_info_id, barcode, name, transaction_type, quantity, description, user_id, data) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);" Args:
database_config = config() site_name (str): _description_
with psycopg2.connect(**database_config) as conn: payload (list): list of values to insert into database
try:
with conn.cursor() as cur:
cur.execute(sql, (new_trans["timestamp"], new_trans["logistics_info_id"], new_trans["barcode"], new_trans["name"], new_trans["transaction_type"],
new_trans["quantity"], new_trans["description"], new_trans["user_id"], json.dumps(new_trans["data"])))
except (Exception, psycopg2.DatabaseError) as error:
print(error)
conn.rollback()
return error
if not location:
mover = logistics_info[2]
else:
mover = location
location_items = None Returns:
location_id = None _type_: _description_
try: """
with conn.cursor() as cur: with open(f"sites/{site_name}/sql/unique/insert_transaction.sql", "r+") as file:
cur.execute(f"SELECT id, items FROM {site_name}_locations WHERE uuid=%s;", (mover, )) sql = file.read()
location = cur.fetchone() try:
if location: with conn.cursor() as cur:
location_id = location[0] cur.execute(sql, payload)
location_items = location[1] except Exception as error:
except (Exception, psycopg2.DatabaseError) as error: conn.rollback()
print(error) return error
conn.rollback()
return error
if logistics_info[3] in location_items.keys(): return "success"
location_items[logistics_info[3]] = location_items[logistics_info[3]] + qty
else:
location_items[logistics_info[3]] = qty
if mover in logistics_info[0].keys(): def addTransaction(*, conn, site_name, payload, location, logistics_info_id, barcode, qty):
logistics_info[0][mover] = logistics_info[0][mover] + qty """a complete function for adding a transaction to the system
else:
logistics_info[0][mover] = qty payload = [timestamp, logistics_info_id, barcode, name, transaction_type,
quantity, description, user_id, data]
Args:
conn (object): psycopg2.connector
site_name (str): The site to which will have a transaction added
payload (list): transaction payload
location (str): location in the site that will be manipulated
logistics_info_id (int): logistic_info id to be mainpulated
barcode (str): barcode in the site to be manipulated
qty (float): qty to be added or appened to the transaction
qty = logistics_info[1] + qty Returns:
str: success/error
set_location_data = f"UPDATE {site_name}_locations SET items = %s WHERE id = %s;" """
set_quantity_on_hand = f"UPDATE {site_name}_logistics_info SET quantity_on_hand = %s, location_data = %s WHERE id = %s;" try:
try: insertTransaction(conn, site_name, payload)
with conn.cursor() as cur: setLocationData(conn, site_name, location, barcode, qty)
cur.execute(set_quantity_on_hand, (qty, json.dumps(logistics_info[0]), new_trans["logistics_info_id"])) setLogisticsDataTransaction(conn, site_name, location, logistics_info_id, qty)
cur.execute(set_location_data, (json.dumps(location_items), location_id)) except (Exception, psycopg2.DatabaseError) as error:
except (Exception, psycopg2.DatabaseError) as error: print(error)
print(error) conn.rollback()
conn.rollback() return error
return error
conn.commit()
def add_food_item(site_name: str, barcode: str, name: str, payload: dict): def add_food_item(site_name: str, barcode: str, name: str, payload: dict):
@ -276,11 +300,10 @@ def add_food_item(site_name: str, barcode: str, name: str, payload: dict):
conn.rollback() conn.rollback()
return False return False
conn.commit() conn.commit()
payload = [datetime.datetime.now(), logistics_info_id, barcode, name, "SYSTEM", 0.0, "Item added to system!", 1, json.dumps({})]
add_transaction(site_name, barcode, qty=0, user_id=1, description="Added Item to System!") addTransaction(conn=conn, site_name=site_name,payload=payload, location=uuid, logistics_info_id=logistics_info_id,barcode=barcode, qty=0.0)
def drop_table(sql_file: str): def drop_table(sql_file: str):
database_config = config() database_config = config()
@ -369,8 +392,6 @@ def create_site(site_name):
conn.commit() conn.commit()
transaction_payload = { transaction_payload = {
"timestamp": None, "timestamp": None,
"logistics_info_id": 0, "logistics_info_id": 0,
@ -383,7 +404,6 @@ transaction_payload = {
"data": {} "data": {}
} }
payload_food_item = { payload_food_item = {
"item_info": { "item_info": {
"linked_items": [], "linked_items": [],
@ -447,20 +467,6 @@ def parse_csv(path_to_csv):
qty = float(line[30]) qty = float(line[30])
add_food_item(site_name="main", barcode=line[1], name=line[2], payload=payload) add_food_item(site_name="main", barcode=line[1], name=line[2], payload=payload)
if __name__ == "__main__": if __name__ == "__main__":
#print(add_readitem(site_name="main", barcode="1235", name="testone"))
"""database_config = config()
sql = "SELECT items FROM test_locations WHERE id=1;"
with psycopg2.connect(**database_config) as conn:
with conn.cursor() as cur:
cur.execute(sql)
items = cur.fetchone()[0]
for k, v in items.items():
print(f"{k}: {v}")
"""
parse_csv(r"C:\\Users\\jadow\\Documents\\code\\postgresql python\\postgresql-python\\2024-10-02-Pantry.csv") parse_csv(r"C:\\Users\\jadow\\Documents\\code\\postgresql python\\postgresql-python\\2024-10-02-Pantry.csv")

View File

@ -0,0 +1,3 @@
INSERT INTO %sitename%_transactions
(timestamp, logistics_info_id, barcode, name, transaction_type, quantity, description, user_id, data)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);

View File

@ -0,0 +1,3 @@
UPDATE %sitename%_logistics_info
SET quantity_on_hand = %s, location_data = %s
WHERE id = %s;

View File

@ -0,0 +1,3 @@
UPDATE %sitename%_locations
SET items = %s
WHERE id = %s;

View File

@ -0,0 +1,3 @@
INSERT INTO main_transactions
(timestamp, logistics_info_id, barcode, name, transaction_type, quantity, description, user_id, data)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s);

View File

@ -0,0 +1,3 @@
UPDATE main_logistics_info
SET quantity_on_hand = %s, location_data = %s
WHERE id = %s;

View File

@ -0,0 +1,3 @@
UPDATE main_locations
SET items = %s
WHERE id = %s;

View File

@ -91,6 +91,7 @@ function updatePrimaryLocation(){
document.getElementById('primary_location').style = "" document.getElementById('primary_location').style = ""
logistics_info['primary_location'] = `${primary_zone}@${primary_location}` logistics_info['primary_location'] = `${primary_zone}@${primary_location}`
}; };
console.log(logistics_info)
}; };
function updateIssueLocation(){ function updateIssueLocation(){
@ -201,6 +202,8 @@ async function saveItem() {
updated['links'] = links; updated['links'] = links;
}; };
console.log(`going into fetch ${logistics_info}`)
await fetch(`/updateItem`, { await fetch(`/updateItem`, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -213,8 +216,8 @@ async function saveItem() {
item_info_id: item[7], item_info_id: item[7],
updated: updated, updated: updated,
item_info: item_info, item_info: item_info,
food_info: food_info,
logistics_info: logistics_info, logistics_info: logistics_info,
food_info: food_info,
}), }),
}); });
M.toast({html: "Item has been saved successfully!", classes: "rounded green lighten-4 black-text"}); M.toast({html: "Item has been saved successfully!", classes: "rounded green lighten-4 black-text"});

View File

@ -0,0 +1,171 @@
let current_page = 1
let end_page;
let limit = 50
let search_text = ""
let zones;
async function setupZones() {
let primary_zone = document.getElementById('zone')
for (let i = 0; i < zones.length; i++){
let option = document.createElement('option')
option.value = zones[i]
option.innerHTML = zones[i]
primary_zone.appendChild(option)
};
};
async function fetchZones() {
const url = new URL('/getZones', window.location.origin);
const response = await fetch(url);
data = await response.json();
zones = data.zones;
};
async function fetchLocations(zone) {
const url = new URL('/getLocations', window.location.origin);
url.searchParams.append('zone', zone);
const response = await fetch(url);
data = await response.json();
return data.locations;
};
async function loadLocations() {
let zone = document.getElementById('zone').value
let locations = await fetchLocations(zone)
await setupLocations(locations, 'location')
};
async function setupLocations(locations, el) {
let loc_el = document.getElementById(el)
console.log(locations)
loc_el.innerHTML = ""
let option = document.createElement('option')
option.value = "undefined"
option.innerHTML = "Select Location..."
loc_el.appendChild(option)
for (let i = 0; i < locations.length; i++){
let option = document.createElement('option')
option.value = locations[i]
option.innerHTML = locations[i]
loc_el.appendChild(option)
};
};
async function fetchItems(){
if (current_page === 1){
document.getElementById('back').classList.add("disabled")
document.getElementById('back').classList.remove("waves-effect")
} else {
document.getElementById('back').classList.remove("disabled")
document.getElementById('back').classList.add("waves-effect")
};
const url = new URL('/getItems', window.location.origin);
url.searchParams.append('page', current_page);
url.searchParams.append('limit', limit);
await fetch(url)
.then(response => response.json())
.then(data => {
console.log(data)
end_page = parseInt(data.end)
if (current_page === end_page){
document.getElementById('forward').classList.add("disabled")
document.getElementById('forward').classList.remove("waves-effect")
} else {
document.getElementById('forward').classList.remove("disabled")
document.getElementById('forward').classList.add("waves-effect")
};
var table = document.getElementById("item_table")
while (table.rows.length > 0) {
table.deleteRow(0);
}
const header = table.createTHead();
const row = header.insertRow(0);
var header_database_id = row.insertCell();
header_database_id.classList.add('center')
var header_barcode = row.insertCell();
header_barcode.classList.add('center')
var header_name = row.insertCell();
header_name.classList.add('center')
header_name.classList.add('hide-on-med-and-down')
header_database_id.innerHTML = `<b>Database ID</b>`;
header_barcode.innerHTML = `<b>Barcode</b>`;
header_name.innerHTML = `<b>Product Name</b>`;
let colorstate = 1;
data.items.forEach(transaction => {
console.log(transaction)
var row = table.insertRow();
var row_id = row.insertCell();
row_id.classList.add('center')
var row_barcode = row.insertCell();
row_barcode.classList.add('center')
var row_name = row.insertCell();
row_name.classList.add('hide-on-med-and-down')
row_name.classList.add('center')
row_id.innerHTML = transaction[0];
row_barcode.innerHTML = transaction[1];
row_name.innerHTML = transaction[2];
if ((colorstate % 2) == 0){
row.classList.add('grey')
row.classList.add('lighten-5')
}
row.classList.add("custom_row")
row.addEventListener('click', function(){
clickRow(transaction[0])
})
colorstate++
});
})
}
async function clickRow(database_id){
let item = await fetchItem(database_id);
await populateFields(item)
};
async function populateFields(item){
document.getElementById("database_id").value = item[0];
document.getElementById("barcode").value = item[1];
document.getElementById("name").value = item[2];
document.getElementById("QOH").value = item[19];
let location = item[16].split('@')
await setLocation(location[0], location[1])
}
async function setLocation(zone, location){
document.getElementById('zone').value = zone
await loadLocations()
document.getElementById('location').value = location
};
async function fetchItem(database_id){
const url = new URL('/getItem', window.location.origin);
url.searchParams.append('id', database_id);
const response = await fetch(url);
data = await response.json();
return data.item;
}
document.getElementById('forward').addEventListener('click', async function(){
current_page++
await fetchItems()
})
document.getElementById('back').addEventListener('click', async function(){
current_page--
await fetchItems()
})

145
templates/itemLookup.html Normal file
View File

@ -0,0 +1,145 @@
<style>
.custom_row:hover{
background-color: rgb(230, 230, 230) !important;
cursor: pointer;
}
</style>
<div id="item_modal" class="modal">
<div class="modal-content">
<div class="row" style="gap: 5px;">
<div class="col s12">
<h4>Add Items...</h4>
</div>
<div class="col s12">
<div class="card-panel grey lighten-4 z-depth-0">
<span class="black-text"> Here is where you can search, add, and remove items from this group by checking or unchecking the items below. You can select
multiple at a time or simply one. Utilize the search bar to filter down quickly to items you need or simply scroll to your hearts content.
<br><br>
<b>WARNING:</b> clicking the checkbox will not save the changes right off the bat! You <b>MUST</b> click the Update Items button!
<br><br>
</span>
</div>
</div>
<div class="col s9 m6 offset-m3 input-field outlined align-center">
<i class="material-icons prefix">search</i>
<input style="border-radius: 20px; border: 1px solid #ccc;" id="search" name="search" type="search" placeholder="Search Items" value="">
</div>
<div class="col s12 center">
<a id="back" class="btn icon-left purple lighten-4 black-text z-depth-0"><i class="material-icons">chevron_left</i></a>
<a id="update_items" class="btn purple lighten-4 black-text z-depth-0">Update Items</a>
<a id="forward" class="btn icon-right purple lighten-4 black-text z-depth-0"><i class="material-icons">chevron_right</i></a>
</div>
<div class="divider col s12"></div>
<div id="table-container" class="col s12">
<table id="item_table">
</table>
</div>
</div>
</div>
</div>
<script>
let current_page = 1
let end_page;
let limit = 50
let search_text = ""
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {
// specify options here
});
});
async function fetchItems(){
if (current_page === 1){
document.getElementById('back').classList.add("disabled")
document.getElementById('back').classList.remove("waves-effect")
} else {
document.getElementById('back').classList.remove("disabled")
document.getElementById('back').classList.add("waves-effect")
};
const url = new URL('/getItems', window.location.origin);
url.searchParams.append('page', current_page);
url.searchParams.append('limit', limit);
await fetch(url)
.then(response => response.json())
.then(data => {
console.log(data)
end_page = parseInt(data.end)
if (current_page === end_page){
document.getElementById('forward').classList.add("disabled")
document.getElementById('forward').classList.remove("waves-effect")
} else {
document.getElementById('forward').classList.remove("disabled")
document.getElementById('forward').classList.add("waves-effect")
};
var table = document.getElementById("item_table")
while (table.rows.length > 0) {
table.deleteRow(0);
}
const header = table.createTHead();
const row = header.insertRow(0);
var header_database_id = row.insertCell();
header_database_id.classList.add('center')
var header_barcode = row.insertCell();
header_barcode.classList.add('center')
var header_name = row.insertCell();
header_name.classList.add('center')
header_name.classList.add('hide-on-med-and-down')
header_database_id.innerHTML = `<b>Database ID</b>`;
header_barcode.innerHTML = `<b>Barcode</b>`;
header_name.innerHTML = `<b>Product Name</b>`;
let colorstate = 1;
data.items.forEach(transaction => {
console.log(transaction)
var row = table.insertRow();
var row_id = row.insertCell();
row_id.classList.add('center')
var row_barcode = row.insertCell();
row_barcode.classList.add('center')
var row_name = row.insertCell();
row_name.classList.add('hide-on-med-and-down')
row_name.classList.add('center')
row_id.innerHTML = transaction[0];
row_barcode.innerHTML = transaction[1];
row_name.innerHTML = transaction[2];
if ((colorstate % 2) == 0){
row.classList.add('grey')
row.classList.add('lighten-5')
}
row.classList.add("custom_row")
row.addEventListener('click', function(){
test(transaction[0])
})
colorstate++
});
})
}
function test(database_id){
console.log(database_id)
};
document.getElementById('forward').addEventListener('click', async function(){
current_page++
await fetchItems()
})
document.getElementById('back').addEventListener('click', async function(){
current_page--
await fetchItems()
})
</script>

View File

@ -385,10 +385,10 @@
button_group.style = "margin-bottom: 0px; padding-bottom: 0px;" button_group.style = "margin-bottom: 0px; padding-bottom: 0px;"
button_group.innerHTML = ` button_group.innerHTML = `
<div class="col s12" style="align-items: center;"> <div class="col s12" style="align-items: center;">
<a href="/item/${item[0]}"class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="bottom" data-tooltip="Edit Item" style="display: inline-flex; border-radius: 20px 10px 20px 10px;"> <a href="/item/${item[0]}" class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="bottom" data-tooltip="Edit Item" style="display: inline-flex; border-radius: 20px 10px 20px 10px;">
<i class='material-icons'>edit</i> <i class='material-icons'>edit</i>
</a> </a>
<a class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="left" data-tooltip="Transactions" style="display: inline-flex; margin-right: 5px; margin-top:0px; border-radius: 20px 10px 20px 10px;"> <a href="/transactions/${item[0]}" class="btn right green lighten-3 black-text text-darken-2 z-depth-0 tooltipped" data-position="left" data-tooltip="Transactions" style="display: inline-flex; margin-right: 5px; margin-top:0px; border-radius: 20px 10px 20px 10px;">
<i class='material-icons'>list_alt</i> <i class='material-icons'>list_alt</i>
</a> </a>
</div>` </div>`

View File

@ -30,6 +30,15 @@
pointer-events: none; pointer-events: none;
opacity: 0.5; /* or your desired degree of transparency */ opacity: 0.5; /* or your desired degree of transparency */
} }
.custom_row:hover{
background-color: rgb(230, 230, 230) !important;
cursor: pointer;
}
.fixed-bottom {
position: absolute;
bottom: 10px;
width: 100%;
}
</style> </style>
<ul id='dropdown1' class='dropdown-content'> <ul id='dropdown1' class='dropdown-content'>
{% for site in sites %} {% for site in sites %}
@ -52,6 +61,12 @@
<li><a href="/items">Site Items</a></li> <li><a href="/items">Site Items</a></li>
<li><a href="/groups">Site Groups</a></li> <li><a href="/groups">Site Groups</a></li>
<li><a href="/shopping-lists">Site Shopping Lists</a></li> <li><a href="/shopping-lists">Site Shopping Lists</a></li>
<div class="fixed-bottom">
<li><a href="/transaction">Add Transaction</a></li>
<li class="disabled"><a href="/admin" class="disabled">Admin</a></li>
<li><a href="/logout" disabled>Logout</a></li>
</div>
</ul> </ul>
<body style="margin-bottom: 80px;"> <body style="margin-bottom: 80px;">
<div class="container section"> <div class="container section">
@ -89,6 +104,41 @@
</ul> </ul>
</div> </div>
</div> </div>
<div id="transaction_view" class="modal">
<div class="modal-content">
<div class="row">
<div class="col s12 green lighten-4">
<h5 class="center" style="border-radius: 10px;">Transaction Receipt</h5>
</div>
<div class="col s12">
<p id="trans_barcode"></p>
</div>
<div class="col s12">
<p id="trans_database_id"></p>
</div>
<div class="col s12">
<p id="trans_timestamp"></p>
</div>
<div class="col s12">
<p id="trans_name"></p>
</div>
<div class="col s12">
<p id="trans_type"></p>
</div>
<div class="col s12">
<p id="trans_qty"></p>
</div>
<div class="col s12">
<p id="trans_description"></p>
</div>
<div class="col s12">
<table id="transaction_data_table">
</table>
</div>
</div>
</div>
</div>
</body> </body>
<script> <script>
const item_id = {{id|tojson}} const item_id = {{id|tojson}}
@ -98,6 +148,11 @@
document.addEventListener('DOMContentLoaded', async function() { document.addEventListener('DOMContentLoaded', async function() {
await fetchTransactions(); await fetchTransactions();
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {});
}); });
async function fetchTransactions(){ async function fetchTransactions(){
@ -178,7 +233,6 @@
let colorstate = 1; let colorstate = 1;
data.transactions.forEach(transaction => { data.transactions.forEach(transaction => {
console.log(transaction) console.log(transaction)
table.c
var row = table.insertRow(); var row = table.insertRow();
var row_id = row.insertCell(); var row_id = row.insertCell();
@ -217,6 +271,10 @@
row.classList.add('green') row.classList.add('green')
row.classList.add('lighten-5') row.classList.add('lighten-5')
} }
row.classList.add("custom_row")
row.addEventListener('click', function(){
test(transaction[0])
})
colorstate++ colorstate++
}); });
document.getElementById("current_page").innerHTML = `${String(current_page)} / ${String(end_page)}` document.getElementById("current_page").innerHTML = `${String(current_page)} / ${String(end_page)}`
@ -224,6 +282,70 @@
}; };
async function fetchTransaction(transaction_id){
const url = new URL('/getTransaction', window.location.origin);
url.searchParams.append('id', transaction_id);
const response = await fetch(url);
data = await response.json();
return data.transaction;
}
async function test(transaction_id){
console.log(transaction_id)
let el = document.getElementById('transaction_view')
let modal = M.Modal.getInstance(el)
transaction = await fetchTransaction(transaction_id)
console.log(transaction)
document.getElementById('trans_barcode').innerHTML = `<b>Barcode:</b> ${transaction[3]}`;
document.getElementById('trans_database_id').innerHTML = `<b>Database ID:</b> ${transaction[0]}`;
document.getElementById('trans_timestamp').innerHTML = `<b>Timestamp:</b> ${transaction[1]}`;
document.getElementById('trans_name').innerHTML = `<b>Item Name:</b> ${transaction[4]}`;
document.getElementById('trans_type').innerHTML = `<b>Transaction Type:</b> ${transaction[5]}`;
document.getElementById('trans_qty').innerHTML = `<b>Qty:</b> ${transaction[6]}`;
document.getElementById('trans_description').innerHTML = `<b>Desription:</b> ${transaction[7]}`;
var table = document.getElementById("transaction_data_table")
while (table.rows.length > 0) {
table.deleteRow(0);
}
var header = table.createTHead();
var row = header.insertRow(0);
var header_key = row.insertCell();
header_key.classList.add('center')
var header_value = row.insertCell();
header_value.classList.add('center')
header_key.innerHTML = `<b>Key</b>`;
header_value.innerHTML = `<b>Value</b>`;
let colorstate = 1;
for(let key in transaction[9]){
console.log(key)
var row_trans = table.insertRow();
var row_key = row_trans.insertCell();
row_key.classList.add('center')
var row_value = row_trans.insertCell();
row_value.classList.add('center')
row_key.innerHTML = key;
row_value.innerHTML = JSON.stringify(transaction[9][key]);
if ((colorstate % 2) == 0){
row_trans.classList.add('green')
row_trans.classList.add('lighten-5')
};
colorstate++
};
modal.open()
};
document.getElementById('forward').addEventListener('click', async () =>{ document.getElementById('forward').addEventListener('click', async () =>{
if (!(document.getElementById("forward").classList.contains("disabled"))){ if (!(document.getElementById("forward").classList.contains("disabled"))){
current_page++ current_page++

128
templates/transaction.html Normal file
View File

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf-8" />
<title id="title"></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/css/materialize.min.css" />
<!-- Material Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<!-- Material Symbols - Outlined Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
<!-- Material Symbols - Rounded Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded" rel="stylesheet" />
<!-- Material Symbols - Sharp Set -->
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.0.3-alpha/dist/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
</head>
<style>
.custom_row:hover{
background-color: rgb(230, 230, 230) !important;
cursor: pointer;
}
</style>
<body>
<div class="container section">
<div class="row">
<div class="col s12">
<a href='{{ proto['referrer'] }}' class="left btn green lighten-4 black-text btn-flat"><i class="material-icons">arrow_back</i></a>
</div>
<div class="col s12">
<h5 class="center">Enter Transaction Receipt</h5>
</div>
<div class="col s11 m4 input-field outlined m-2">
<input id="database_id" type="text" placeholder=" " maxlength="20">
<label for="database_id">Database ID</label>
<!--<span class="supporting-text">Supporting Text</span>-->
</div>
<div class="col s1" style="margin-top: 15px;">
<a class="btn btn-flat green lighten-4 modal-trigger" href="#item_modal" style="display: flex; align-items: center; width: 120px;"><i class="material-symbols-outlined" style="padding-right: 10px;">search</i>Lookup</a>
</div>
<div class="col m7"> </div>
<div class="col s12 m6 input-field outlined m-2">
<input id="barcode" type="text" placeholder=" " maxlength="20">
<label for="barcode">Item Barcode</label>
<!--<span class="supporting-text">Supporting Text</span>-->
</div>
<div class="col s12 m6 input-field outlined m-2">
<input id="name" type="text" placeholder="" disabled>
<label for="name">Item Name</label>
</div>
<div class="col s7 m4 input-field outlined m-2">
<input id="QOH" type="text" placeholder="" disabled>
<label for="QOH">Quantity on Hand</label>
</div>
<div class="col s2" style="margin-top: 15px;">
<a class="btn btn-flat green lighten-4 modal-trigger" href="#locations" style="display: flex; align-items: center; width: 180px;"><i class="material-symbols-outlined" style="padding-right: 10px;">event_list</i>Item Locations</a>
</div>
<div class="col s12 divider"></div>
<div class="col s12 m6 m-2">
<label for="trans_type">Transaction Type</label>
<select id="trans_type" class="browser-default">
<option value="" disabled selected>Choose your option</option>
<option value="In">Adjust In</option>
<option value="Out">Adjust Out</option>
</select>
</div>
<div class="col s6 m3 m-2">
<label onchange="loadLocations()" for="zone">Zone</label>
<select id="zone" class="browser-default">
<option value="" disabled selected>Choose your option</option>
</select>
</div>
<div class="col s6 m3 m-2">
<label for="location">Location</label>
<select id="location" class="browser-default">
<option value="" disabled selected>Choose your option</option>
</select>
</div>
</div>
</div>
<div id="item_modal" class="modal">
<div class="modal-content">
<div class="row" style="gap: 5px;">
<div class="col s12">
<h4>Add Items...</h4>
</div>
<div class="col s12">
<div class="card-panel grey lighten-4 z-depth-0">
<span class="black-text"> Here is where you can search, add, and remove items from this group by checking or unchecking the items below. You can select
multiple at a time or simply one. Utilize the search bar to filter down quickly to items you need or simply scroll to your hearts content.
<br><br>
<b>WARNING:</b> clicking the checkbox will not save the changes right off the bat! You <b>MUST</b> click the Update Items button!
<br><br>
</span>
</div>
</div>
<div class="col s9 m6 offset-m3 input-field outlined align-center">
<i class="material-icons prefix">search</i>
<input style="border-radius: 20px; border: 1px solid #ccc;" id="search" name="search" type="search" placeholder="Search Items" value="">
</div>
<div class="col s12 center">
<a id="back" class="btn icon-left purple lighten-4 black-text z-depth-0"><i class="material-icons">chevron_left</i></a>
<a id="update_items" class="btn purple lighten-4 black-text z-depth-0">Update Items</a>
<a id="forward" class="btn icon-right purple lighten-4 black-text z-depth-0"><i class="material-icons">chevron_right</i></a>
</div>
<div class="divider col s12"></div>
<div id="table-container" class="col s12">
<table id="item_table">
</table>
</div>
</div>
</div>
</div>
</body>
<script src="{{ url_for('static', filename='transactionHandler.js') }}"></script>
<script>
document.addEventListener('DOMContentLoaded', async function() {
await fetchZones()
await setupZones()
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {
// specify options here
});
});
</script>

View File

@ -1,4 +1,4 @@
from flask import Flask, render_template, session from flask import Flask, render_template, session, request
import api, config import api, config
app = Flask(__name__) app = Flask(__name__)
app.secret_key = '11gs22h2h1a4h6ah8e413a45' app.secret_key = '11gs22h2h1a4h6ah8e413a45'
@ -20,6 +20,11 @@ def item(id):
sites = config.sites_config() sites = config.sites_config()
return render_template("items/item.html", id=id, current_site=session['selected_site'], sites=sites['sites']) return render_template("items/item.html", id=id, current_site=session['selected_site'], sites=sites['sites'])
@app.route("/transaction")
def transaction():
print(request.referrer)
sites = config.sites_config()
return render_template("transaction.html", current_site=session['selected_site'], sites=sites['sites'], proto={'referrer': request.referrer})
@app.route("/workshop") @app.route("/workshop")
def workshop(): def workshop():