From 6dd33c29229fb9e31a9fa74b4fede9109a90f8af Mon Sep 17 00:00:00 2001 From: Jadowyne Ulve Date: Sun, 27 Apr 2025 17:28:45 -0500 Subject: [PATCH] items_API.paginateLoc and Zones updated --- .../database_items.cpython-312.pyc | Bin 9227 -> 12542 bytes .../__pycache__/items_API.cpython-312.pyc | Bin 39396 -> 39988 bytes application/items/database_items.py | 45 +++++++ application/items/items_API.py | 121 ++++++++++++------ .../items/sql/paginateLocationsBySkuZone.sql | 15 +++ .../sql/paginateLocationsBySkuZoneCount.sql | 15 +++ application/items/sql/paginateZonesBySku.sql | 15 +++ .../items/sql/paginateZonesBySkuCount.sql | 13 ++ 8 files changed, 184 insertions(+), 40 deletions(-) create mode 100644 application/items/sql/paginateLocationsBySkuZone.sql create mode 100644 application/items/sql/paginateLocationsBySkuZoneCount.sql create mode 100644 application/items/sql/paginateZonesBySku.sql create mode 100644 application/items/sql/paginateZonesBySkuCount.sql diff --git a/application/items/__pycache__/database_items.cpython-312.pyc b/application/items/__pycache__/database_items.cpython-312.pyc index fc4df4808c53ae4fb028bc4a96f3943723f7e2e7..7649beff351a6d4068b8d987789015d0287ff618 100644 GIT binary patch delta 1740 zcmds%UuauZ9LLYSxwpwpa+B0H|C-$V?Mz~4-K2GkYi76QmIb;wX~lIaF6L%iwN2bj zi>@T3gFO^fOgIm%e_-`RHU=_LWP;-CmJ;+OasG+22VWF?Yt})amE!N*P)Zy6;HwAj zk8{80`#a~{bAO-n_VJCl;Rl}AB4`7j8ZL~viUu21E(Uy7gQQ9_5|d;lHraNrO=`Qs zo>5DN;#qTk=a2@5IBBQKfvRm$wV>)+R2``LE%h8D=|SPQDLg2KOLWNiS>-J^bsfh% zUr+}>-|+lJ;a4pd>J+XTAJ<6KOEf|`2KNaQ*kILBEIulnpftE3MDPu(pU!IW1Hq5~ zw3@NY##{GgX}LG6i=y}R3Hm%r&@cNSU5^L#Zc2;K>dp9@c2k(i=~Hc4oy=tE44u{G zn5_0SBRR9}Ew9N^H(+_vCpX|;K|HU2+gAV7U%qAaT2FzpRIM+E)UO&bN%-@zG51Zb$ENF(N%v9>p$)z^*VndkEJ%{VI;{#wM*NUwb9-i&Ltce(|HRUxi3jh}=qi zoBk?Y&ipKlRGd;ltU9IN%=V81HK(T_)=VAqx}t6&w)o~xrYCAP$5s9N`VS3@7pt~V zfvs7c3&}#Z(E*dMAP5bWmg}w~2o0!}u(G+e1_S$1HucW~QwRx3s=;k0tZk(=NSczn z{?LM;R8IK3`PCep#3x>nQhn#}io9xxH4h=Q)YUHbsg`GI<5)kd0JCXg+zuU`! ze)j+eo)X21T6KwMMT@#*XJNGDV#NSg@~gp9>d_ESA1g-GrLc(ZfK8cnX?Xg zRLdTg9@>NB7VH0p22OKQei}}6rjOM3W1H1CoKD22#?z@L3IvKBIE0B^+TH#ivEU{) z7u*$%k*?iWlLz4wK7c3lZVMt-XO-!kjm=Ffj6`n(Bg0A=R!)r)NQ|af86bI1smIFm zW7{Y(w+C-VYwhNFN6~==Qkp@+3|?n_j;iNE6AMpwA+{Y0{D;>*3Je6548lN=)Nyb( z29S4LL7?eZ5C|$+1c7Gi76Mv10$&=UMngvYx9|9q2jNY*Ba~B6ZlG0=knDl5rWu$_ xOVbm{!!i^z+?sGk6+Gs@wr>@6Qitk$AuNonkp8v)EoreS-RyrzMr0Av{spj4(6j&m delta 205 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 VxR$8-25v@!f|+(M=s0nZ{~t^#@-qMc delta 4745 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 LCjXU}ck}-P5G2G} diff --git a/application/items/database_items.py b/application/items/database_items.py index a1c8bb5..978a6c6 100644 --- a/application/items/database_items.py +++ b/application/items/database_items.py @@ -128,3 +128,48 @@ def getPrefixes(site:str, payload:tuple, convert:bool=True): return recordset, count except (Exception, psycopg2.DatabaseError) as error: raise postsqldb.DatabaseError(error, payload, sql) + +def paginateZonesBySku(site: str, payload: tuple, convert=True): + database_config = config.config() + zones, count = (), 0 + with open(f"application/items/sql/paginateZonesBySku.sql", "r+") as file: + sql = file.read().replace("%%site_name%%", site) + with open(f"application/items/sql/paginateZonesBySkuCount.sql", "r+") as file: + sql_count = file.read().replace("%%site_name%%", site) + try: + with psycopg2.connect(**database_config) as conn: + with conn.cursor() as cur: + cur.execute(sql, payload) + rows = cur.fetchall() + if rows and convert: + zones = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows] + elif rows and not convert: + zones = rows + cur.execute(sql_count, payload) + count = cur.fetchone()[0] + return zones, count + except Exception as error: + raise postsqldb.DatabaseError(error, payload, sql) + +def paginateLocationsBySkuZone(site: str, payload: tuple, convert=True): + database_config = config.config() + locations, count = (), 0 + with open(f"application/items/sql/paginateLocationsBySkuZone.sql", "r+") as file: + sql = file.read().replace("%%site_name%%", site) + with open(f"application/items/sql/paginateLocationsBySkuZoneCount.sql", "r+") as file: + sql_count = file.read().replace("%%site_name%%", site) + try: + with psycopg2.connect(**database_config) as conn: + with conn.cursor() as cur: + cur.execute(sql, payload) + rows = cur.fetchall() + if rows and convert: + locations = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows] + elif rows and not convert: + locations = rows + cur.execute(sql_count, payload) + count = cur.fetchone()[0] + return locations, count + except Exception as error: + raise postsqldb.DatabaseError(error, payload, sql) + diff --git a/application/items/items_API.py b/application/items/items_API.py index dd15fb9..49601d6 100644 --- a/application/items/items_API.py +++ b/application/items/items_API.py @@ -223,56 +223,97 @@ def getModalPrefixes(): return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"}) return jsonify({"prefixes":recordset, "end":math.ceil(count/limit), "error":True, "message":f"method {request.method} is not allowed!"}) - -@items_api.route('/item/getZones', methods=['GET']) -def getZones(): - page = int(request.args.get('page', 1)) - limit = int(request.args.get('limit', 1)) - database_config = config() - site_name = session['selected_site'] - zones = [] - offset = (page - 1) * limit - payload = (limit, offset) - count = 0 - with psycopg2.connect(**database_config) as conn: - zones, count = database.getZonesWithCount(conn, site_name, payload, convert=True) - print(count, len(zones)) - return jsonify(zones=zones, endpage=math.ceil(count[0]/limit)) - - @items_api.route('/item/getZonesBySku', methods=["GET"]) +@login_required def getZonesbySku(): + """ GET zones by sku by passing page, limit, item_id + --- + parameters: + - in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: page of the records to GET + - in: query + name: limit + schema: + type: integer + minimum: 1 + default: 10 + description: number of records to grab from the system + - in: query + name: item_id + schema: + type: integer + minimum: 1 + default: 1 + description: item_id to pull zones for + responses: + 200: + description: Zones received successfully. + """ + zones, count = [], 0 if request.method == "GET": page = int(request.args.get('page', 1)) - limit = int(request.args.get('limit', 1)) + limit = int(request.args.get('limit', 10)) item_id = int(request.args.get('item_id')) - database_config = config() site_name = session['selected_site'] - zones = [] offset = (page - 1) * limit - payload = (item_id, limit, offset) - count = 0 - with psycopg2.connect(**database_config) as conn: - zones, count = db.ZonesTable.paginateZonesBySku(conn, site_name, payload) - print(zones, count) - return jsonify(zones=zones, endpage=math.ceil(count/limit)) + zones, count = database_items.paginateZonesBySku(site_name, (item_id, limit, offset)) + return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f''}) + return jsonify({'zones': zones, 'endpage': math.ceil(count/limit), 'error':False, 'message': f'method {request.method} not allowed.'}) @items_api.route('/item/getLocationsBySkuZone', methods=['get']) +@login_required def getLocationsBySkuZone(): - zone_id = int(request.args.get('zone_id', 1)) - part_id = int(request.args.get('part_id', 1)) - page = int(request.args.get('page', 1)) - limit = int(request.args.get('limit', 1)) - - offset = (page-1)*limit - database_config = config() - site_name = session['selected_site'] - locations = [] - count=0 - with psycopg2.connect(**database_config) as conn: - payload = (part_id, zone_id, limit, offset) - locations, count = db.LocationsTable.paginateLocationsBySkuZone(conn, site_name, payload) - return jsonify(locations=locations, endpage=math.ceil(count/limit)) + """ GET locations by sku by passing page, limit, item_id, zone_id + --- + parameters: + - in: query + name: page + schema: + type: integer + minimum: 1 + default: 1 + description: page of the records to GET + - in: query + name: limit + schema: + type: integer + minimum: 1 + default: 10 + description: number of records to grab from the system + - in: query + name: item_id + schema: + type: integer + minimum: 1 + default: 1 + description: item_id to pull locations for zone_id + - in: query + name: zone_id + schema: + type: integer + minimum: 1 + default: 1 + description: zone_id to pull locations for item_id + responses: + 200: + description: Zones received successfully. + """ + locations, count = [], 0 + if request.method == "GET": + zone_id = int(request.args.get('zone_id', 1)) + part_id = int(request.args.get('part_id', 1)) + page = int(request.args.get('page', 1)) + limit = int(request.args.get('limit', 1)) + offset = (page-1)*limit + site_name = session['selected_site'] + locations, count = database_items.paginateLocationsBySkuZone(site_name, (part_id, zone_id, limit, offset)) + return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': False, 'message': f''}) + return jsonify({'locations': locations, 'endpage': math.ceil(count/limit), 'error': True, 'message': f'method {request.method} is not allowed.'}) @items_api.route('/item/getLocations', methods=['get']) diff --git a/application/items/sql/paginateLocationsBySkuZone.sql b/application/items/sql/paginateLocationsBySkuZone.sql new file mode 100644 index 0000000..6574408 --- /dev/null +++ b/application/items/sql/paginateLocationsBySkuZone.sql @@ -0,0 +1,15 @@ +WITH passed_id AS (SELECT %s AS passed_id), + cte_item_locations AS ( + SELECT DISTINCT ils.location_id FROM %%site_name%%_item_locations ils + WHERE ils.part_id = (SELECT passed_id FROM passed_id) + ), + cte_locations AS ( + SELECT DISTINCT locations.zone_id FROM %%site_name%%_locations locations + WHERE locations.id IN (SELECT location_id FROM cte_item_locations) + ) + + +SELECT DISTINCT location.* FROM cte_item_locations cil +JOIN %%site_name%%_locations location ON cil.location_id = location.id +WHERE location.zone_id = %s +LIMIT %s OFFSET %s; diff --git a/application/items/sql/paginateLocationsBySkuZoneCount.sql b/application/items/sql/paginateLocationsBySkuZoneCount.sql new file mode 100644 index 0000000..9a2fb9d --- /dev/null +++ b/application/items/sql/paginateLocationsBySkuZoneCount.sql @@ -0,0 +1,15 @@ +WITH passed_id AS (SELECT %s AS passed_id), + cte_item_locations AS ( + SELECT DISTINCT ils.location_id FROM %%site_name%%_item_locations ils + WHERE ils.part_id = (SELECT passed_id FROM passed_id) + ), + cte_locations AS ( + SELECT DISTINCT locations.zone_id FROM %%site_name%%_locations locations + WHERE locations.id IN (SELECT location_id FROM cte_item_locations) + ) + + +SELECT COUNT(DISTINCT location.*) FROM cte_item_locations cil +JOIN %%site_name%%_locations location ON cil.location_id = location.id +WHERE location.zone_id = %s +LIMIT %s OFFSET %s; diff --git a/application/items/sql/paginateZonesBySku.sql b/application/items/sql/paginateZonesBySku.sql new file mode 100644 index 0000000..16f8cb3 --- /dev/null +++ b/application/items/sql/paginateZonesBySku.sql @@ -0,0 +1,15 @@ +WITH passed_id AS (SELECT %s AS passed_id), + cte_item_locations AS ( + SELECT DISTINCT ils.location_id FROM %%site_name%%_item_locations ils + WHERE ils.part_id = (SELECT passed_id FROM passed_id) + ), + cte_locations AS ( + SELECT DISTINCT locations.zone_id FROM %%site_name%%_locations locations + WHERE locations.id IN (SELECT location_id FROM cte_item_locations) + ) + + +SELECT DISTINCT zone.* FROM cte_locations cil +JOIN %%site_name%%_zones zone ON cil.zone_id = zone.id +LIMIT %s OFFSET %s; + diff --git a/application/items/sql/paginateZonesBySkuCount.sql b/application/items/sql/paginateZonesBySkuCount.sql new file mode 100644 index 0000000..4174fba --- /dev/null +++ b/application/items/sql/paginateZonesBySkuCount.sql @@ -0,0 +1,13 @@ +WITH passed_id AS (SELECT %s AS passed_id), + cte_item_locations AS ( + SELECT DISTINCT ils.location_id FROM %%site_name%%_item_locations ils + WHERE ils.part_id = (SELECT passed_id FROM passed_id) + ), + cte_locations AS ( + SELECT DISTINCT locations.zone_id FROM %%site_name%%_locations locations + WHERE locations.id IN (SELECT location_id FROM cte_item_locations) + ) + +SELECT COUNT(DISTINCT zone.*) FROM cte_locations cil +JOIN %%site_name%%_zones zone ON cil.zone_id = zone.id +LIMIT %s OFFSET %s;