Spaces:
Sleeping
Sleeping
File size: 7,557 Bytes
9e6917b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
from fastapi import FastAPI, File, UploadFile,HTTPException
from fastapi.responses import StreamingResponse
import pandas as pd
import numpy as np
import requests
import os
import io
import zipfile
from urllib.parse import urljoin
from typing import List
from pydantic import BaseModel
from io import BytesIO
# app = FastAPI()
# Input model
# Extract items with categories
def extract_items_with_categories(menu):
items_list = []
categories_seen = set() # Set to keep track of categories that have been added
for category in menu['categories']:
category_name = category['name']
category_position = category['position'] if category['position'] != -1 else 0
if category_name not in categories_seen:
items_list.append({
'category': category_name,
'position': category_position,
'Item': None, # Placeholder for item
'itemCode': None,
'item_position': None,
'img_url': None,
'Description': None,
'price_dine': None
})
categories_seen.add(category_name)
for item_code in category['items']:
item = next((item for item in menu['items'] if item['itemCode'] == item_code), None)
if item:
items_list.append({
'category': '', # Empty string for subsequent items in the same category
'position': category['position'],
'Item': item['name'],
'itemCode': item.get("itemCode",""),
'item_position': item['position'],
'img_url': "https://f.nooncdn.com/food_production/"+item['image'],
'Description': item['itemDesc'],
'price_dine': item['price']
})
return items_list
# Extract options
def extract_options(menu):
options_dict = {}
for item in menu['items']:
if 'modifiers' in item:
for modifier_code in item['modifiers']:
modifier = next((modifier for modifier in menu['modifiers'] if modifier['modifierCode'] == modifier_code), None)
if modifier:
if item['itemCode'] not in options_dict:
options_dict[item['itemCode']] = {}
if modifier['name'] not in options_dict[item['itemCode']]:
options_dict[item['itemCode']][modifier['name']] = {
'Min': modifier.get('minTotalOptions'),
'Max': modifier.get('maxTotalOptions'),
'Options': []
}
for option in modifier['options']:
option_item = next((i for i in menu['items'] if i['itemCode'] == option['itemCode']), None)
if option_item:
options_dict[item['itemCode']][modifier['name']]['Options'].append({
'Option name': option_item['name'],
'Option price': option['price']
})
return options_dict
# Process data for a single URL
def process_url(url, latitude, longitude):
outlet_code = url.split('/')[-2]
# Make the request
api_url = "https://food.noon.com/_svc/mp-food-api-mpnoon/consumer/restaurant/outlet/details/guest"
payload = {
"addressLat": latitude,
"addressLng": longitude,
"deliveryType": "default",
"outletCode": outlet_code
}
headers = {
'Connection': 'keep-alive',
"Accept": "application/json, text/plain, */*",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8,gu;q=0.7",
"Cache-Control": "no-cache, max-age=0, must-revalidate, no-store",
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
"Cookie": "bm_mi=791533C8E67CE8E7DA98E80ADED70F69~YAAQRK0cuOep9tGPAQAAUYKw3RcGDAVhD+mtWU8IH76wZL29zl4qqCjMwGv8sKtYlQWZNaFftSOvHFOvQU4+3CY2uHZyjjK6I3GeNdKEn+XHupISeNc0K16GOXLqcPOwu4sADTmxE7PYQvSQE7eimhqsBiJVRd96R8W0D2hl31FlY/4rl+NPZvM3iXjrn2GO50VMv+HhGfCnDMBwApBxgpMWFLfs0u6EYy44mg/FXbom5s5pa3cro8AS35nYHbdUbi61K9fnWRVaF8L/4z0xh7V1AEQETevb5fdGF8aB9m2UG29p2W6KSMb8DyFZLpG3vl5+IRECqZdFxaUMnykO8G/ynRHG~1; Domain=.noon.com; Path=/; Expires=Mon, 03 Jun 2024 12:41:22 GMT; Max-Age=7199; Secure"
}
response = requests.post(api_url, headers=headers, json=payload)
json_data = response.json()
# Extract items and options
items = extract_items_with_categories(json_data['data']['menu'])
options = extract_options(json_data['data']['menu'])
# Create a DataFrame for items
items_df = pd.DataFrame(items)
options_list = []
for item_code, option_groups in options.items():
for group_name, group_data in option_groups.items():
row = {
'itemCode': item_code,
'Option Group Name': group_name,
'Min': group_data.get('Min'),
'Max': group_data.get('Max')
}
for i, option in enumerate(group_data['Options']):
row[f'Option name {i+1}'] = option['Option name']
row[f'Option price {i+1}'] = option['Option price']
options_list.append(row)
# Create DataFrame for options
options_df = pd.DataFrame(options_list)
# Merge DataFrames on 'itemCode'
merged_df = items_df.merge(options_df, on='itemCode', how='left')
merged_df['category'] = merged_df['category'].replace('', np.nan).ffill()
merged_df['Item'] = merged_df['Item'].replace('', np.nan)
merged_df.iloc[:, :7] = merged_df.iloc[:, :7].mask(merged_df.iloc[:, :7].duplicated(), '')
merged_df = merged_df.dropna(how='all')
non_cat_pos_columns = merged_df.columns.difference(['category', 'position'])
mask = merged_df[non_cat_pos_columns].isna().all(axis=1) & merged_df[['category', 'position']].notna().all(axis=1)
merged_df = merged_df[~mask]
if 'Max' in merged_df.columns:
max_column_index = merged_df.columns.get_loc('Max')
for i in range(max_column_index + 1, len(merged_df.columns)):
merged_df.rename(columns={merged_df.columns[i]: ''}, inplace=True)
merged_df = merged_df.drop(columns=['itemCode'])
output = BytesIO()
with pd.ExcelWriter(output, engine='openpyxl') as writer:
merged_df.to_excel(writer, index=False, sheet_name='Menu')
output.seek(0)
return output,f"{outlet_code}_menu.xlsx"
# @app.post("/generate_and_download", response_class=StreamingResponse)
# def generate_and_download(details: RestaurantDetailsRequest):
# files = []
# for url in details.urls:
# output_filename = process_url(url, details.latitude, details.longitude)
# files.append(output_filename)
# zip_buffer = io.BytesIO()
# with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
# for file in files:
# zip_file.write(file, os.path.basename(file))
# zip_buffer.seek(0)
# return StreamingResponse(zip_buffer, media_type="application/x-zip-compressed", headers={"Content-Disposition": "attachment;filename=output_files.zip"})
# if __name__ == "__main__":
# import uvicorn
# uvicorn.run(app, host="127.0.0.1", port=8000)
|