From 34072739598061617459dfceb06c692356a1aaa5 Mon Sep 17 00:00:00 2001 From: Jadowyne Ulve Date: Sat, 26 Apr 2025 19:22:41 -0500 Subject: [PATCH] recipe_api.postSkuItem updated to new schema --- .../database_recipes.cpython-312.pyc | Bin 7607 -> 10050 bytes .../__pycache__/recipes_api.cpython-312.pyc | Bin 18083 -> 17989 bytes scripts/recipes/database_recipes.py | 36 ++++++++ scripts/recipes/recipes_api.py | 82 ++++++++++-------- scripts/recipes/sql/getItemData.sql | 4 + scripts/recipes/sql/postRecipeItem.sql | 4 + 6 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 scripts/recipes/sql/getItemData.sql create mode 100644 scripts/recipes/sql/postRecipeItem.sql diff --git a/scripts/recipes/__pycache__/database_recipes.cpython-312.pyc b/scripts/recipes/__pycache__/database_recipes.cpython-312.pyc index 5389543a17b2cfa205acc031ac287ac77f097ce1..f923b9de2a52fd8b94a18f1f85f92c651a0c8619 100644 GIT binary patch delta 1239 zcmY*YO>7%Q6rS1L@p^Z?jyLwM6Q_>zV-rl1QWsJL34!3X1QPTB1fgC~lHIgv3wFnr z+DeW>q@Fm{j1WZ}NKa5zNC6+nscLX;TtE?`azU!Zi3@UMP^2OO@7YPyj^%IO``-87 z{Jh!kroKNl_Je8a1jhI!^Q;sn6icvx)$%L#%Pf0a!uBRJ&6jy^)`lv>1(WItTH9k_6_>dUVQZyh+u_5tstU#B=n(T-_W3wU~ zd6fpmWqXv4idrPT`dY<*-<_|_AA^%{1`A}v950vS?zx75UEl^n2*E@MBlIHR33&v; z0%&T5%Zq-gvRwS2X=2@l`LbW&yvVZ#kD@AufOo|mfVpOX`-?^Hap*ANeF*&s34{TF zCi5}9j2jp_9DERC#u>kIZ~~qI1~baTqU6}DC7EnWtc9WlT^rnR?^^b!1GNE>Y!S^I zTp#__?*B3I(vJOdi%_dT@3?mpgI{Dn%YJ_Jm&C+RiHWa@o0Xk}do8~wWBk6j@8m?R zH*z8h>75#TG8En=0DB5bx`iI>$p?Z5`!exPuY2yg?Nai!m7kPvhw>@5r4Q$$>ekU& z8=MBwfNy9TNE%U=KVmfcROC}E|D@JPs~8;*Vsw(_XVk_EGTJkU+qB<3DQ_p@Zcg6L zF|cblocdYyUs>nFa2tFCKzwMNVmyu3&qjtl1;#}EKVws&V`4M%dY~&5x^+V3qnMNy zvrfNw&obCJxNf~@y{*ujV%wh49~QkS!j_Zj$PZg~*hXwcr%r|)2Xn4|-pNqf7Pa_A z(G%9{iRhX{pMXag6C1W3!!|yAg!~vLKaHEP!}y)O=`SvqeAMt~Aaq8YcT&d59ql=| zboTt_v*HuyAI5VKs{bATQfAX&U8&y~SfDg4lw@|esVo$W7dmf*39ON9feGw^{_I^-O2lh_%t%O^cP}@#JnA T?CWw@FxQFv1yq#JLc#w5#hnv^ delta 377 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 diff --git a/scripts/recipes/database_recipes.py b/scripts/recipes/database_recipes.py index 06ffcb1..4f02266 100644 --- a/scripts/recipes/database_recipes.py +++ b/scripts/recipes/database_recipes.py @@ -24,6 +24,24 @@ def getModalSKUs(site, payload, convert=True): return rows, count return [], 0 +def getItemData(site:str, payload:tuple, convert:bool=True): + database_config = config.config() + record = () + try: + with psycopg2.connect(**database_config) as conn: + with conn.cursor() as cur: + with open("scripts/recipes/sql/getItemData.sql") as file: + sql = file.read().replace("%%site_name%%", site) + cur.execute(sql, payload) + rows = cur.fetchone() + if rows and convert: + record = postsqldb.tupleDictionaryFactory(cur.description, rows) + if rows and not convert: + record = rows + return record + except (Exception, psycopg2.DatabaseError) as error: + raise postsqldb.DatabaseError(error, payload, sql) + def getRecipes(site:str, payload:tuple, convert=True): recordset = [] count = 0 @@ -81,6 +99,24 @@ def postRecipe(site:str, payload:tuple, convert=True): return record except (Exception, psycopg2.DatabaseError) as error: raise postsqldb.DatabaseError(error, payload, sql) + +def postRecipeItem(site:str, payload:tuple, convert=True): + database_config = config.config() + record = () + with open("scripts/recipes/sql/postRecipeItem.sql") as file: + sql = 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.fetchone() + if rows and convert: + record = postsqldb.tupleDictionaryFactory(cur.description, rows) + elif rows and not convert: + record = rows + return record + except (Exception, psycopg2.DatabaseError) as error: + raise postsqldb.DatabaseError(error, payload, sql) def postRecipeUpdate(site, payload, convert=True): database_config = config.config() diff --git a/scripts/recipes/recipes_api.py b/scripts/recipes/recipes_api.py index 24b0f00..ad39ce5 100644 --- a/scripts/recipes/recipes_api.py +++ b/scripts/recipes/recipes_api.py @@ -57,6 +57,7 @@ def recipe(id, mode='view'): return render_template("recipes/recipe_view.html", recipe_id=id, current_site=session['selected_site']) @recipes_api.route('/recipes/getRecipes', methods=["GET"]) +@login_required def getRecipes(): """ Get a subquery of recipes from the database by passing a page, limit --- @@ -76,6 +77,7 @@ def getRecipes(): return jsonify({'recipes': recipes, 'end': math.ceil(count/limit), 'error': True, 'message': f'method is not allowed: {request.method}'}) @recipes_api.route('/recipe/getRecipe', methods=["GET"]) +@login_required def getRecipe(): """ Get a query for recipe id from database by passing an id --- @@ -93,6 +95,7 @@ def getRecipe(): return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed'}) @recipes_api.route('/recipes/addRecipe', methods=["POST"]) +@login_required def addRecipe(): """ post a new recipe into the database by passing a recipe_name and recipe description --- @@ -118,6 +121,7 @@ def addRecipe(): return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method}'}) @recipes_api.route('/recipe/getItems', methods=["GET"]) +@login_required def getItems(): """ Pass along a page, limit, and search strings to get a pagination of items from the system --- @@ -130,21 +134,20 @@ def getItems(): if request.method == "GET": page = int(request.args.get('page', 1)) limit = int(request.args.get('limit', 10)) - search_string = request.args.get('search_string', 10) + search_string = request.args.get('search_string', "") site_name = session['selected_site'] offset = (page - 1) * limit recordset, count = database_recipes.getModalSKUs(site_name, (search_string, limit, offset)) - print(recordset) return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"}) return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":True, "message":"There was an error with this GET statement"}) - update_model = model_api.model('model', { 'id': fields.Integer(min=1), 'update': fields.Raw(required=True, description="all the data to be updated!") }) @recipes_api.route('/recipe/postUpdate', methods=["POST"]) +@login_required @model_api.expect(update_model) def postUpdate(): """ This is an endpoint for updating an RecipeTuple in the sites recipes table @@ -166,51 +169,62 @@ def postUpdate(): return jsonify({'recipe': recipe, 'error': True, 'message': 'Update of Recipe unsuccessful!'}) @recipes_api.route('/recipe/postCustomItem', methods=["POST"]) +@login_required def postCustomItem(): + """ post a recipe item to the database by passing a uuid, recipe_id, item_type, item_name, uom, qty, and link + --- + responses: + 200: + description: Recipe Item posted successfully! + """ recipe = {} if request.method == "POST": - database_config = config() site_name = session['selected_site'] - with psycopg2.connect(**database_config) as conn: - recipe_item = postsqldb.RecipesTable.ItemPayload( - uuid=f"%{int(request.get_json()['rp_id'])}{database.getUUID(6)}%", - rp_id=int(request.get_json()['rp_id']), - item_type=request.get_json()['item_type'], - item_name=request.get_json()['item_name'], - uom=request.get_json()['uom'], - qty=float(request.get_json()['qty']), - links=request.get_json()['links'] - ) - postsqldb.RecipesTable.insert_item_tuple(conn, site_name, recipe_item.payload(), convert=True) - recipe = postsqldb.RecipesTable.getRecipe(conn, site_name, (int(request.get_json()['rp_id']), ), convert=True) + rp_id = int(request.get_json()['rp_id']) + recipe_item = db.RecipesTable.ItemPayload( + uuid=f"%{int(request.get_json()['rp_id'])}{database.getUUID(6)}%", + rp_id=rp_id, + item_type=request.get_json()['item_type'], + item_name=request.get_json()['item_name'], + uom=request.get_json()['uom'], + qty=float(request.get_json()['qty']), + links=request.get_json()['links'] + ) + database_recipes.postRecipeItem(site_name, recipe_item.payload()) + recipe = database_recipes.getRecipe(site_name, (rp_id, )) return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'}) - return jsonify({'recipe': recipe, 'error': True, 'message': 'Recipe Item was not added unsuccessful!'}) + return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed!'}) @recipes_api.route('/recipe/postSKUItem', methods=["POST"]) +@login_required def postSKUItem(): + """ post a recipe item to the database by passing a recipe_id and item_id + --- + responses: + 200: + description: recipe item was posted successfully! + """ recipe = {} if request.method == "POST": recipe_id = int(request.get_json()['recipe_id']) item_id = int(request.get_json()['item_id']) - - database_config = config() site_name = session['selected_site'] - with psycopg2.connect(**database_config) as conn: - item = database.getItemAllByID(conn, site_name, (item_id, ), convert=True) - recipe_item = postsqldb.RecipesTable.ItemPayload( - uuid=item['barcode'], - rp_id=recipe_id, - item_type='sku', - item_name=item['item_name'], - uom=item['item_info']['uom']['id'], - qty=float(item['item_info']['uom_quantity']), - item_id=item['id'], - links=item['links'] - ) - postsqldb.RecipesTable.insert_item_tuple(conn, site_name, recipe_item.payload(), convert=True) - recipe = postsqldb.RecipesTable.getRecipe(conn, site_name, (recipe_id, ), convert=True) + item = database_recipes.getItemData(site_name, (item_id, )) + print(item) + recipe_item = db.RecipesTable.ItemPayload( + uuid=item['barcode'], + rp_id=recipe_id, + item_type='sku', + item_name=item['item_name'], + uom=item['uom'], + qty=float(item['uom_quantity']), + item_id=item['id'], + links=item['links'] + ) + database_recipes.postRecipeItem(site_name, recipe_item.payload()) + recipe = database_recipes.getRecipe(site_name, (recipe_id, )) return jsonify({'recipe': recipe, 'error': False, 'message': 'Recipe Item was added successful!'}) - return jsonify({'recipe': recipe, 'error': True, 'message': 'Recipe Item was not added unsuccessful!'}) + return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} is not allowed!'}) @recipes_api.route('/recipe/postImage/', methods=["POST"]) def uploadImage(recipe_id): diff --git a/scripts/recipes/sql/getItemData.sql b/scripts/recipes/sql/getItemData.sql new file mode 100644 index 0000000..ca66227 --- /dev/null +++ b/scripts/recipes/sql/getItemData.sql @@ -0,0 +1,4 @@ +SELECT item.id, item.barcode, item.item_name, item.links, item_info.uom_quantity, item_info.uom +FROM %%site_name%%_items item +LEFT JOIN %%site_name%%_item_info item_info ON item_info.id = item.item_info_id +WHERE item.id = %s; \ No newline at end of file diff --git a/scripts/recipes/sql/postRecipeItem.sql b/scripts/recipes/sql/postRecipeItem.sql new file mode 100644 index 0000000..1d9d919 --- /dev/null +++ b/scripts/recipes/sql/postRecipeItem.sql @@ -0,0 +1,4 @@ +INSERT INTO %%site_name%%_recipe_items +(uuid, rp_id, item_type, item_name, uom, qty, item_id, links) +VALUES (%s, %s, %s, %s, %s, %s, %s, %s) +RETURNING *; \ No newline at end of file