{ "cells": [ { "cell_type": "markdown", "id": "87780665-20d1-4934-9b92-4e785647e8f6", "metadata": {}, "source": [ "# sample data creation" ] }, { "cell_type": "code", "execution_count": 1, "id": "eaa15450-aaca-4e60-bd8a-22af17fa86db", "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-05-29 13:06:45,517 - botocore.credentials - INFO - Found credentials in shared credentials file: ~/.aws/credentials\n", "2025-05-29 13:06:45,604 - config.logger - INFO - S3Manager initialized for bucket: operation-menu-boy\n", "2025-05-29 13:06:45,826 - config.logger - INFO - Fetching file from S3: shibuyayakiniku-nikunohi/スプレッドシート/【v2】渋谷焼肉 ニクノヒ (7).xlsx\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "operation-menu-boy, shibuyayakiniku-nikunohi/スプレッドシート/【v2】渋谷焼肉 ニクノヒ (7).xlsx\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "2025-05-29 13:06:46,676 - config.logger - INFO - Successfully loaded file: shibuyayakiniku-nikunohi/スプレッドシート/【v2】渋谷焼肉 ニクノヒ (7).xlsx\n", "2025-05-29 13:06:46,681 - config.logger - INFO - 日本時間(ナノ秒単位) : 1748491606681487104\n" ] } ], "source": [ "import pandas as pd\n", "import importlib, services, domain, config\n", "from config.variables import *\n", "import sys\n", "from logging import INFO, DEBUG\n", "logger.setLevel(INFO)\n", "pd.set_option('display.max_columns', None)" ] }, { "cell_type": "code", "execution_count": 2, "id": "e2be864e-b766-4bec-aeb5-77a6b1768b18", "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "コースカテゴリ背景色: 4-pink\n" ] }, { "data": { "text/plain": [ "{'shop_id': 'shibuyayakiniku-nikunohi',\n", " 'different_time_menu_shop_id': '',\n", " 'shop_name_ja': '渋谷焼肉 ニクノヒ',\n", " 'shop_name_cn_s': '涩谷烤肉二之日',\n", " 'shop_name_cn_t': '澀谷烤肉二之日',\n", " 'shop_name_en': 'Shibuya Yakiniku Nikunohi',\n", " 'shop_name_kr': '시부야 야키니쿠 니쿠노히',\n", " 'shop_information_ja': '現金はご利用不可です。キャッシュレスのみとさせて頂いております。',\n", " 'shop_information_cn_s': '不接受现金。我们只接受非现金付款。',\n", " 'shop_information_cn_t': '不接受現金。我們只接受非現金付款。',\n", " 'shop_information_en': 'Cash is not accepted. Cashless payment only.',\n", " 'shop_information_kr': '현금은 이용 불가합니다.캐시리스만으로 하고 있습니다.',\n", " 'shop_course_category_background_color': Decimal('4'),\n", " 'shop_course_drink_category_id': Decimal('3'),\n", " 'shop_description_ja': 'クオリティの高い国産肉をリーズナブルに楽しめる、コースメインの焼肉店。\\n「黒毛和牛のユッケ」、「牛タン盛り合わせ」、リブロースやヒレといった脂を抑えた赤身の旨みを味わえるお肉を提供しております。\\nセルフ飲み放題の“大人のドリンクバー”はトルネード生ビール、ワインも豊富に用意しており、落ち着いた雰囲気の空間は、デートや会食、女子会などに様々なシーンでご利用いただけます!',\n", " 'shop_description_cn_s': '以套餐为主的烤肉店,可以以合理的价格享用高品质的国产肉。\\n我们提供“Yukke(炖黑毛和牛)”、“牛舌拼盘”、肋眼牛排和菲力牛排等可以让您享受脂肪较少的瘦红肉风味的肉类。\\n自助无限畅饮的“成人饮品吧”提供种类丰富的Tornado生啤和葡萄酒,轻松的氛围非常适合约会、商务聚餐、女生之夜等各种场合!',\n", " 'shop_description_cn_t': '以套餐為主的烤肉店,可以合理的價格享用高品質的國產肉。\\n我們提供「Yukke(燉黑毛和牛)」、「牛舌拼盤」、肋眼牛排和菲力牛排等可以讓您享受脂肪較少的瘦紅肉風味的肉類。\\n自助無限暢飲的「成人飲品吧」提供豐富的Tornado生啤酒和葡萄酒,輕鬆的氛圍非常適合約會、商務聚餐、女生之夜等各種場合!',\n", " 'shop_description_en': 'This yakiniku restaurant mainly serves course meals, where you can enjoy high-quality domestic meat at reasonable prices.\\nWe offer meats that allow you to savor the deliciousness of lean red meat with less fat, such as \"Japanese Black Beef Yukhoe,\" \"Beef Tongue Platter,\" rib eye, and fillet.\\nOur self-service all-you-can-drink \"adult drink bar\" offers Tornado draft beer and a wide selection of wine, and the relaxed atmosphere makes this a great place for a variety of occasions, such as dates, business dinners, and girls\\' nights!',\n", " 'shop_description_kr': '고품질의 국산 고기를 합리적으로 즐길 수 있는 코스 메인 야키니쿠점.\\n「흑모와규의 유케」, 「소탕 모듬」, 리브로스나 지느러미 등의 지방을 억제한 붉은 맛의 맛을 맛볼 수 있는 고기를 제공하고 있습니다.\\n셀프 음료 무제한의 “어른의 음료 바”는 토네이도 생 맥주, 와인도 풍부하게 준비하고 있어 차분한 분위기의 공간은, 데이트나 회식, 여자회 등에 다양한 장면에서 이용하실 수 있습니다!',\n", " 'shop_icon_type': Decimal('0'),\n", " 'shop_category_text_ja': '焼肉、ホルモン',\n", " 'shop_category_text_cn_s': '烤肉、内脏',\n", " 'shop_category_text_cn_t': '烤肉、內臟',\n", " 'shop_category_text_en': 'Yakiniku, Offal',\n", " 'shop_category_text_kr': '불고기, 호르몬',\n", " 'created_at': Decimal('1748491606681487104'),\n", " 'updated_at': Decimal('1748491606681487104'),\n", " 'lower_budget': Decimal('5000'),\n", " 'upper_budget': Decimal('6999'),\n", " 'open_hours_sun': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_mon': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_tue': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_wed': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_thu': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_fri': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'open_hours_sat': {'start_time_1': '17:00',\n", " 'end_time_1': '00:00',\n", " 'last_order_1': '',\n", " 'start_time_2': '',\n", " 'end_time_2': '',\n", " 'last_order_2': '',\n", " 'is_closed': False},\n", " 'business_hours_ja': '不定休',\n", " 'business_hours_cn_s': '不定期假期',\n", " 'business_hours_cn_t': '不定期假期',\n", " 'business_hours_en': 'Irregular holidays',\n", " 'business_hours_kr': '부정기',\n", " 'video_ids': [],\n", " 'image_ids': [],\n", " 'icon_name': '',\n", " 'text_name': '',\n", " 'recommended_menu': '',\n", " 'private_room_type': Decimal('0'),\n", " 'supported_creditcards': ['VISA',\n", " ' Mastercard',\n", " ' JCB',\n", " ' American Express',\n", " ' Dineres Club',\n", " ' 銀聯(UnionPay)'],\n", " 'supported_emoneys': ['\"Suica',\n", " 'Pasmo',\n", " 'etc...(交通系)\"',\n", " ' 楽天Edy(Rakuten Edy)',\n", " ' WAON',\n", " ' iD',\n", " ' QUIC Pay'],\n", " 'supported_qr_payments': ['PayPay',\n", " ' d払い(d Barai)',\n", " ' 楽天ペイ(Rakuten Pay)',\n", " ' au Pay',\n", " ' 支付宝(ALIPAY)',\n", " ' 微信支付(WeChat Pay)'],\n", " 'request_icons': {'water': False,\n", " 'plate': False,\n", " 'chopstick': False,\n", " 'fork': False,\n", " 'knife': False,\n", " 'spoon': False,\n", " 'restroom': False,\n", " 'check': False,\n", " 'owan': False,\n", " 'renge': False,\n", " 'epuron': False,\n", " 'otefuki': False},\n", " 'footer_disable_icons': {'request': False, 'cartOrderHistory': False},\n", " 'is_kids_available': False,\n", " 'kids_avaiability_description_ja': 'お子様の入店はご相談ください。',\n", " 'kids_avaiability_description_en': 'Please enquire if you would like to bring children into the store.',\n", " 'kids_avaiability_description_kr': '어린이의 입점은 상담해 주십시오.',\n", " 'kids_avaiability_description_cn_t': '如果您想帶孩子進店,請諮詢。',\n", " 'kids_avaiability_description_cn_s': '如果您想带孩子进店,请咨询。',\n", " 'cart_free_comment_flag': False,\n", " 'smoking_type': Decimal('1'),\n", " 'links': {'officialWebSite': 'https://henry-kitokito.com/info01/',\n", " 'instagram': 'https://www.instagram.com/shibuya.nikunohi/',\n", " 'facebook': '',\n", " 'affiliatedStore': '',\n", " 'x': '',\n", " 'tiktok': '',\n", " 'googlemap': 'https://www.google.com/search?sca_esv=393159a26b253a41&rlz=1C5CHFA_enJP1126JP1129&si=APYL9bs7Hg2KMLB-4tSoTdxuOx8BdRvHbByC_AuVpNyh0x2KzRDZG9n3a26eHqR_cH2geHMPtoFv4jgM-eRhOqIcqUgTK9FFBng5KeTsaLPplHhLFm35jjiOv4ggjx7it-mXGXiJLl6jzgv-bjK1SO3fSLZ-BqH2_w%3D%3D&q=%E6%B8%8B%E8%B0%B7%E7%84%BC%E8%82%89+%E3%83%8B%E3%82%AF%E3%83%8E%E3%83%92+%E3%82%AF%E3%83%81%E3%82%B3%E3%83%9F&sa=X&ved=2ahUKEwib14_qy82MAxVanq8BHWHROY8Q0bkNegQIKBAE&biw=1440&bih=778&dpr=2'},\n", " 'group_companies': ''}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from domain.shop import Shop\n", "\n", "shop_inst = Shop()\n", "shops_data = shop_inst.get_shop_data(excel)\n", "\n", "image_shop_dict = shop_inst.get_image_id_from_outside_qr(shops_data)\n", "video_shop_dict = shop_inst.get_video_id_from_outside_qr(shops_data)\n", "\n", "shops_data" ] }, { "cell_type": "code", "execution_count": 3, "id": "603b9364", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-05-29 13:06:46,915 - config.logger - INFO - read option df successfully.\n", "2025-05-29 13:06:47,148 - config.logger - INFO - read child option df successfully.\n", "2025-05-29 13:06:47,310 - config.logger - INFO - read 料理 df successfully.\n" ] } ], "source": [ "from domain.option import Option\n", "\n", "spreadsheet_format_version = \"v2\"\n", "# spreadsheet_format_version = sys.argv[3]\n", "option_inst = Option(spreadsheet_format_version)\n", "option_df = option_inst.get_option_df(excel)\n", "option_df = option_inst.fill_na_option_df(option_df)\n", "option_df = option_inst.merge_option_position(excel, option_df)\n", "\n", "child_option_df = None\n", "if \"オプション子オプション\" in excel.sheet_names:\n", " child_option_df = option_inst.get_child_option_df(excel)\n", " child_option_df = option_inst.fill_na_option_df(child_option_df, child_flag=True)\n", "\n", "option_data = option_inst.get_option_list(option_df, child_option_df)\n", "\n", "image_option_dict = option_inst.get_image_option_id_from_option_id(option_data)" ] }, { "cell_type": "code", "execution_count": 4, "id": "d9dc46c8-1894-4d11-b99a-de79110d3834", "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-05-29 13:06:47,480 - config.logger - INFO - read 料理 df successfully.\n", "2025-05-29 13:06:47,492 - config.logger - INFO - successfully got dish json list:\n" ] } ], "source": [ "from domain.dish import Dish\n", "\n", "dish_inst = Dish(spreadsheet_format_version)\n", "dish_df = dish_inst.get_df(excel)\n", "dish_df = dish_inst.fill_na_in_df(dish_df)\n", "dish_df = dish_inst.delete_non_publish_dish(dish_df)\n", "merged_df = dish_inst.merge_option(dish_df, option_df)\n", "sample_dishes_json_list = dish_inst.get_dishes_dict_list(dish_df, merged_df)\n", "\n", "dish_search_dict = dish_inst.get_dish_search_dict(sample_dishes_json_list)\n", "image_dish_dict = dish_inst.get_image_dish_id_from_dish_id(sample_dishes_json_list)\n", "video_dish_dict = dish_inst.get_video_dish_id_from_dish_id(sample_dishes_json_list)" ] }, { "cell_type": "code", "execution_count": 5, "id": "f1cece1d-83de-44b5-bf27-43df5ed14e12", "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/tomofumiogawa/Code/sho-x/translate_tool_internal/domain/category.py:25: FutureWarning: Setting an item of incompatible dtype is deprecated and will raise an error in a future version of pandas. Value '' has dtype incompatible with float64, please explicitly cast to a compatible dtype first.\n", " category_df.fillna('', inplace=True)\n", "2025-05-29 13:06:47,551 - config.logger - INFO - read category df successfully.\n", "2025-05-29 13:06:47,562 - config.logger - INFO - get category(menu) json list successfuly.\n" ] } ], "source": [ "from domain.category import Category\n", "\n", "category_inst = Category()\n", "category_df = category_inst.get_df(excel)\n", "category_df = category_inst.merge_dish_df(category_df, dish_df)\n", "sample_menu_json_list = category_inst.get_menu_json_list(category_df, dish_df, dish_search_dict)\n", "\n", "menu_search_dict = category_inst.get_menu_search_dict(sample_menu_json_list)" ] }, { "cell_type": "code", "execution_count": 10, "id": "9a4b9469", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2025-05-29 13:10:49,590 - config.logger - INFO - read 飲み放題 df successfully.\n", "2025-05-29 13:10:49,593 - config.logger - INFO - Starting DataFrame preprocessing.\n" ] } ], "source": [ "# 飲み放題シートの処理\n", "drink_menu_categories = []\n", "additional_option_data = []\n", "additional_drink_images = {}\n", "\n", "from domain.drink_plan import DrinkPlan\n", "\n", "drink_plan_inst = DrinkPlan(spreadsheet_format_version)\n", "drink_plan_df = drink_plan_inst.get_df(excel)\n", "\n", "if not drink_plan_df.empty:\n", " # 前処理\n", " drink_plan_df = drink_plan_inst.preprocess_df(drink_plan_df)\n", " drink_plan_df = drink_plan_inst.delete_non_publish_items(drink_plan_df)\n", "\n", " # 飲み放題プランのオプションデータを取得\n", " options_list, plan_option_map = drink_plan_inst.get_plan_options_dict_list(drink_plan_df)\n", "\n", " # 飲み放題プランのdishデータを取得\n", " plan_dishes_list = drink_plan_inst.get_plan_dishes_dict_list(drink_plan_df, plan_option_map, options_list)\n", "\n", " # ドリンク個別のdishデータを取得\n", " drink_dishes_list, drink_dish_map = drink_plan_inst.get_drink_dishes_dict_list(drink_plan_df, plan_dishes_list)\n", "\n", " if plan_dishes_list: # プランデータが存在する場合のみ処理\n", " # メインの「飲み放題」カテゴリを作成(各プランカテゴリへの参照を含む)\n", " main_category_dict = drink_plan_inst.get_main_category_dict(plan_dishes_list)\n", "\n", " # 各プランをカテゴリとして作成(プランとそのドリンクを含む)\n", " plan_categories_list, plan_category_ids = drink_plan_inst.get_plan_categories_dict_list(plan_dishes_list, drink_dish_map)\n", "\n", " # 料理リストに飲み放題プランとドリンクを追加\n", " sample_dishes_json_list.extend(plan_dishes_list)\n", " sample_dishes_json_list.extend(drink_dishes_list)\n", "\n", " # オプションリストにファーストドリンクオプションを追加\n", " option_data.extend(options_list)\n", "\n", " # メニューリストにカテゴリを追加(メインカテゴリとプランカテゴリ)\n", " sample_menu_json_list.extend(plan_categories_list)\n", " sample_menu_json_list.append(main_category_dict)\n", "\n", " # 「コース飲み放題」シートの読み込みとプランIDマッピング\n", " course_drink_df = pd.DataFrame()\n", " if \"コース飲み放題\" in excel.sheet_names:\n", " course_drink_df = excel.parse(sheet_name=\"コース飲み放題\", header=1)\n", " course_drink_df.columns = course_drink_df.columns.str.replace(\"(\", \"(\").str.replace(\")\", \")\")\n", " # コースIDがNaNの行は除外\n", " if 'コースID' in course_drink_df.columns:\n", " course_drink_df = course_drink_df.dropna(subset=['コースID'])\n", " plan_name_to_id = {}\n", " if not course_drink_df.empty:\n", " plan_name_to_id = {dish[\"dish_name_ja\"]: dish[\"dish_id\"] for dish in plan_dishes_list}" ] }, { "cell_type": "code", "execution_count": 11, "id": "0d65da3a", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| \n", " | # | \n", "コースID | \n", "コース名(参照用) | \n", "飲み放題プラン行番号 | \n", "飲み放題プラン名(参照用) | \n", "金額(税込) | \n", "
|---|---|---|---|---|---|---|
| 0 | \n", "1.0 | \n", "1.0 | \n", "ニクノヒ コース | \n", "1.0 | \n", "飲み放題 | \n", "NaN | \n", "
| 1 | \n", "2.0 | \n", "1.0 | \n", "ニクノヒ コース | \n", "83.0 | \n", "プレミアム飲み放題 | \n", "1000.0 | \n", "