diff --git "a/0\354\243\274\354\260\250\353\257\270\354\205\230/0\354\243\274\354\260\250\353\257\270\354\205\230_\352\263\240\352\262\275\354\210\230.png" "b/0\354\243\274\354\260\250\353\257\270\354\205\230/0\354\243\274\354\260\250\353\257\270\354\205\230_\352\263\240\352\262\275\354\210\230.png" new file mode 100644 index 0000000..6d4c828 Binary files /dev/null and "b/0\354\243\274\354\260\250\353\257\270\354\205\230/0\354\243\274\354\260\250\353\257\270\354\205\230_\352\263\240\352\262\275\354\210\230.png" differ diff --git "a/0\354\243\274\354\260\250\353\257\270\354\205\230/hello.vuerd.json" "b/0\354\243\274\354\260\250\353\257\270\354\205\230/hello.vuerd.json" new file mode 100644 index 0000000..4737311 --- /dev/null +++ "b/0\354\243\274\354\260\250\353\257\270\354\205\230/hello.vuerd.json" @@ -0,0 +1,2976 @@ +{ + "$schema": "https://raw.githubusercontent.com/dineug/erd-editor/main/json-schema/schema.json", + "version": "3.0.0", + "settings": { + "width": 2000, + "height": 2000, + "scrollTop": -750.1514, + "scrollLeft": -373.2146, + "zoomLevel": 0.71, + "show": 431, + "database": 4, + "databaseName": "", + "canvasType": "ERD", + "language": 1, + "tableNameCase": 4, + "columnNameCase": 2, + "bracketType": 1, + "relationshipDataTypeSync": true, + "relationshipOptimization": false, + "columnOrder": [ + 1, + 2, + 4, + 8, + 16, + 32, + 64 + ], + "maxWidthComment": -1, + "ignoreSaveSettings": 0 + }, + "doc": { + "tableIds": [ + "SW3qSYcmcjF6fxRxL9C6W", + "EnyjPta3Re1to-0Ow_c0k", + "3sN0z9wOs5gRHtxPeLnNL", + "cRAlxAB1DS5CVIqN0YxH_", + "FbuZsipRsYu9OgkLtQvRH", + "U-iS9P7j9_XRpt7sokj1u", + "WzdtVxFyk4teMt3xZ8E-8", + "1m_s3Ee0XEsle86A1W9bt", + "QF-n1pnH466PZnRVifDEq", + "66s2GuXAH4IsvhVcW9jiZ", + "uc2j1aS_eaeKNmWqHIhjm", + "DCLfTq9CxYAqBLL9O5uV-" + ], + "relationshipIds": [ + "x5KesGnxWH7BV5U7SRUKf", + "eQ0Udv6TLmj-vhXKBJS9z", + "QHb8FIR-OWcNh55-2nQS3", + "MD92WiyC8by1qAm4I_XSo", + "hlb49ERgeQ1Wz6x78DVes", + "GOioAAFNsn_A5uVd9veiB", + "1bzWUSllbdQW-XkNzsFDL", + "hMvmzUWSPDWpRGtzvjQ_H", + "MNEmKtrdfaxLY7ulw1tGy", + "dxZac9LiwDnVGUoVgGBK_", + "t4n5Tkjog7EkRQY3WzvHA", + "jkWOiJoVYIrCuKnZXEIEX" + ], + "indexIds": [], + "memoIds": [] + }, + "collections": { + "tableEntities": { + "SW3qSYcmcjF6fxRxL9C6W": { + "id": "SW3qSYcmcjF6fxRxL9C6W", + "name": "User", + "comment": "", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd", + "PbYSFy11QfczYemBl6sN8", + "IyuLsAKxYBgglcCueMciJ", + "j6FYMzLSV8ObnYo640OZW", + "aRwenG0xV5S3tVe_HxfGr", + "c8eBgjgL943BPvdbqGlNx", + "2F4WIGFoal0Pfq5aKWJGR", + "EMxDdIiEeIocCGxgzqdY2" + ], + "seqColumnIds": [ + "FdInoxrEYMeqkCxyYQlEd", + "PbYSFy11QfczYemBl6sN8", + "IyuLsAKxYBgglcCueMciJ", + "j6FYMzLSV8ObnYo640OZW", + "aRwenG0xV5S3tVe_HxfGr", + "c8eBgjgL943BPvdbqGlNx", + "2F4WIGFoal0Pfq5aKWJGR", + "EMxDdIiEeIocCGxgzqdY2", + "qwK66PRnyh6wZ7ebcTFIa", + "unGW2Vhu7oVMAbbyb_uU8", + "IPxLAdyOC8VYOSQBns0-W", + "o3xi1phrDUYwXoYMLJvNP", + "QbmabyqvWYXUzYuw76G_K", + "aVEC_JkxE3fKxtkaAGdo_", + "Yymdw8aFEqAAoh_FDoQnk" + ], + "ui": { + "x": 692.698, + "y": 898.2007, + "zIndex": 2, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758454295079, + "createAt": 1758265403229 + } + }, + "cRAlxAB1DS5CVIqN0YxH_": { + "id": "cRAlxAB1DS5CVIqN0YxH_", + "name": "Mission", + "comment": "", + "columnIds": [ + "NG68JYiPiJ-OOvG6HiKys", + "x6gCvhNKdcN5NiRG-o2V1", + "wF8OtNJBqHscI54r3JBWY", + "JGl101X01OJCUEt54mALi", + "VwpFfMO3n1vJKpvDTSr3C", + "iOfII2VWsbj9mzzIOT53n", + "Ot0SIC-v-b6RBocUOwIHc", + "NvKLpAdjRzQgpUoTUmIou" + ], + "seqColumnIds": [ + "NG68JYiPiJ-OOvG6HiKys", + "x6gCvhNKdcN5NiRG-o2V1", + "wF8OtNJBqHscI54r3JBWY", + "JGl101X01OJCUEt54mALi", + "VwpFfMO3n1vJKpvDTSr3C", + "iOfII2VWsbj9mzzIOT53n", + "P9cavuKJGE8NxA5pnr2w_", + "87sEqz5-srk0VbG4yiWb2", + "Ot0SIC-v-b6RBocUOwIHc", + "NvKLpAdjRzQgpUoTUmIou" + ], + "ui": { + "x": 1651.263, + "y": 575.2659, + "zIndex": 129, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758456876153, + "createAt": 1758267265581 + } + }, + "e6c3szi_ECXJt-WIBHtd_": { + "id": "e6c3szi_ECXJt-WIBHtd_", + "name": "User_mission", + "comment": "", + "columnIds": [ + "QJfGm1SMwEAxzNijipiM4", + "wyBJqunyME-zl1-De524y", + "Dt2MU1hvPB0ihSmrydMny" + ], + "seqColumnIds": [ + "o8VGEZ3v_LBPKvH8ZdawX", + "QJfGm1SMwEAxzNijipiM4", + "7CiWEnTk56G5_bVXZb7B1", + "O4m50Mtp1WSycEW6FyxTF", + "egLozO6_0r3FSIp9c5Wpn", + "k-eAvJsD6k9GBQMdmy37y", + "wyBJqunyME-zl1-De524y", + "Dt2MU1hvPB0ihSmrydMny", + "fyCBGRc-o-aQC-EQBLTv3" + ], + "ui": { + "x": 807.5343, + "y": 393.1509, + "zIndex": 220, + "widthName": 78, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758290558424, + "createAt": 1758267910532 + } + }, + "EnyjPta3Re1to-0Ow_c0k": { + "id": "EnyjPta3Re1to-0Ow_c0k", + "name": "User_mission", + "comment": "", + "columnIds": [ + "0vodZWX_87XT9VbutIozY", + "Inuqs8_WWLi2BSn2yGcR8", + "LYVABXr59kbCKrzUnqLHM", + "1S2A9Kj1q0Zg1NjLnMd4x" + ], + "seqColumnIds": [ + "BTWnyvg3l8OqAD1jo6ns0", + "StKAxk-_jDp-US4C117il", + "dQFMxc6o44lnTzRBkWRX1", + "0vodZWX_87XT9VbutIozY", + "Inuqs8_WWLi2BSn2yGcR8", + "LYVABXr59kbCKrzUnqLHM", + "0W8hNlGVp449tH6a85DH8", + "1S2A9Kj1q0Zg1NjLnMd4x" + ], + "ui": { + "x": 669.9466, + "y": 597.6242, + "zIndex": 332, + "widthName": 78, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758455572842, + "createAt": 1758292158564 + } + }, + "3sN0z9wOs5gRHtxPeLnNL": { + "id": "3sN0z9wOs5gRHtxPeLnNL", + "name": "Store", + "comment": "", + "columnIds": [ + "AfeYLVYuvV8Wl821feyp7", + "bbfng-98l1GftLFmZFiJz", + "hIRya3_Znn8A6lvR0oQKD", + "7loiKwFcsBh-V-HXDU4qt" + ], + "seqColumnIds": [ + "AfeYLVYuvV8Wl821feyp7", + "bbfng-98l1GftLFmZFiJz", + "hIRya3_Znn8A6lvR0oQKD", + "mMOcNIkrGjGfNRqn9YDzj", + "nRMf6gQpPmzyCevOtE4-8", + "7loiKwFcsBh-V-HXDU4qt" + ], + "ui": { + "x": 1652.6988, + "y": 969.3323, + "zIndex": 402, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371770324, + "createAt": 1758292692269 + } + }, + "FbuZsipRsYu9OgkLtQvRH": { + "id": "FbuZsipRsYu9OgkLtQvRH", + "name": "location", + "comment": "", + "columnIds": [ + "H4d48_Pb2KZNa64mBsDPG", + "HdJ2IUlX-_VuFBeKr-A5F" + ], + "seqColumnIds": [ + "H4d48_Pb2KZNa64mBsDPG", + "iN3tJldWUJdh77mvXWKi9", + "HdJ2IUlX-_VuFBeKr-A5F" + ], + "ui": { + "x": 1686.6967, + "y": 1343.0536, + "zIndex": 474, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371772349, + "createAt": 1758292911987 + } + }, + "U-iS9P7j9_XRpt7sokj1u": { + "id": "U-iS9P7j9_XRpt7sokj1u", + "name": "User_term", + "comment": "유저 약관", + "columnIds": [ + "xsiBCEQ2379F08SJM44Q2", + "oO6A3-YfUIYuwwbbHAwak" + ], + "seqColumnIds": [ + "xsiBCEQ2379F08SJM44Q2", + "DyOGo0HbdYNLl3F6fFJoV", + "uN4FKxyEb5gnf7VCsybG5", + "mxT0CemzkBll17N1CaQca", + "ouZqKosGANQxQuTaKY53B", + "oO6A3-YfUIYuwwbbHAwak" + ], + "ui": { + "x": 243.8593, + "y": 907.7111, + "zIndex": 534, + "widthName": 61, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371793459, + "createAt": 1758293071658 + } + }, + "WzdtVxFyk4teMt3xZ8E-8": { + "id": "WzdtVxFyk4teMt3xZ8E-8", + "name": "Term", + "comment": "약관", + "columnIds": [ + "aDfTa3M4EJInboYW1AwJY", + "CAHkq77oQC59cHUkF9lfd" + ], + "seqColumnIds": [ + "JOnYVd6w4ZQXXijAEVaCG", + "aDfTa3M4EJInboYW1AwJY", + "CAHkq77oQC59cHUkF9lfd", + "s02QSeo8dSiozImiCBNFi", + "qN1PeVGlmvL6ncOuxtWr5" + ], + "ui": { + "x": 264.2814, + "y": 1253.7228, + "zIndex": 573, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371797226, + "createAt": 1758293158363 + } + }, + "1m_s3Ee0XEsle86A1W9bt": { + "id": "1m_s3Ee0XEsle86A1W9bt", + "name": "Review", + "comment": "", + "columnIds": [ + "EInU_RFu6bLHrzU6Q0B7n", + "55SgG8fQHW7ou5JDkXvKA", + "0zdmPP4N-6oeuWmSY2VKl", + "k7258dBY3kP6fzWqjW50q", + "dIZqWQhwiiNrzz92BX0G8", + "miNr6v2QE9PGLzoUleK6j" + ], + "seqColumnIds": [ + "ubc2_bhpYhqglGT5scNC3", + "EInU_RFu6bLHrzU6Q0B7n", + "55SgG8fQHW7ou5JDkXvKA", + "0zdmPP4N-6oeuWmSY2VKl", + "k7258dBY3kP6fzWqjW50q", + "dIZqWQhwiiNrzz92BX0G8", + "miNr6v2QE9PGLzoUleK6j", + "ui_LT2XpbGmhIg5fAS2Pi", + "D8BdbHLmKJm3uyowygI7N" + ], + "ui": { + "x": 1190.2824, + "y": 991.2705, + "zIndex": 665, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758453111994, + "createAt": 1758293542228 + } + }, + "QF-n1pnH466PZnRVifDEq": { + "id": "QF-n1pnH466PZnRVifDEq", + "name": "User_food", + "comment": "", + "columnIds": [ + "ypBgbxrNHcFXsICZQcZ2H", + "e1w70_JR6SjRa9NgGo_A5", + "-EseBZUybBvjTNt06vdVn" + ], + "seqColumnIds": [ + "ypBgbxrNHcFXsICZQcZ2H", + "e1w70_JR6SjRa9NgGo_A5", + "dXSf5AH3ZE3-iEAjP4chh", + "-EseBZUybBvjTNt06vdVn" + ], + "ui": { + "x": 715.3327, + "y": 1248.6227, + "zIndex": 735, + "widthName": 61, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371798997, + "createAt": 1758370772406 + } + }, + "-XsTDrkVEFThAtw5o3ffB": { + "id": "-XsTDrkVEFThAtw5o3ffB", + "name": "Food", + "comment": "", + "columnIds": [ + "_7FVj3JXN-FWncfuCO9fc", + "6lcMP4yv3KRQvHJT-VnXw" + ], + "seqColumnIds": [ + "_7FVj3JXN-FWncfuCO9fc", + "6lcMP4yv3KRQvHJT-VnXw", + "6qUzoeD5b_nQwCop5-hwf" + ], + "ui": { + "x": 682.8064, + "y": 1524.454, + "zIndex": 765, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758370916296, + "createAt": 1758370851007 + } + }, + "66s2GuXAH4IsvhVcW9jiZ": { + "id": "66s2GuXAH4IsvhVcW9jiZ", + "name": "Food", + "comment": "", + "columnIds": [ + "pDRsYIOgYuYMV6I6tKbxF", + "fsqZCVY3nKxoVoEII8SK-" + ], + "seqColumnIds": [ + "pDRsYIOgYuYMV6I6tKbxF", + "tkg6jpNA4gsXXB_wFOmZI", + "fsqZCVY3nKxoVoEII8SK-" + ], + "ui": { + "x": 652.1287, + "y": 1461.6571, + "zIndex": 777, + "widthName": 60, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371805367, + "createAt": 1758370922625 + } + }, + "uc2j1aS_eaeKNmWqHIhjm": { + "id": "uc2j1aS_eaeKNmWqHIhjm", + "name": "Review_photo", + "comment": "", + "columnIds": [ + "1ULvVjxodU2ux6IItl1wu", + "yWEtyzLaYRh-GxP2rBAbN", + "UAN06zaHoneXEx6Zdkeim" + ], + "seqColumnIds": [ + "1ULvVjxodU2ux6IItl1wu", + "yWEtyzLaYRh-GxP2rBAbN", + "UAN06zaHoneXEx6Zdkeim" + ], + "ui": { + "x": 1167.0787, + "y": 1326.5081, + "zIndex": 821, + "widthName": 81, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758371521008, + "createAt": 1758371002822 + } + }, + "DCLfTq9CxYAqBLL9O5uV-": { + "id": "DCLfTq9CxYAqBLL9O5uV-", + "name": "Review_reply", + "comment": "", + "columnIds": [ + "rqOwtDSa3ID9yipZKxdHy", + "sgfvuuZDNafwtoRn92ETX", + "EvmR_T3qUbZVAAWd_4fc-" + ], + "seqColumnIds": [ + "rqOwtDSa3ID9yipZKxdHy", + "sgfvuuZDNafwtoRn92ETX", + "EvmR_T3qUbZVAAWd_4fc-" + ], + "ui": { + "x": 1195.2408, + "y": 801.8977, + "zIndex": 869, + "widthName": 76, + "widthComment": 60, + "color": "" + }, + "meta": { + "updateAt": 1758452986555, + "createAt": 1758371143408 + } + } + }, + "tableColumnEntities": { + "FdInoxrEYMeqkCxyYQlEd": { + "id": "FdInoxrEYMeqkCxyYQlEd", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 2, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267191583, + "createAt": 1758265422086 + } + }, + "PbYSFy11QfczYemBl6sN8": { + "id": "PbYSFy11QfczYemBl6sN8", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "email", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267190704, + "createAt": 1758265422908 + } + }, + "j6FYMzLSV8ObnYo640OZW": { + "id": "j6FYMzLSV8ObnYo640OZW", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "name", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267166778, + "createAt": 1758265423283 + } + }, + "IyuLsAKxYBgglcCueMciJ": { + "id": "IyuLsAKxYBgglcCueMciJ", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "password", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267156685, + "createAt": 1758265423480 + } + }, + "aRwenG0xV5S3tVe_HxfGr": { + "id": "aRwenG0xV5S3tVe_HxfGr", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "point", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267178236, + "createAt": 1758267092940 + } + }, + "2F4WIGFoal0Pfq5aKWJGR": { + "id": "2F4WIGFoal0Pfq5aKWJGR", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "creater_at", + "comment": "", + "dataType": "DATETIME", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 61, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267184778, + "createAt": 1758267093429 + } + }, + "EMxDdIiEeIocCGxgzqdY2": { + "id": "EMxDdIiEeIocCGxgzqdY2", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "updated_at", + "comment": "", + "dataType": "DATETIME", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 67, + "widthComment": 60, + "widthDataType": 61, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267186531, + "createAt": 1758267116062 + } + }, + "qwK66PRnyh6wZ7ebcTFIa": { + "id": "qwK66PRnyh6wZ7ebcTFIa", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267199296, + "createAt": 1758267199296 + } + }, + "NG68JYiPiJ-OOvG6HiKys": { + "id": "NG68JYiPiJ-OOvG6HiKys", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "mission_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292339893, + "createAt": 1758267269917 + } + }, + "x6gCvhNKdcN5NiRG-o2V1": { + "id": "x6gCvhNKdcN5NiRG-o2V1", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "title", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267717899, + "createAt": 1758267270691 + } + }, + "wF8OtNJBqHscI54r3JBWY": { + "id": "wF8OtNJBqHscI54r3JBWY", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "description", + "comment": "", + "dataType": "TEXT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 65, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267709501, + "createAt": 1758267270911 + } + }, + "JGl101X01OJCUEt54mALi": { + "id": "JGl101X01OJCUEt54mALi", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "point", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267705329, + "createAt": 1758267271091 + } + }, + "VwpFfMO3n1vJKpvDTSr3C": { + "id": "VwpFfMO3n1vJKpvDTSr3C", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "created_at", + "comment": "", + "dataType": "DATETIME", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 63, + "widthComment": 60, + "widthDataType": 61, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267697531, + "createAt": 1758267666779 + } + }, + "iOfII2VWsbj9mzzIOT53n": { + "id": "iOfII2VWsbj9mzzIOT53n", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "updated_at", + "comment": "", + "dataType": "DATETIME", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 67, + "widthComment": 60, + "widthDataType": 61, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290512081, + "createAt": 1758267667303 + } + }, + "unGW2Vhu7oVMAbbyb_uU8": { + "id": "unGW2Vhu7oVMAbbyb_uU8", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "mission_id", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267838696, + "createAt": 1758267838695 + } + }, + "P9cavuKJGE8NxA5pnr2w_": { + "id": "P9cavuKJGE8NxA5pnr2w_", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267887525, + "createAt": 1758267887525 + } + }, + "IPxLAdyOC8VYOSQBns0-W": { + "id": "IPxLAdyOC8VYOSQBns0-W", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "mission_id", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758267899656, + "createAt": 1758267899656 + } + }, + "QJfGm1SMwEAxzNijipiM4": { + "id": "QJfGm1SMwEAxzNijipiM4", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "is_complete", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 70, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290045198, + "createAt": 1758289793648 + } + }, + "7CiWEnTk56G5_bVXZb7B1": { + "id": "7CiWEnTk56G5_bVXZb7B1", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "description", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 65, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758289885652, + "createAt": 1758289793848 + } + }, + "O4m50Mtp1WSycEW6FyxTF": { + "id": "O4m50Mtp1WSycEW6FyxTF", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758289794072, + "createAt": 1758289794072 + } + }, + "egLozO6_0r3FSIp9c5Wpn": { + "id": "egLozO6_0r3FSIp9c5Wpn", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758289794285, + "createAt": 1758289794285 + } + }, + "k-eAvJsD6k9GBQMdmy37y": { + "id": "k-eAvJsD6k9GBQMdmy37y", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758289794472, + "createAt": 1758289794472 + } + }, + "wyBJqunyME-zl1-De524y": { + "id": "wyBJqunyME-zl1-De524y", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290518710, + "createAt": 1758290122020 + } + }, + "o3xi1phrDUYwXoYMLJvNP": { + "id": "o3xi1phrDUYwXoYMLJvNP", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290123213, + "createAt": 1758290123213 + } + }, + "87sEqz5-srk0VbG4yiWb2": { + "id": "87sEqz5-srk0VbG4yiWb2", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290495131, + "createAt": 1758290132755 + } + }, + "o8VGEZ3v_LBPKvH8ZdawX": { + "id": "o8VGEZ3v_LBPKvH8ZdawX", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "mission_id", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290506316, + "createAt": 1758290506316 + } + }, + "Dt2MU1hvPB0ihSmrydMny": { + "id": "Dt2MU1hvPB0ihSmrydMny", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "mission_id", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290515492, + "createAt": 1758290515492 + } + }, + "fyCBGRc-o-aQC-EQBLTv3": { + "id": "fyCBGRc-o-aQC-EQBLTv3", + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290535920, + "createAt": 1758290535919 + } + }, + "QbmabyqvWYXUzYuw76G_K": { + "id": "QbmabyqvWYXUzYuw76G_K", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290536668, + "createAt": 1758290536668 + } + }, + "aVEC_JkxE3fKxtkaAGdo_": { + "id": "aVEC_JkxE3fKxtkaAGdo_", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758290552767, + "createAt": 1758290552767 + } + }, + "LYVABXr59kbCKrzUnqLHM": { + "id": "LYVABXr59kbCKrzUnqLHM", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "is_complete", + "comment": "", + "dataType": "BOOLEAN", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 70, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292378420, + "createAt": 1758292176706 + } + }, + "BTWnyvg3l8OqAD1jo6ns0": { + "id": "BTWnyvg3l8OqAD1jo6ns0", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292177058, + "createAt": 1758292177058 + } + }, + "StKAxk-_jDp-US4C117il": { + "id": "StKAxk-_jDp-US4C117il", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292177231, + "createAt": 1758292177231 + } + }, + "dQFMxc6o44lnTzRBkWRX1": { + "id": "dQFMxc6o44lnTzRBkWRX1", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292191903, + "createAt": 1758292191903 + } + }, + "Yymdw8aFEqAAoh_FDoQnk": { + "id": "Yymdw8aFEqAAoh_FDoQnk", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292193405, + "createAt": 1758292193405 + } + }, + "0vodZWX_87XT9VbutIozY": { + "id": "0vodZWX_87XT9VbutIozY", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292288369, + "createAt": 1758292288369 + } + }, + "Inuqs8_WWLi2BSn2yGcR8": { + "id": "Inuqs8_WWLi2BSn2yGcR8", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "mission_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292339893, + "createAt": 1758292325129 + } + }, + "0W8hNlGVp449tH6a85DH8": { + "id": "0W8hNlGVp449tH6a85DH8", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292468361, + "createAt": 1758292468361 + } + }, + "bbfng-98l1GftLFmZFiJz": { + "id": "bbfng-98l1GftLFmZFiJz", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "store_name", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 69, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293038283, + "createAt": 1758292755585 + } + }, + "hIRya3_Znn8A6lvR0oQKD": { + "id": "hIRya3_Znn8A6lvR0oQKD", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "detail_address", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 85, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293045826, + "createAt": 1758292755934 + } + }, + "mMOcNIkrGjGfNRqn9YDzj": { + "id": "mMOcNIkrGjGfNRqn9YDzj", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "location_id", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 64, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292907905, + "createAt": 1758292756113 + } + }, + "nRMf6gQpPmzyCevOtE4-8": { + "id": "nRMf6gQpPmzyCevOtE4-8", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "mission_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 62, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292783115, + "createAt": 1758292783115 + } + }, + "AfeYLVYuvV8Wl821feyp7": { + "id": "AfeYLVYuvV8Wl821feyp7", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "store_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292870691, + "createAt": 1758292810918 + } + }, + "NvKLpAdjRzQgpUoTUmIou": { + "id": "NvKLpAdjRzQgpUoTUmIou", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "store_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292870691, + "createAt": 1758292812173 + } + }, + "iN3tJldWUJdh77mvXWKi9": { + "id": "iN3tJldWUJdh77mvXWKi9", + "tableId": "FbuZsipRsYu9OgkLtQvRH", + "name": "location_id", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 64, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758292942337, + "createAt": 1758292934368 + } + }, + "HdJ2IUlX-_VuFBeKr-A5F": { + "id": "HdJ2IUlX-_VuFBeKr-A5F", + "tableId": "FbuZsipRsYu9OgkLtQvRH", + "name": "location_name", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 85, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293052779, + "createAt": 1758292943766 + } + }, + "H4d48_Pb2KZNa64mBsDPG": { + "id": "H4d48_Pb2KZNa64mBsDPG", + "tableId": "FbuZsipRsYu9OgkLtQvRH", + "name": "location_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 2, + "ui": { + "keys": 1, + "widthName": 64, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293049076, + "createAt": 1758292964168 + } + }, + "7loiKwFcsBh-V-HXDU4qt": { + "id": "7loiKwFcsBh-V-HXDU4qt", + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "name": "location_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 2, + "widthName": 64, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293049076, + "createAt": 1758292964927 + } + }, + "DyOGo0HbdYNLl3F6fFJoV": { + "id": "DyOGo0HbdYNLl3F6fFJoV", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "term_id", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293141187, + "createAt": 1758293101287 + } + }, + "xsiBCEQ2379F08SJM44Q2": { + "id": "xsiBCEQ2379F08SJM44Q2", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293121419, + "createAt": 1758293121418 + } + }, + "JOnYVd6w4ZQXXijAEVaCG": { + "id": "JOnYVd6w4ZQXXijAEVaCG", + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "name": "Term_id", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293206382, + "createAt": 1758293202932 + } + }, + "CAHkq77oQC59cHUkF9lfd": { + "id": "CAHkq77oQC59cHUkF9lfd", + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "name": "term_name", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 66, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371540668, + "createAt": 1758293212321 + } + }, + "uN4FKxyEb5gnf7VCsybG5": { + "id": "uN4FKxyEb5gnf7VCsybG5", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293239893, + "createAt": 1758293239893 + } + }, + "s02QSeo8dSiozImiCBNFi": { + "id": "s02QSeo8dSiozImiCBNFi", + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293243929, + "createAt": 1758293243928 + } + }, + "mxT0CemzkBll17N1CaQca": { + "id": "mxT0CemzkBll17N1CaQca", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293302757, + "createAt": 1758293302757 + } + }, + "qN1PeVGlmvL6ncOuxtWr5": { + "id": "qN1PeVGlmvL6ncOuxtWr5", + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293304598, + "createAt": 1758293304598 + } + }, + "ouZqKosGANQxQuTaKY53B": { + "id": "ouZqKosGANQxQuTaKY53B", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293314990, + "createAt": 1758293314990 + } + }, + "aDfTa3M4EJInboYW1AwJY": { + "id": "aDfTa3M4EJInboYW1AwJY", + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "name": "term_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371537945, + "createAt": 1758293324974 + } + }, + "oO6A3-YfUIYuwwbbHAwak": { + "id": "oO6A3-YfUIYuwwbbHAwak", + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "name": "term_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371537945, + "createAt": 1758293326187 + } + }, + "ubc2_bhpYhqglGT5scNC3": { + "id": "ubc2_bhpYhqglGT5scNC3", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758293551653, + "createAt": 1758293551653 + } + }, + "k7258dBY3kP6fzWqjW50q": { + "id": "k7258dBY3kP6fzWqjW50q", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "content", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370733353, + "createAt": 1758293552010 + } + }, + "0zdmPP4N-6oeuWmSY2VKl": { + "id": "0zdmPP4N-6oeuWmSY2VKl", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "star", + "comment": "", + "dataType": "FLOAT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370726631, + "createAt": 1758293552173 + } + }, + "EInU_RFu6bLHrzU6Q0B7n": { + "id": "EInU_RFu6bLHrzU6Q0B7n", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370383612, + "createAt": 1758370383611 + } + }, + "55SgG8fQHW7ou5JDkXvKA": { + "id": "55SgG8fQHW7ou5JDkXvKA", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "store_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370393338, + "createAt": 1758370393337 + } + }, + "dIZqWQhwiiNrzz92BX0G8": { + "id": "dIZqWQhwiiNrzz92BX0G8", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "created_at", + "comment": "", + "dataType": "DATETIME", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 63, + "widthComment": 60, + "widthDataType": 61, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370747887, + "createAt": 1758370449226 + } + }, + "Ot0SIC-v-b6RBocUOwIHc": { + "id": "Ot0SIC-v-b6RBocUOwIHc", + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "name": "verification", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 65, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370692412, + "createAt": 1758370517201 + } + }, + "ypBgbxrNHcFXsICZQcZ2H": { + "id": "ypBgbxrNHcFXsICZQcZ2H", + "tableId": "QF-n1pnH466PZnRVifDEq", + "name": "user_food_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 76, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370848692, + "createAt": 1758370787809 + } + }, + "e1w70_JR6SjRa9NgGo_A5": { + "id": "e1w70_JR6SjRa9NgGo_A5", + "tableId": "QF-n1pnH466PZnRVifDEq", + "name": "user_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370801687, + "createAt": 1758370801686 + } + }, + "_7FVj3JXN-FWncfuCO9fc": { + "id": "_7FVj3JXN-FWncfuCO9fc", + "tableId": "-XsTDrkVEFThAtw5o3ffB", + "name": "food_id", + "comment": "", + "dataType": "", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370904863, + "createAt": 1758370862584 + } + }, + "6lcMP4yv3KRQvHJT-VnXw": { + "id": "6lcMP4yv3KRQvHJT-VnXw", + "tableId": "-XsTDrkVEFThAtw5o3ffB", + "name": "user_food_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 76, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370879876, + "createAt": 1758370879876 + } + }, + "6qUzoeD5b_nQwCop5-hwf": { + "id": "6qUzoeD5b_nQwCop5-hwf", + "tableId": "-XsTDrkVEFThAtw5o3ffB", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370901742, + "createAt": 1758370901742 + } + }, + "dXSf5AH3ZE3-iEAjP4chh": { + "id": "dXSf5AH3ZE3-iEAjP4chh", + "tableId": "QF-n1pnH466PZnRVifDEq", + "name": "food_id", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370930728, + "createAt": 1758370927670 + } + }, + "tkg6jpNA4gsXXB_wFOmZI": { + "id": "tkg6jpNA4gsXXB_wFOmZI", + "tableId": "66s2GuXAH4IsvhVcW9jiZ", + "name": "food_idc", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758370963412, + "createAt": 1758370937770 + } + }, + "pDRsYIOgYuYMV6I6tKbxF": { + "id": "pDRsYIOgYuYMV6I6tKbxF", + "tableId": "66s2GuXAH4IsvhVcW9jiZ", + "name": "food_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371526780, + "createAt": 1758370949384 + } + }, + "-EseBZUybBvjTNt06vdVn": { + "id": "-EseBZUybBvjTNt06vdVn", + "tableId": "QF-n1pnH466PZnRVifDEq", + "name": "food_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371526780, + "createAt": 1758370950298 + } + }, + "fsqZCVY3nKxoVoEII8SK-": { + "id": "fsqZCVY3nKxoVoEII8SK-", + "tableId": "66s2GuXAH4IsvhVcW9jiZ", + "name": "food_name", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 66, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371529490, + "createAt": 1758370971595 + } + }, + "1ULvVjxodU2ux6IItl1wu": { + "id": "1ULvVjxodU2ux6IItl1wu", + "tableId": "uc2j1aS_eaeKNmWqHIhjm", + "name": "review_photo_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 95, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371076136, + "createAt": 1758371013060 + } + }, + "yWEtyzLaYRh-GxP2rBAbN": { + "id": "yWEtyzLaYRh-GxP2rBAbN", + "tableId": "uc2j1aS_eaeKNmWqHIhjm", + "name": "review_photo_url", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 99, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371107362, + "createAt": 1758371013632 + } + }, + "miNr6v2QE9PGLzoUleK6j": { + "id": "miNr6v2QE9PGLzoUleK6j", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "review_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 10, + "ui": { + "keys": 1, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371048220, + "createAt": 1758371033308 + } + }, + "ui_LT2XpbGmhIg5fAS2Pi": { + "id": "ui_LT2XpbGmhIg5fAS2Pi", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "", + "comment": "", + "dataType": "", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371044596, + "createAt": 1758371044596 + } + }, + "UAN06zaHoneXEx6Zdkeim": { + "id": "UAN06zaHoneXEx6Zdkeim", + "tableId": "uc2j1aS_eaeKNmWqHIhjm", + "name": "review_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371059577, + "createAt": 1758371059577 + } + }, + "rqOwtDSa3ID9yipZKxdHy": { + "id": "rqOwtDSa3ID9yipZKxdHy", + "tableId": "DCLfTq9CxYAqBLL9O5uV-", + "name": "reply_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371211815, + "createAt": 1758371156738 + } + }, + "sgfvuuZDNafwtoRn92ETX": { + "id": "sgfvuuZDNafwtoRn92ETX", + "tableId": "DCLfTq9CxYAqBLL9O5uV-", + "name": "content", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371206948, + "createAt": 1758371157094 + } + }, + "D8BdbHLmKJm3uyowygI7N": { + "id": "D8BdbHLmKJm3uyowygI7N", + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "name": "review_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371167244, + "createAt": 1758371167244 + } + }, + "EvmR_T3qUbZVAAWd_4fc-": { + "id": "EvmR_T3qUbZVAAWd_4fc-", + "tableId": "DCLfTq9CxYAqBLL9O5uV-", + "name": "review_id", + "comment": "", + "dataType": "INT", + "default": "", + "options": 8, + "ui": { + "keys": 2, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758371174249, + "createAt": 1758371174248 + } + }, + "c8eBgjgL943BPvdbqGlNx": { + "id": "c8eBgjgL943BPvdbqGlNx", + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "name": "phone_num", + "comment": "", + "dataType": "VARCHAR", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 69, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758454322947, + "createAt": 1758454292626 + } + }, + "1S2A9Kj1q0Zg1NjLnMd4x": { + "id": "1S2A9Kj1q0Zg1NjLnMd4x", + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "name": "d_day", + "comment": "", + "dataType": "INT", + "default": "", + "options": 0, + "ui": { + "keys": 0, + "widthName": 60, + "widthComment": 60, + "widthDataType": 60, + "widthDefault": 60 + }, + "meta": { + "updateAt": 1758455579192, + "createAt": 1758455572842 + } + } + }, + "relationshipEntities": { + "EkbFWggaU1It65_7uNSjS": { + "id": "EkbFWggaU1It65_7uNSjS", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "NG68JYiPiJ-OOvG6HiKys" + ], + "x": 1117.1233, + "y": 543.8356, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "unGW2Vhu7oVMAbbyb_uU8" + ], + "x": 642.4006999999999, + "y": 547.4966, + "direction": 2 + }, + "meta": { + "updateAt": 1758267838696, + "createAt": 1758267838696 + } + }, + "5iUsaVpjTW4MU4K6NMQMr": { + "id": "5iUsaVpjTW4MU4K6NMQMr", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 642.4006999999999, + "y": 535.4966, + "direction": 2 + }, + "end": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "P9cavuKJGE8NxA5pnr2w_" + ], + "x": 1117.1233, + "y": 555.8356, + "direction": 1 + }, + "meta": { + "updateAt": 1758267887526, + "createAt": 1758267887526 + } + }, + "rGsXeC_iDXqZ4y1hQ9xhm": { + "id": "rGsXeC_iDXqZ4y1hQ9xhm", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "NG68JYiPiJ-OOvG6HiKys" + ], + "x": 1117.1233, + "y": 611.8356, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "IPxLAdyOC8VYOSQBns0-W" + ], + "x": 642.4006999999999, + "y": 609.4966, + "direction": 2 + }, + "meta": { + "updateAt": 1758267899657, + "createAt": 1758267899657 + } + }, + "_AWjE6cS9dAz6qVah7-UZ": { + "id": "_AWjE6cS9dAz6qVah7-UZ", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "columnIds": [ + "wyBJqunyME-zl1-De524y" + ], + "x": 807.5343, + "y": 457.1509, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "o3xi1phrDUYwXoYMLJvNP" + ], + "x": 588.9761, + "y": 444.7569, + "direction": 2 + }, + "meta": { + "updateAt": 1758290123214, + "createAt": 1758290123214 + } + }, + "Jq2X7Q5CzYRNyKOzHIcs6": { + "id": "Jq2X7Q5CzYRNyKOzHIcs6", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "columnIds": [ + "wyBJqunyME-zl1-De524y" + ], + "x": 1182.5343, + "y": 446.5208, + "direction": 2 + }, + "end": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "87sEqz5-srk0VbG4yiWb2" + ], + "x": 1391.0959, + "y": 447.6165, + "direction": 1 + }, + "meta": { + "updateAt": 1758290132756, + "createAt": 1758290132756 + } + }, + "vc8VPwZFTZBBnV499eEyE": { + "id": "vc8VPwZFTZBBnV499eEyE", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "columnIds": [ + "fyCBGRc-o-aQC-EQBLTv3" + ], + "x": 807.5343, + "y": 469.1509, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "QbmabyqvWYXUzYuw76G_K" + ], + "x": 588.9761, + "y": 444.7569, + "direction": 2 + }, + "meta": { + "updateAt": 1758290536668, + "createAt": 1758290536668 + } + }, + "oPSgwDtJYxercMoHAYg1p": { + "id": "oPSgwDtJYxercMoHAYg1p", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "e6c3szi_ECXJt-WIBHtd_", + "columnIds": [ + "fyCBGRc-o-aQC-EQBLTv3" + ], + "x": 807.5343, + "y": 469.1509, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "aVEC_JkxE3fKxtkaAGdo_" + ], + "x": 588.9761, + "y": 444.7569, + "direction": 2 + }, + "meta": { + "updateAt": 1758290552767, + "createAt": 1758290552767 + } + }, + "Vd8Xywn-nyqjLc37CrASA": { + "id": "Vd8Xywn-nyqjLc37CrASA", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "columnIds": [ + "dQFMxc6o44lnTzRBkWRX1" + ], + "x": 732.6244, + "y": 406.6435, + "direction": 1 + }, + "end": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "Yymdw8aFEqAAoh_FDoQnk" + ], + "x": 588.9761, + "y": 444.7569, + "direction": 2 + }, + "meta": { + "updateAt": 1758292193405, + "createAt": 1758292193405 + } + }, + "x5KesGnxWH7BV5U7SRUKf": { + "id": "x5KesGnxWH7BV5U7SRUKf", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 880.198, + "y": 898.2007, + "direction": 4 + }, + "end": { + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "columnIds": [ + "0vodZWX_87XT9VbutIozY" + ], + "x": 857.4466, + "y": 749.6242, + "direction": 8 + }, + "meta": { + "updateAt": 1758292288369, + "createAt": 1758292288369 + } + }, + "eQ0Udv6TLmj-vhXKBJS9z": { + "id": "eQ0Udv6TLmj-vhXKBJS9z", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "NG68JYiPiJ-OOvG6HiKys" + ], + "x": 1651.263, + "y": 699.2659, + "direction": 1 + }, + "end": { + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "columnIds": [ + "Inuqs8_WWLi2BSn2yGcR8" + ], + "x": 1044.9466, + "y": 673.6242, + "direction": 2 + }, + "meta": { + "updateAt": 1758292325130, + "createAt": 1758292325130 + } + }, + "c7zF524469Jx_P8stTYTY": { + "id": "c7zF524469Jx_P8stTYTY", + "identification": false, + "relationshipType": 8, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 588.9761, + "y": 488.7569, + "direction": 2 + }, + "end": { + "tableId": "EnyjPta3Re1to-0Ow_c0k", + "columnIds": [ + "0W8hNlGVp449tH6a85DH8" + ], + "x": 777.8297, + "y": 480.2598, + "direction": 1 + }, + "meta": { + "updateAt": 1758292468361, + "createAt": 1758292468361 + } + }, + "ppOMDQJnZUglApRYtpBNt": { + "id": "ppOMDQJnZUglApRYtpBNt", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "NG68JYiPiJ-OOvG6HiKys" + ], + "x": 1577.5959, + "y": 535.6165, + "direction": 8 + }, + "end": { + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "columnIds": [ + "nRMf6gQpPmzyCevOtE4-8" + ], + "x": 1575.0283, + "y": 632.0134, + "direction": 4 + }, + "meta": { + "updateAt": 1758292783115, + "createAt": 1758292783115 + } + }, + "QHb8FIR-OWcNh55-2nQS3": { + "id": "QHb8FIR-OWcNh55-2nQS3", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "columnIds": [ + "AfeYLVYuvV8Wl821feyp7" + ], + "x": 1847.6988, + "y": 969.3323, + "direction": 4 + }, + "end": { + "tableId": "cRAlxAB1DS5CVIqN0YxH_", + "columnIds": [ + "NvKLpAdjRzQgpUoTUmIou" + ], + "x": 1837.763, + "y": 823.2659, + "direction": 8 + }, + "meta": { + "updateAt": 1758292812174, + "createAt": 1758292812174 + } + }, + "MD92WiyC8by1qAm4I_XSo": { + "id": "MD92WiyC8by1qAm4I_XSo", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 1, + "start": { + "tableId": "FbuZsipRsYu9OgkLtQvRH", + "columnIds": [ + "H4d48_Pb2KZNa64mBsDPG" + ], + "x": 1881.6967, + "y": 1343.0536, + "direction": 4 + }, + "end": { + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "columnIds": [ + "7loiKwFcsBh-V-HXDU4qt" + ], + "x": 1847.6988, + "y": 1121.3323, + "direction": 8 + }, + "meta": { + "updateAt": 1758292964928, + "createAt": 1758292964928 + } + }, + "hlb49ERgeQ1Wz6x78DVes": { + "id": "hlb49ERgeQ1Wz6x78DVes", + "identification": false, + "relationshipType": 16, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 692.698, + "y": 1022.2007, + "direction": 1 + }, + "end": { + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "columnIds": [ + "xsiBCEQ2379F08SJM44Q2" + ], + "x": 608.8593, + "y": 959.7111, + "direction": 2 + }, + "meta": { + "updateAt": 1758293121419, + "createAt": 1758293121419 + } + }, + "WMXN_t4yhZ_plMFEz3Lii": { + "id": "WMXN_t4yhZ_plMFEz3Lii", + "identification": false, + "relationshipType": 16, + "startRelationshipType": 2, + "start": { + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "columnIds": [ + "uN4FKxyEb5gnf7VCsybG5" + ], + "x": 403.048, + "y": 805.2189, + "direction": 8 + }, + "end": { + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "columnIds": [ + "s02QSeo8dSiozImiCBNFi" + ], + "x": 404.3084, + "y": 953.9311, + "direction": 4 + }, + "meta": { + "updateAt": 1758293243929, + "createAt": 1758293243929 + } + }, + "s5NbCdJYvnyHaAWaSh2oy": { + "id": "s5NbCdJYvnyHaAWaSh2oy", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "columnIds": [ + "mxT0CemzkBll17N1CaQca" + ], + "x": 403.048, + "y": 805.2189, + "direction": 8 + }, + "end": { + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "columnIds": [ + "qN1PeVGlmvL6ncOuxtWr5" + ], + "x": 404.3084, + "y": 953.9311, + "direction": 4 + }, + "meta": { + "updateAt": 1758293304598, + "createAt": 1758293304598 + } + }, + "GOioAAFNsn_A5uVd9veiB": { + "id": "GOioAAFNsn_A5uVd9veiB", + "identification": false, + "relationshipType": 16, + "startRelationshipType": 2, + "start": { + "tableId": "WzdtVxFyk4teMt3xZ8E-8", + "columnIds": [ + "aDfTa3M4EJInboYW1AwJY" + ], + "x": 449.7814, + "y": 1253.7228, + "direction": 4 + }, + "end": { + "tableId": "U-iS9P7j9_XRpt7sokj1u", + "columnIds": [ + "oO6A3-YfUIYuwwbbHAwak" + ], + "x": 426.35929999999996, + "y": 1011.7111, + "direction": 8 + }, + "meta": { + "updateAt": 1758293326188, + "createAt": 1758293326188 + } + }, + "1bzWUSllbdQW-XkNzsFDL": { + "id": "1bzWUSllbdQW-XkNzsFDL", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 1067.6979999999999, + "y": 1022.2007, + "direction": 2 + }, + "end": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "EInU_RFu6bLHrzU6Q0B7n" + ], + "x": 1190.2824, + "y": 1091.2705, + "direction": 1 + }, + "meta": { + "updateAt": 1758370383612, + "createAt": 1758370383612 + } + }, + "hMvmzUWSPDWpRGtzvjQ_H": { + "id": "hMvmzUWSPDWpRGtzvjQ_H", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "3sN0z9wOs5gRHtxPeLnNL", + "columnIds": [ + "AfeYLVYuvV8Wl821feyp7" + ], + "x": 1652.6988, + "y": 1045.3323, + "direction": 1 + }, + "end": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "55SgG8fQHW7ou5JDkXvKA" + ], + "x": 1559.2824, + "y": 1091.2705, + "direction": 2 + }, + "meta": { + "updateAt": 1758370393338, + "createAt": 1758370393338 + } + }, + "MNEmKtrdfaxLY7ulw1tGy": { + "id": "MNEmKtrdfaxLY7ulw1tGy", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "SW3qSYcmcjF6fxRxL9C6W", + "columnIds": [ + "FdInoxrEYMeqkCxyYQlEd" + ], + "x": 880.198, + "y": 1146.2006999999999, + "direction": 8 + }, + "end": { + "tableId": "QF-n1pnH466PZnRVifDEq", + "columnIds": [ + "e1w70_JR6SjRa9NgGo_A5" + ], + "x": 905.8327, + "y": 1248.6227, + "direction": 4 + }, + "meta": { + "updateAt": 1758370801687, + "createAt": 1758370801687 + } + }, + "x5Z5XwztzLa-nZAhAScph": { + "id": "x5Z5XwztzLa-nZAhAScph", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "QF-n1pnH466PZnRVifDEq", + "columnIds": [ + "ypBgbxrNHcFXsICZQcZ2H" + ], + "x": 873.4383, + "y": 1407.5521, + "direction": 8 + }, + "end": { + "tableId": "-XsTDrkVEFThAtw5o3ffB", + "columnIds": [ + "6lcMP4yv3KRQvHJT-VnXw" + ], + "x": 873.3064, + "y": 1524.454, + "direction": 4 + }, + "meta": { + "updateAt": 1758370879876, + "createAt": 1758370879876 + } + }, + "dxZac9LiwDnVGUoVgGBK_": { + "id": "dxZac9LiwDnVGUoVgGBK_", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 1, + "start": { + "tableId": "66s2GuXAH4IsvhVcW9jiZ", + "columnIds": [ + "pDRsYIOgYuYMV6I6tKbxF" + ], + "x": 837.6287, + "y": 1461.6571, + "direction": 4 + }, + "end": { + "tableId": "QF-n1pnH466PZnRVifDEq", + "columnIds": [ + "-EseBZUybBvjTNt06vdVn" + ], + "x": 905.8327, + "y": 1376.6227, + "direction": 8 + }, + "meta": { + "updateAt": 1758370950298, + "createAt": 1758370950298 + } + }, + "t4n5Tkjog7EkRQY3WzvHA": { + "id": "t4n5Tkjog7EkRQY3WzvHA", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "miNr6v2QE9PGLzoUleK6j" + ], + "x": 1374.7824, + "y": 1191.2705, + "direction": 8 + }, + "end": { + "tableId": "uc2j1aS_eaeKNmWqHIhjm", + "columnIds": [ + "UAN06zaHoneXEx6Zdkeim" + ], + "x": 1369.0787, + "y": 1326.5081, + "direction": 4 + }, + "meta": { + "updateAt": 1758371059577, + "createAt": 1758371059577 + } + }, + "mymht63SidIE5C-WzUI5A": { + "id": "mymht63SidIE5C-WzUI5A", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "miNr6v2QE9PGLzoUleK6j" + ], + "x": 1539.2824, + "y": 991.2705, + "direction": 4 + }, + "end": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "D8BdbHLmKJm3uyowygI7N" + ], + "x": 1559.2824, + "y": 1047.2705, + "direction": 2 + }, + "meta": { + "updateAt": 1758371167244, + "createAt": 1758371167244 + } + }, + "jkWOiJoVYIrCuKnZXEIEX": { + "id": "jkWOiJoVYIrCuKnZXEIEX", + "identification": false, + "relationshipType": 4, + "startRelationshipType": 2, + "start": { + "tableId": "1m_s3Ee0XEsle86A1W9bt", + "columnIds": [ + "miNr6v2QE9PGLzoUleK6j" + ], + "x": 1374.7824, + "y": 991.2705, + "direction": 4 + }, + "end": { + "tableId": "DCLfTq9CxYAqBLL9O5uV-", + "columnIds": [ + "EvmR_T3qUbZVAAWd_4fc-" + ], + "x": 1377.7408, + "y": 929.8977, + "direction": 8 + }, + "meta": { + "updateAt": 1758371174249, + "createAt": 1758371174249 + } + } + }, + "indexEntities": {}, + "indexColumnEntities": {}, + "memoEntities": {} + } +} \ No newline at end of file diff --git "a/1\354\243\274\354\260\250\353\257\270\354\205\230/homepage.sql" "b/1\354\243\274\354\260\250\353\257\270\354\205\230/homepage.sql" new file mode 100644 index 0000000..c50ee4b --- /dev/null +++ "b/1\354\243\274\354\260\250\353\257\270\354\205\230/homepage.sql" @@ -0,0 +1,21 @@ +-- 4번 +SELECT + m.title, + m.description, + m.point, + um.is_complete, + um.d_day, + s.store_name, + l.location_name +FROM + User_mission um +JOIN + Mission m ON um.mission_id = m.mission_id +JOIN + Store s ON m.store_id = s.store_id +JOIN + Location l ON s.location_id = l.location_id +WHERE + um.user_id = 1 +ORDER BY + um.d_day ASC; -- 디데이 가까운 순서로 정렬 diff --git "a/1\354\243\274\354\260\250\353\257\270\354\205\230/mission_status.sql" "b/1\354\243\274\354\260\250\353\257\270\354\205\230/mission_status.sql" new file mode 100644 index 0000000..542d388 --- /dev/null +++ "b/1\354\243\274\354\260\250\353\257\270\354\205\230/mission_status.sql" @@ -0,0 +1,20 @@ +-- 3번 +SELECT + m.mission_id, + m.title, + m.description, + m.point, + um.status, + um.started_at, + um.completed_at +FROM + User_missions AS um +INNER JOIN + Missions AS m ON um.mission_id = m.mission_id -- 사용자가 이미 시작했거나 완료한 미션들 조회 +WHERE + um.user_id = 현재_사용자_ID + AND um.status IN ('in_progress', 'completed') -- 진행 중 또는 완료 상태 +ORDER BY + um.updated_at DESC -- 가장 최근에 갱신된 미션부터 정렬 +LIMIT + 10 OFFSET 0; \ No newline at end of file diff --git "a/1\354\243\274\354\260\250\353\257\270\354\205\230/mypage.sql" "b/1\354\243\274\354\260\250\353\257\270\354\205\230/mypage.sql" new file mode 100644 index 0000000..f7c09fd --- /dev/null +++ "b/1\354\243\274\354\260\250\353\257\270\354\205\230/mypage.sql" @@ -0,0 +1,8 @@ +-- 2번 +SELECT u.user_id, + u.email, + u.name, + u.point, + u.phone_num +FROM User AS u +WHERE u.user_id = '1'; \ No newline at end of file diff --git "a/1\354\243\274\354\260\250\353\257\270\354\205\230/review.sql" "b/1\354\243\274\354\260\250\353\257\270\354\205\230/review.sql" new file mode 100644 index 0000000..0a4530c --- /dev/null +++ "b/1\354\243\274\354\260\250\353\257\270\354\205\230/review.sql" @@ -0,0 +1,16 @@ +-- 1번 +-- 가게 리뷰와 유저 정보 조회 +SELECT r.review_id, + r.star, + r.content, + r.created_at, + u.user_id, + u.name, + u.email +FROM Review r +INNER JOIN User u ON r.user_id = u.user_id +WHERE r.store_id = 101; + +-- 리뷰 추가 +INSERT INTO Review (user_id, store_id, star, content, created_at) + VALUES (1, 101, 5, '음 너무 맛있어요', NOW()); \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" new file mode 100644 index 0000000..3b1da23 Binary files /dev/null and "b/4\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" differ diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/.DS_Store" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/.DS_Store" new file mode 100644 index 0000000..40bae72 Binary files /dev/null and "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/.DS_Store" differ diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/.DS_Store" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/.DS_Store" new file mode 100644 index 0000000..0f3439b Binary files /dev/null and "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/.DS_Store" differ diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/.DS_Store" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/.DS_Store" new file mode 100644 index 0000000..0f91354 Binary files /dev/null and "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/.DS_Store" differ diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/.DS_Store" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/.DS_Store" new file mode 100644 index 0000000..bb85c08 Binary files /dev/null and "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/.DS_Store" differ diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/Umc9thApplication.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/Umc9thApplication.java" new file mode 100644 index 0000000..0e3eec9 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/Umc9thApplication.java" @@ -0,0 +1,15 @@ +package com.example.umc9th; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + + +@SpringBootApplication +@EnableJpaAuditing +public class Umc9thApplication { + public static void main(String[] args) { + SpringApplication.run(Umc9thApplication.class, args); + + } +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/mission/entity/Mission.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/mission/entity/Mission.java" new file mode 100644 index 0000000..a67ba17 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/mission/entity/Mission.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.mission.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.mapping.UserMission; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "mission") +public class Mission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_id") + private Long id; + + @Column(nullable = false, length = 100) + private String title; + + @Column(columnDefinition = "TEXT") + private String description; + + @Column(nullable = false) + private Integer point; + + @Column(length = 50) + private String verification; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // UserMission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "mission", cascade = CascadeType.ALL) + @Builder.Default + private List userMissionList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/Review.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/Review.java" new file mode 100644 index 0000000..2dce1bf --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/Review.java" @@ -0,0 +1,54 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review") +public class Review extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_id") + private Long id; + + @Column(nullable = false) + private Float star; + + @Column(columnDefinition = "TEXT") + private String content; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 User는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 Store는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // ReviewPhoto와의 연관 관계 (1:N) + // Review 입장에서 ReviewPhoto는 1:N + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL) + @Builder.Default + private List reviewPhotoList = new ArrayList<>(); + + // ReviewReply와의 연관 관계 (1:N) + // Review 입장에서 ReviewReply는 1:N // 헷갈림 + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL) + @Builder.Default + private List reviewReplyList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" new file mode 100644 index 0000000..56310ba --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_photo") +public class ReviewPhoto extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_photo_id") + private Long id; + + @Column(name = "review_photo_url", nullable = false) + private String reviewPhotoUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; + +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewReply.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewReply.java" new file mode 100644 index 0000000..ccaa29e --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/review/entity/ReviewReply.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_reply") +public class ReviewReply extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "reply_id") + private Long id; + + @Column(columnDefinition = "TEXT") + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Location.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Location.java" new file mode 100644 index 0000000..73384e1 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Location.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "location") +public class Location extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "location_id") + private Long id; + + @Column(name = "location_name", nullable = false, length = 50) + private String name; + + // Store와의 연관 관계 (1:N) + @OneToMany(mappedBy = "location", cascade = CascadeType.ALL) + @Builder.Default + private List storeList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Store.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Store.java" new file mode 100644 index 0000000..99ad0b6 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/store/entity/Store.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.review.entity.Review; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "store") +public class Store extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "store_id") + private Long id; + + @Column(name = "store_name", nullable = false, length = 50) + private String name; + + @Column(name = "detailAddress", length = 100) + private String detailAddress; + + // Location과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "location_id") + private Location location; + + // Review와의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List reviewList = new ArrayList<>(); + + // Mission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List missionList = new ArrayList<>(); + +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Food.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Food.java" new file mode 100644 index 0000000..7dc8fc2 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Food.java" @@ -0,0 +1,25 @@ +package com.example.umc9th.domain.user.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Builder +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE) +@Getter +@Table(name = "food") + +public class Food { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "food_id") + private Long id; + + @Column(nullable = false, length = 50) + private String foodName; +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Term.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Term.java" new file mode 100644 index 0000000..03bf421 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/Term.java" @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.TermName; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Table(name = "term") +public class Term { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "term_id") // DB 컬럼명 명시 + private Long id; + + @Column(name = "term_name", nullable = false) // ENUM 컬럼만 남김 + @Enumerated(EnumType.STRING) + private TermName name; +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/User.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/User.java" new file mode 100644 index 0000000..9fbbf0a --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/User.java" @@ -0,0 +1,47 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.Gender; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user") +public class User extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") + private Long id; + + @Column(nullable = false, length = 50) + private String name; + + @Enumerated(EnumType.STRING) + @Builder.Default + @Column(nullable = false) + private Gender gender = Gender.NONE; + + @Column(nullable = false, length = 50, unique = true) + private String email; + + @Column(nullable = false) + private String password; + + @Column(length = 20) + private String phoneNum; + + @Builder.Default + @Column(nullable = false) + private Integer point = 0; + + @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE) + private List userFoodList = new ArrayList<>(); +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" new file mode 100644 index 0000000..fdb0822 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Food; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_food") +public class UserFood { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_food_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "food_id") + private Food food; +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" new file mode 100644 index 0000000..ba7da35 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" @@ -0,0 +1,38 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_mission") +public class UserMission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_mission_id") + private Long id; + + @Column(nullable = false) + private Boolean isComplete; + + @Column + private Integer dDay; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Mission과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id") + private Mission mission; + +} \ No newline at end of file diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" new file mode 100644 index 0000000..0e46a62 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Term; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; + +import lombok.*; +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_term") +public class UserTerm { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_term_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "term_id") + private Term term; +} + + diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/Gender.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/Gender.java" new file mode 100644 index 0000000..e07fca7 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/Gender.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum Gender { + MALE, FEMALE, NONE +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/TermName.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/TermName.java" new file mode 100644 index 0000000..1473bd4 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/domain/user/enums/TermName.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum TermName { + AGE, SERVICE, PRIVACY, LOCATION, MARKETING +} diff --git "a/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/global/entity/BaseEntity.java" "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/global/entity/BaseEntity.java" new file mode 100644 index 0000000..70f7459 --- /dev/null +++ "b/4\354\243\274\354\260\250\353\257\270\354\205\230/java/com/example/umc9th/global/entity/BaseEntity.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; +} + diff --git "a/5\354\243\274\354\260\250\353\257\270\354\205\230/mission.md" "b/5\354\243\274\354\260\250\353\257\270\354\205\230/mission.md" new file mode 100644 index 0000000..750fd92 --- /dev/null +++ "b/5\354\243\274\354\260\250\353\257\270\354\205\230/mission.md" @@ -0,0 +1,51 @@ +// 1번 +// JPA +public interface ReviewRepository extends JpaRepository { + List findReviewsByStoreId(Long storeId); +} + +// JPQL +public interface ReviewRepository extends JpaRepository { + @Query("SELECT r FROM Review r JOIN FETCH r.user WHERE r.store.id = :storeId") + List findReviewsByStoreId(@Param("storeId") Long storeId); +} + + +// 2번 +// JPA +public interface UserRepository extends JpaRepository { + Optional findById(Long userId); // Optinal은 NULL 방지 + + +// JPQL +@Query("SELECT u FROM User u WHERE u.id = :userId") +Optional findUserById(@Param("userId") Long userId); + + +// 3번 +public interface UserMissionRepository extends JpaRepository { + + @Query(""" + SELECT um FROM UserMission um + JOIN FETCH um.mission m + WHERE um.user.id = :userId + AND um.status IN ('in_progress', 'completed') + ORDER BY um.updatedAt DESC + """) + List findUserMissions(@Param("userId") Long userId, Pageable pageable); +} + +// 4번 +public interface UserMissionRepository extends JpaRepository { + + @Query(""" + SELECT um + FROM UserMission um + JOIN FETCH um.mission m + JOIN FETCH m.store s + JOIN FETCH s.location l + WHERE um.user.id = :userId + ORDER BY um.dDay ASC + """) + List findUserHome(@Param("userId") Long userId); +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" new file mode 100644 index 0000000..741587f Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" new file mode 100644 index 0000000..c9f0357 Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" new file mode 100644 index 0000000..c73db4f Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" new file mode 100644 index 0000000..e75394b Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" new file mode 100644 index 0000000..0f3439b Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" new file mode 100644 index 0000000..0f91354 Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" new file mode 100644 index 0000000..bb85c08 Binary files /dev/null and "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" differ diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" new file mode 100644 index 0000000..0e3eec9 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" @@ -0,0 +1,15 @@ +package com.example.umc9th; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + + +@SpringBootApplication +@EnableJpaAuditing +public class Umc9thApplication { + public static void main(String[] args) { + SpringApplication.run(Umc9thApplication.class, args); + + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" new file mode 100644 index 0000000..a67ba17 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.mission.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.mapping.UserMission; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "mission") +public class Mission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_id") + private Long id; + + @Column(nullable = false, length = 100) + private String title; + + @Column(columnDefinition = "TEXT") + private String description; + + @Column(nullable = false) + private Integer point; + + @Column(length = 50) + private String verification; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // UserMission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "mission", cascade = CascadeType.ALL) + @Builder.Default + private List userMissionList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" new file mode 100644 index 0000000..f8eba91 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.review.controller; + +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.service.ReviewService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/reviews") +public class ReviewController { + + private final ReviewService reviewService; + + @GetMapping("/user/{userId}") + public List getReviewsByUser( // 별점 필터링 + @PathVariable Long userId, + @RequestParam(required = false) Long storeId, + @RequestParam(required = false) Integer minStar, + @RequestParam(required = false) Integer maxStar + ) { + return reviewService.getReviewsByUserWithFilters(userId, storeId, minStar, maxStar); + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" new file mode 100644 index 0000000..87cb90c --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" @@ -0,0 +1,18 @@ +package com.example.umc9th.domain.review.dto; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class ReviewResponse { + private Long reviewId; + private String content; + private Float star; + + @QueryProjection + public ReviewResponse(Long reviewId, String content, Float star) { + this.reviewId = reviewId; + this.content = content; + this.star = star; + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" new file mode 100644 index 0000000..d8df6ee --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" @@ -0,0 +1,54 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review") +public class Review extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_id") + private Long id; + + @Column(nullable = false) + private Float star; + + @Column(columnDefinition = "TEXT") + private String content; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 User는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 Store는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // ReviewPhoto와의 연관 관계 (1:N) + // Review 입장에서 ReviewPhoto는 1:N + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @Builder.Default + private List reviewPhotoList = new ArrayList<>(); + + // ReviewReply와의 연관 관계 (1:N) + // Review 입장에서 ReviewReply는 1:N // 헷갈림 + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @Builder.Default + private List reviewReplyList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" new file mode 100644 index 0000000..56310ba --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_photo") +public class ReviewPhoto extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_photo_id") + private Long id; + + @Column(name = "review_photo_url", nullable = false) + private String reviewPhotoUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; + +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" new file mode 100644 index 0000000..ccaa29e --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_reply") +public class ReviewReply extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "reply_id") + private Long id; + + @Column(columnDefinition = "TEXT") + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" new file mode 100644 index 0000000..2781dcc --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" @@ -0,0 +1,7 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.entity.Review; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReviewRepository extends JpaRepository, ReviewRepositoryCustom { +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" new file mode 100644 index 0000000..227197c --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" @@ -0,0 +1,9 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.dto.ReviewResponse; + +import java.util.List; + +public interface ReviewRepositoryCustom { + List findReviewsByUserWithFilters(Long userId, Long storeId, Integer minStar, Integer maxStar); +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" new file mode 100644 index 0000000..e38d9fc --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" @@ -0,0 +1,38 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.dto.QReviewResponse; +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.entity.QReview; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class ReviewRepositoryImpl implements ReviewRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List findReviewsByUserWithFilters(Long userId, Long storeId, Integer minStar, Integer maxStar) { + QReview review = QReview.review; + + var query = queryFactory + .select(new QReviewResponse( + review.id, + review.content, + review.star + )) + .from(review) + .where(review.user.id.eq(userId)); + + if (storeId != null) query.where(review.store.id.eq(storeId)); + if (minStar != null && maxStar != null) query.where(review.star.between(minStar, maxStar)); + else if (minStar != null) query.where(review.star.goe(minStar)); + else if (maxStar != null) query.where(review.star.loe(maxStar)); + + return query.orderBy(review.id.desc()).fetch(); + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/ReviewService.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/ReviewService.java" new file mode 100644 index 0000000..f24cd1c --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/ReviewService.java" @@ -0,0 +1,20 @@ +package com.example.umc9th.domain.review.service; + +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.repository.ReviewRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ReviewService { + + private final ReviewRepository reviewRepository; + + public List getReviewsByUserWithFilters(Long userId, Long storeId, Integer minStar, Integer maxStar) { + // Repository에서 바로 DTO Projection + return reviewRepository.findReviewsByUserWithFilters(userId, storeId, minStar, maxStar); + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" new file mode 100644 index 0000000..73384e1 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "location") +public class Location extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "location_id") + private Long id; + + @Column(name = "location_name", nullable = false, length = 50) + private String name; + + // Store와의 연관 관계 (1:N) + @OneToMany(mappedBy = "location", cascade = CascadeType.ALL) + @Builder.Default + private List storeList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" new file mode 100644 index 0000000..99ad0b6 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.review.entity.Review; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "store") +public class Store extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "store_id") + private Long id; + + @Column(name = "store_name", nullable = false, length = 50) + private String name; + + @Column(name = "detailAddress", length = 100) + private String detailAddress; + + // Location과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "location_id") + private Location location; + + // Review와의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List reviewList = new ArrayList<>(); + + // Mission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List missionList = new ArrayList<>(); + +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" new file mode 100644 index 0000000..b5270f8 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" @@ -0,0 +1,29 @@ +package com.example.umc9th.domain.user.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Builder +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE) +@Getter +@Table(name = "food") + +public class Food { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "food_id") + private Long id; + + @Column(nullable = false, length = 50) + private String foodName; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" new file mode 100644 index 0000000..03bf421 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.TermName; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Table(name = "term") +public class Term { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "term_id") // DB 컬럼명 명시 + private Long id; + + @Column(name = "term_name", nullable = false) // ENUM 컬럼만 남김 + @Enumerated(EnumType.STRING) + private TermName name; +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" new file mode 100644 index 0000000..1564108 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" @@ -0,0 +1,48 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.Gender; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user") +public class User extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") + private Long id; + + @Column(nullable = false, length = 50) + private String name; + + @Enumerated(EnumType.STRING) + @Builder.Default + @Column(nullable = false) + private Gender gender = Gender.NONE; + + @Column(nullable = false, length = 50, unique = true) + private String email; + + @Column(nullable = false) + private String password; + + @Column(length = 20) + private String phoneNum; + + @Builder.Default + @Column(nullable = false) + private Integer point = 0; + + @Builder.Default + @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE) + private List userFoodList = new ArrayList<>(); +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" new file mode 100644 index 0000000..fdb0822 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Food; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_food") +public class UserFood { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_food_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "food_id") + private Food food; +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" new file mode 100644 index 0000000..ba7da35 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" @@ -0,0 +1,38 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_mission") +public class UserMission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_mission_id") + private Long id; + + @Column(nullable = false) + private Boolean isComplete; + + @Column + private Integer dDay; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Mission과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id") + private Mission mission; + +} \ No newline at end of file diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" new file mode 100644 index 0000000..0e46a62 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Term; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; + +import lombok.*; +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_term") +public class UserTerm { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_term_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "term_id") + private Term term; +} + + diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" new file mode 100644 index 0000000..e07fca7 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum Gender { + MALE, FEMALE, NONE +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" new file mode 100644 index 0000000..1473bd4 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum TermName { + AGE, SERVICE, PRIVACY, LOCATION, MARKETING +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" new file mode 100644 index 0000000..0ba8875 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" @@ -0,0 +1,15 @@ +package com.example.umc9th.global.config; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QuerydslConfig { + + @Bean + public JPAQueryFactory jpaQueryFactory(EntityManager em) { + return new JPAQueryFactory(em); + } +} diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" new file mode 100644 index 0000000..70f7459 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; +} + diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" new file mode 100644 index 0000000..ec8fa85 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" @@ -0,0 +1,18 @@ +spring: + application: + name: umc9th + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${DB_URL} + username: ${DB_USER} + password: ${DB_PW} + + jpa: + database: mysql + show-sql: true + hibernate: + ddl-auto: update + properties: + hibernate: + format_sql: true diff --git "a/6\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" new file mode 100644 index 0000000..a96d2a7 --- /dev/null +++ "b/6\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" @@ -0,0 +1,13 @@ +package com.example.umc9th; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Umc9thApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" new file mode 100644 index 0000000..f8b7a96 Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" new file mode 100644 index 0000000..bf1533f Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" new file mode 100644 index 0000000..c73db4f Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" new file mode 100644 index 0000000..e75394b Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" new file mode 100644 index 0000000..0f3439b Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" new file mode 100644 index 0000000..0f91354 Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" new file mode 100644 index 0000000..bb85c08 Binary files /dev/null and "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/.DS_Store" differ diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" new file mode 100644 index 0000000..0e3eec9 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/Umc9thApplication.java" @@ -0,0 +1,15 @@ +package com.example.umc9th; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + + +@SpringBootApplication +@EnableJpaAuditing +public class Umc9thApplication { + public static void main(String[] args) { + SpringApplication.run(Umc9thApplication.class, args); + + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" new file mode 100644 index 0000000..a67ba17 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/mission/entity/Mission.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.mission.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.mapping.UserMission; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "mission") +public class Mission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "mission_id") + private Long id; + + @Column(nullable = false, length = 100) + private String title; + + @Column(columnDefinition = "TEXT") + private String description; + + @Column(nullable = false) + private Integer point; + + @Column(length = 50) + private String verification; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // UserMission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "mission", cascade = CascadeType.ALL) + @Builder.Default + private List userMissionList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" new file mode 100644 index 0000000..d7ac886 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/controller/ReviewController.java" @@ -0,0 +1,51 @@ +package com.example.umc9th.domain.review.controller; + +import com.example.umc9th.domain.review.converter.ReviewConverter; +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.dto.res.ReviewResDTO; +import com.example.umc9th.domain.review.service.query.ReviewQueryService; +import com.example.umc9th.global.apiPayload.ApiResponse; +import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/reviews") +public class ReviewController { + + private final ReviewQueryService reviewQueryService; + + /** + * 내가 작성한 리뷰 조회 API (필터링 포함) + *

+ * 사용 예시: + * - 전체 조회: GET /reviews/user/1 + * - 가게별: GET /reviews/user/1?storeId=5 + * - 별점 범위: GET /reviews/user/1?minStar=3&maxStar=5 + * - 조합: GET /reviews/user/1?storeId=5&minStar=4&maxStar=5 + */ + @GetMapping("/user/{userId}") + public ApiResponse getMyReviews( + @PathVariable Long userId, + @RequestParam(required = false) Long storeId, + @RequestParam(required = false) Integer minStar, + @RequestParam(required = false) Integer maxStar + ) { + // Service 호출 + List reviews = reviewQueryService.getReviewsByUserWithFilters( + userId, storeId, minStar, maxStar + ); + + // 응답 코드 정의 + GeneralSuccessCode code = GeneralSuccessCode.OK; + + // Converter를 통해 DTO 변환 후 응답 + return ApiResponse.onSuccess( + code, + ReviewConverter.toReviewListDTO(reviews) + ); + } +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/converter/ReviewConverter.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/converter/ReviewConverter.java" new file mode 100644 index 0000000..8d45bb8 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/converter/ReviewConverter.java" @@ -0,0 +1,35 @@ +package com.example.umc9th.domain.review.converter; + +import com.example.umc9th.domain.review.dto.res.ReviewResDTO; +import com.example.umc9th.domain.review.dto.ReviewResponse; + +import java.util.List; +import java.util.stream.Collectors; + +public class ReviewConverter { + + /** + * QueryDSL 조회 결과 → 응답 DTO 변환 + */ + public static ReviewResDTO.ReviewListDTO toReviewListDTO(List reviews) { + List reviewDTOs = reviews.stream() + .map(ReviewConverter::toReviewDTO) + .collect(Collectors.toList()); + + return ReviewResDTO.ReviewListDTO.builder() + .reviews(reviewDTOs) + .totalCount(reviewDTOs.size()) + .build(); + } + + /** + * 개별 리뷰 변환 + */ + private static ReviewResDTO.ReviewDTO toReviewDTO(ReviewResponse review) { + return ReviewResDTO.ReviewDTO.builder() + .reviewId(review.getReviewId()) + .content(review.getContent()) + .star(review.getStar()) + .build(); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" new file mode 100644 index 0000000..f25bf7d --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/ReviewResponse.java" @@ -0,0 +1,19 @@ +package com.example.umc9th.domain.review.dto; + +import com.querydsl.core.annotations.QueryProjection; +import lombok.Getter; + +@Getter +public class ReviewResponse { + private Long reviewId; + private String content; + private Integer star; + + @QueryProjection + public ReviewResponse(Long reviewId, String content, Integer star) { + this.reviewId = reviewId; + this.content = content; + this.star = star; + } +} + diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/req/ReviewReqDTO.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/req/ReviewReqDTO.java" new file mode 100644 index 0000000..5914f94 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/req/ReviewReqDTO.java" @@ -0,0 +1,4 @@ +package com.example.umc9th.domain.review.dto.req; + +public class ReviewReqDTO { +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/res/ReviewResDTO.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/res/ReviewResDTO.java" new file mode 100644 index 0000000..7d5765d --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/dto/res/ReviewResDTO.java" @@ -0,0 +1,37 @@ +package com.example.umc9th.domain.review.dto.res; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +public class ReviewResDTO { + + /** + * 리뷰 목록 응답 DTO + * result 안에 들어갈 데이터 + */ + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ReviewListDTO { + private List reviews; + private Integer totalCount; + } + + /** + * 개별 리뷰 DTO + */ + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class ReviewDTO { + private Long reviewId; + private String content; + private Integer star; + } +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" new file mode 100644 index 0000000..9bc62ff --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/Review.java" @@ -0,0 +1,54 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.domain.store.entity.Store; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review") +public class Review extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_id") + private Long id; + + @Column(nullable = false) + private Integer star; + + @Column(columnDefinition = "TEXT") + private String content; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 User는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Store와의 연관 관계 (N:1) - 연관 관계의 주인 + // Review 입장에서 Store는 N:1 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id") + private Store store; + + // ReviewPhoto와의 연관 관계 (1:N) + // Review 입장에서 ReviewPhoto는 1:N + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @Builder.Default + private List reviewPhotoList = new ArrayList<>(); + + // ReviewReply와의 연관 관계 (1:N) + // Review 입장에서 ReviewReply는 1:N // 헷갈림 + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @Builder.Default + private List reviewReplyList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" new file mode 100644 index 0000000..56310ba --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewPhoto.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_photo") +public class ReviewPhoto extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "review_photo_id") + private Long id; + + @Column(name = "review_photo_url", nullable = false) + private String reviewPhotoUrl; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; + +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" new file mode 100644 index 0000000..ccaa29e --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/entity/ReviewReply.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.domain.review.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "review_reply") +public class ReviewReply extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "reply_id") + private Long id; + + @Column(columnDefinition = "TEXT") + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/ReviewException.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/ReviewException.java" new file mode 100644 index 0000000..2ae42f6 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/ReviewException.java" @@ -0,0 +1,11 @@ +package com.example.umc9th.domain.review.exception; + +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import com.example.umc9th.global.apiPayload.exception.GeneralException; + +public class ReviewException extends GeneralException { + + public ReviewException(BaseErrorCode code) { + super(code); + } +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/code/ReviewErrorCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/code/ReviewErrorCode.java" new file mode 100644 index 0000000..921f95a --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/exception/code/ReviewErrorCode.java" @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.review.exception.code; + +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum ReviewErrorCode implements BaseErrorCode { + + // Review 관련 에러 + INVALID_USER_ID(HttpStatus.BAD_REQUEST, "REVIEW400_1", "유효하지 않은 사용자 ID입니다."), + INVALID_STAR_RANGE(HttpStatus.BAD_REQUEST, "REVIEW400_2", "별점은 1~5 사이여야 하며, 최소값이 최대값보다 클 수 없습니다."), + + REVIEW_NOT_FOUND(HttpStatus.NOT_FOUND, "REVIEW404_1", "리뷰를 찾을 수 없습니다."), + REVIEW_ACCESS_DENIED(HttpStatus.FORBIDDEN, "REVIEW403_1", "해당 리뷰에 접근할 권한이 없습니다."), + ; + + private final HttpStatus status; + private final String code; + private final String message; +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" new file mode 100644 index 0000000..2781dcc --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepository.java" @@ -0,0 +1,7 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.entity.Review; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReviewRepository extends JpaRepository, ReviewRepositoryCustom { +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" new file mode 100644 index 0000000..9989c1c --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryCustom.java" @@ -0,0 +1,10 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.querydsl.core.types.Predicate; + +import java.util.List; + +public interface ReviewRepositoryCustom { + List searchReview(Predicate predicate); // predicate를 사용한 동적 쿼리 메서드 +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" new file mode 100644 index 0000000..ad1eef3 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/repository/ReviewRepositoryImpl.java" @@ -0,0 +1,41 @@ +package com.example.umc9th.domain.review.repository; + +import com.example.umc9th.domain.review.dto.QReviewResponse; +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.entity.QReview; +import com.example.umc9th.domain.store.entity.QStore; +import com.querydsl.core.types.Predicate; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +@Transactional(readOnly = true) // 조회 작업이므로 readOnly +public class ReviewRepositoryImpl implements ReviewRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + @Override + public List searchReview(Predicate predicate) { // predicate를 사용한 동적 쿼리 메서드 + // Q 클래스 선언 + QReview review = QReview.review; + QStore store = QStore.store; + + return queryFactory + .select(new QReviewResponse( + review.id, + review.content, + review.star + )) + .from(review) + .leftJoin(review.store, store) // Store 정보가 필요하면 join + .where(predicate) // 동적으로 전달받은 조건 적용 + .orderBy(review.id.desc()) // 최신 리뷰가 먼저 오도록 정렬 + .fetch(); + } + +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandService.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandService.java" new file mode 100644 index 0000000..c2b8277 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandService.java" @@ -0,0 +1,9 @@ +package com.example.umc9th.domain.review.service.command; + +public interface ReviewCommandService { + + // 나중에 리뷰 작성, 수정, 삭제 메서드 추가 + // ex) Long createReview(ReviewReqDTO dto); + // void updateReview(Long reviewId, ReviewReqDTO dto); + // void deleteReview(Long reviewId); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandServiceImpl.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandServiceImpl.java" new file mode 100644 index 0000000..b05640f --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/command/ReviewCommandServiceImpl.java" @@ -0,0 +1,16 @@ +package com.example.umc9th.domain.review.service.command; + +import com.example.umc9th.domain.review.repository.ReviewRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +@Transactional // 쓰기 작업이므로 readOnly 없음 +public class ReviewCommandServiceImpl implements ReviewCommandService { + + private final ReviewRepository reviewRepository; + + // 나중에 구현 +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryService.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryService.java" new file mode 100644 index 0000000..9a477a9 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryService.java" @@ -0,0 +1,18 @@ +package com.example.umc9th.domain.review.service.query; + +import com.example.umc9th.domain.review.dto.ReviewResponse; + +import java.util.List; + +public interface ReviewQueryService { + + /** + * 사용자의 리뷰 조회 (필터링 포함) + */ + List getReviewsByUserWithFilters( + Long userId, + Long storeId, + Integer minStar, + Integer maxStar + ); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryServiceImpl.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryServiceImpl.java" new file mode 100644 index 0000000..eefcec8 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/review/service/query/ReviewQueryServiceImpl.java" @@ -0,0 +1,87 @@ +package com.example.umc9th.domain.review.service.query; + +import com.example.umc9th.domain.review.dto.ReviewResponse; +import com.example.umc9th.domain.review.entity.QReview; +import com.example.umc9th.domain.review.exception.ReviewException; +import com.example.umc9th.domain.review.exception.code.ReviewErrorCode; +import com.example.umc9th.domain.review.repository.ReviewRepository; +import com.querydsl.core.BooleanBuilder; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) // 조회 작업이므로 readOnly +public class ReviewQueryServiceImpl implements ReviewQueryService { + + private final ReviewRepository reviewRepository; + + @Override + public List getReviewsByUserWithFilters( + Long userId, + Long storeId, + Integer minStar, + Integer maxStar + ) { + // 검증: 필수 파라미터 체크 + validateUserId(userId); + + // 검증: 별점 범위 체크 + validateStarRange(minStar, maxStar); + + // Q 클래스 선언 + QReview review = QReview.review; + + // BooleanBuilder로 동적 조건 생성 + BooleanBuilder builder = new BooleanBuilder(); + + // 필수 조건: 특정 사용자의 리뷰만 + builder.and(review.user.id.eq(userId)); + + // 선택 조건: 가게 필터링 + if (storeId != null) { + builder.and(review.store.id.eq(storeId)); + } + + // 선택 조건: 별점 필터링 + if (minStar != null && maxStar != null) { + builder.and(review.star.between(minStar.floatValue(), maxStar.floatValue())); + } else if (minStar != null) { + builder.and(review.star.goe(minStar.floatValue())); + } else if (maxStar != null) { + builder.and(review.star.loe(maxStar.floatValue())); + } + + // Repository 호출 & 결과 반환 + return reviewRepository.searchReview(builder); + } + + /** + * 사용자 ID 검증 + */ + private void validateUserId(Long userId) { + if (userId == null || userId <= 0) { + throw new ReviewException(ReviewErrorCode.INVALID_USER_ID); + } + } + + /** + * 별점 범위 검증 + */ + private void validateStarRange(Integer minStar, Integer maxStar) { + if (minStar != null && (minStar < 1 || minStar > 5)) { + throw new ReviewException(ReviewErrorCode.INVALID_STAR_RANGE); + } + + if (maxStar != null && (maxStar < 1 || maxStar > 5)) { + throw new ReviewException(ReviewErrorCode.INVALID_STAR_RANGE); + } + + if (minStar != null && maxStar != null && minStar > maxStar) { + throw new ReviewException(ReviewErrorCode.INVALID_STAR_RANGE); + } + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" new file mode 100644 index 0000000..73384e1 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Location.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "location") +public class Location extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "location_id") + private Long id; + + @Column(name = "location_name", nullable = false, length = 50) + private String name; + + // Store와의 연관 관계 (1:N) + @OneToMany(mappedBy = "location", cascade = CascadeType.ALL) + @Builder.Default + private List storeList = new ArrayList<>(); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" new file mode 100644 index 0000000..99ad0b6 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/store/entity/Store.java" @@ -0,0 +1,46 @@ +package com.example.umc9th.domain.store.entity; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.review.entity.Review; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "store") +public class Store extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "store_id") + private Long id; + + @Column(name = "store_name", nullable = false, length = 50) + private String name; + + @Column(name = "detailAddress", length = 100) + private String detailAddress; + + // Location과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "location_id") + private Location location; + + // Review와의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List reviewList = new ArrayList<>(); + + // Mission과의 연관 관계 (1:N) + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + @Builder.Default + private List missionList = new ArrayList<>(); + +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/controller/TestController.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/controller/TestController.java" new file mode 100644 index 0000000..851510f --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/controller/TestController.java" @@ -0,0 +1,44 @@ +package com.example.umc9th.domain.test.controller; + +import com.example.umc9th.domain.test.converter.TestConverter; +import com.example.umc9th.domain.test.dto.res.TestResDTO; +import com.example.umc9th.domain.test.service.query.TestQueryService; +import com.example.umc9th.global.apiPayload.ApiResponse; +import com.example.umc9th.global.apiPayload.code.GeneralSuccessCode; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/temp") +public class TestController { + + private final TestQueryService testQueryService; + + @GetMapping("/test") + public ApiResponse test() { + // 응답 코드 정의 + GeneralSuccessCode code = GeneralSuccessCode.OK; + + return ApiResponse.onSuccess( + code, + TestConverter.toTestingDTO("This is Test!") + ); + } + + // 예외 상황 + @GetMapping("/exception") + public ApiResponse exception( + @RequestParam Long flag + ) { + + testQueryService.checkFlag(flag); + + // 응답 코드 정의 + GeneralSuccessCode code = GeneralSuccessCode.OK; + return ApiResponse.onSuccess(code, TestConverter.toExceptionDTO("This is Test!")); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/converter/TestConverter.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/converter/TestConverter.java" new file mode 100644 index 0000000..af81183 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/converter/TestConverter.java" @@ -0,0 +1,24 @@ +package com.example.umc9th.domain.test.converter; + +import com.example.umc9th.domain.test.dto.res.TestResDTO; + +public class TestConverter { + + // 객체 -> DTO + public static TestResDTO.Testing toTestingDTO( + String testing + ) { + return TestResDTO.Testing.builder() + .testString(testing) + .build(); + } + + // 객체 -> DTO + public static TestResDTO.Exception toExceptionDTO( + String testing + ){ + return TestResDTO.Exception.builder() + .testString(testing) + .build(); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/req/TestReqDTO.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/req/TestReqDTO.java" new file mode 100644 index 0000000..405e3b9 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/req/TestReqDTO.java" @@ -0,0 +1,4 @@ +package com.example.umc9th.domain.test.dto.req; + +public class TestReqDTO { +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/res/TestResDTO.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/res/TestResDTO.java" new file mode 100644 index 0000000..9f13f52 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/dto/res/TestResDTO.java" @@ -0,0 +1,19 @@ +package com.example.umc9th.domain.test.dto.res; + +import lombok.Builder; +import lombok.Getter; + +public class TestResDTO { + + @Builder + @Getter + public static class Testing { + private String testString; + } + + @Builder + @Getter + public static class Exception { + private String testString; + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/TestException.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/TestException.java" new file mode 100644 index 0000000..c26ed05 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/TestException.java" @@ -0,0 +1,11 @@ +package com.example.umc9th.domain.test.exception; + +import com.example.umc9th.global.apiPayload.exception.GeneralException; +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; + +public class TestException extends GeneralException { + + public TestException(BaseErrorCode code) { + super(code); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/code/TestErrorCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/code/TestErrorCode.java" new file mode 100644 index 0000000..7264f21 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/exception/code/TestErrorCode.java" @@ -0,0 +1,19 @@ +package com.example.umc9th.domain.test.exception.code; + +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum TestErrorCode implements BaseErrorCode { + + // For test + TEST_EXCEPTION(HttpStatus.BAD_REQUEST, "TEST400_1", "이거는 테스트"), + ; + + private final HttpStatus status; + private final String code; + private final String message; +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryService.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryService.java" new file mode 100644 index 0000000..a6419ab --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryService.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.test.service.query; + +public interface TestQueryService { + void checkFlag(Long flag); +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryServiceImpl.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryServiceImpl.java" new file mode 100644 index 0000000..1af8423 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/test/service/query/TestQueryServiceImpl.java" @@ -0,0 +1,18 @@ +package com.example.umc9th.domain.test.service.query; + +import com.example.umc9th.domain.test.exception.TestException; +import com.example.umc9th.domain.test.exception.code.TestErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TestQueryServiceImpl implements TestQueryService { + + @Override + public void checkFlag(Long flag) { + if (flag == 1) { + throw new TestException(TestErrorCode.TEST_EXCEPTION); + } + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" new file mode 100644 index 0000000..b5270f8 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Food.java" @@ -0,0 +1,29 @@ +package com.example.umc9th.domain.user.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Builder +@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) +@AllArgsConstructor(access = lombok.AccessLevel.PRIVATE) +@Getter +@Table(name = "food") + +public class Food { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "food_id") + private Long id; + + @Column(nullable = false, length = 50) + private String foodName; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" new file mode 100644 index 0000000..03bf421 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/Term.java" @@ -0,0 +1,23 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.TermName; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Table(name = "term") +public class Term { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "term_id") // DB 컬럼명 명시 + private Long id; + + @Column(name = "term_name", nullable = false) // ENUM 컬럼만 남김 + @Enumerated(EnumType.STRING) + private TermName name; +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" new file mode 100644 index 0000000..1564108 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/User.java" @@ -0,0 +1,48 @@ +package com.example.umc9th.domain.user.entity; + +import com.example.umc9th.domain.user.enums.Gender; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user") +public class User extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") + private Long id; + + @Column(nullable = false, length = 50) + private String name; + + @Enumerated(EnumType.STRING) + @Builder.Default + @Column(nullable = false) + private Gender gender = Gender.NONE; + + @Column(nullable = false, length = 50, unique = true) + private String email; + + @Column(nullable = false) + private String password; + + @Column(length = 20) + private String phoneNum; + + @Builder.Default + @Column(nullable = false) + private Integer point = 0; + + @Builder.Default + @OneToMany(mappedBy = "user", cascade = CascadeType.REMOVE) + private List userFoodList = new ArrayList<>(); +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" new file mode 100644 index 0000000..fdb0822 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserFood.java" @@ -0,0 +1,27 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Food; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_food") +public class UserFood { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_food_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "food_id") + private Food food; +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" new file mode 100644 index 0000000..ba7da35 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserMission.java" @@ -0,0 +1,38 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.mission.entity.Mission; +import com.example.umc9th.domain.user.entity.User; +import com.example.umc9th.global.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_mission") +public class UserMission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_mission_id") + private Long id; + + @Column(nullable = false) + private Boolean isComplete; + + @Column + private Integer dDay; + + // User와의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + // Mission과의 연관 관계 (N:1) - 연관 관계의 주인 + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id") + private Mission mission; + +} \ No newline at end of file diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" new file mode 100644 index 0000000..0e46a62 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/entity/mapping/UserTerm.java" @@ -0,0 +1,30 @@ +package com.example.umc9th.domain.user.entity.mapping; + +import com.example.umc9th.domain.user.entity.Term; +import com.example.umc9th.domain.user.entity.User; +import jakarta.persistence.*; + +import lombok.*; +@Entity +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +@Table(name = "user_term") +public class UserTerm { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_term_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "term_id") + private Term term; +} + + diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" new file mode 100644 index 0000000..e07fca7 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/Gender.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum Gender { + MALE, FEMALE, NONE +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" new file mode 100644 index 0000000..1473bd4 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/domain/user/enums/TermName.java" @@ -0,0 +1,5 @@ +package com.example.umc9th.domain.user.enums; + +public enum TermName { + AGE, SERVICE, PRIVACY, LOCATION, MARKETING +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/ApiResponse.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/ApiResponse.java" new file mode 100644 index 0000000..e15b755 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/ApiResponse.java" @@ -0,0 +1,37 @@ +package com.example.umc9th.global.apiPayload; + +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import com.example.umc9th.global.apiPayload.code.BaseSuccessCode; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess", "code", "message", "result"}) +public class ApiResponse { + + @JsonProperty("isSuccess") + private final Boolean isSuccess; + + @JsonProperty("code") + private final String code; + + @JsonProperty("message") + private final String message; + + @JsonProperty("result") + private T result; + + + // ✅ 성공한 경우 (성공 코드 인터페이스 사용) + public static ApiResponse onSuccess(BaseSuccessCode code, T result) { + return new ApiResponse<>(true, code.getCode(), code.getMessage(), result); + } + + // 실패한 경우 (result 포함) + public static ApiResponse onFailure(BaseErrorCode code, T result) { + return new ApiResponse<>(false, code.getCode(), code.getMessage(), result); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseErrorCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseErrorCode.java" new file mode 100644 index 0000000..d0d553f --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseErrorCode.java" @@ -0,0 +1,10 @@ +package com.example.umc9th.global.apiPayload.code; + +import org.springframework.http.HttpStatus; + +public interface BaseErrorCode { + + HttpStatus getStatus(); + String getCode(); + String getMessage(); +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseSuccessCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseSuccessCode.java" new file mode 100644 index 0000000..19d1b22 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/BaseSuccessCode.java" @@ -0,0 +1,9 @@ +package com.example.umc9th.global.apiPayload.code; + +import org.springframework.http.HttpStatus; + +public interface BaseSuccessCode { + HttpStatus getStatus(); + String getCode(); + String getMessage(); +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralErrorCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralErrorCode.java" new file mode 100644 index 0000000..d41e910 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralErrorCode.java" @@ -0,0 +1,31 @@ +package com.example.umc9th.global.apiPayload.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum GeneralErrorCode implements BaseErrorCode{ + + BAD_REQUEST(HttpStatus.BAD_REQUEST, + "COMMON400_1", + "잘못된 요청입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, + "AUTH401_1", + "인증이 필요합니다."), + FORBIDDEN(HttpStatus.FORBIDDEN, + "AUTH403_1", + "요청이 거부되었습니다."), + NOT_FOUND(HttpStatus.NOT_FOUND, + "COMMON404_1", + "요청한 리소스를 찾을 수 없습니다."), + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, + "COMMON500_1", + "예기치 않은 서버 에러가 발생했습니다."), + ; + + private final HttpStatus status; + private final String code; + private final String message; +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralSuccessCode.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralSuccessCode.java" new file mode 100644 index 0000000..ef060c8 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/code/GeneralSuccessCode.java" @@ -0,0 +1,24 @@ +package com.example.umc9th.global.apiPayload.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum GeneralSuccessCode implements BaseSuccessCode { + + OK(HttpStatus.OK, + "COMMON200", + "요청이 성공적으로 처리되었습니다."), + CREATED(HttpStatus.CREATED, + "COMMON201", + "리소스가 성공적으로 생성되었습니다."), + NO_CONTENT(HttpStatus.NO_CONTENT, + "COMMON204", + "요청이 성공적으로 처리되었으며, 반환할 내용이 없습니다."), + ; + private final HttpStatus status; + private final String code; + private final String message; +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/exception/GeneralException.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/exception/GeneralException.java" new file mode 100644 index 0000000..902d4b5 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/exception/GeneralException.java" @@ -0,0 +1,14 @@ +package com.example.umc9th.global.apiPayload.exception; + +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import lombok.Getter; + +@Getter +public class GeneralException extends RuntimeException { + private final BaseErrorCode code; + + public GeneralException(BaseErrorCode code) { + super(code.getMessage()); + this.code = code; + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java" new file mode 100644 index 0000000..195e36c --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/apiPayload/handler/GeneralExceptionAdvice.java" @@ -0,0 +1,42 @@ +package com.example.umc9th.global.apiPayload.handler; + +import com.example.umc9th.global.apiPayload.ApiResponse; +import com.example.umc9th.global.apiPayload.code.BaseErrorCode; +import com.example.umc9th.global.apiPayload.code.GeneralErrorCode; +import com.example.umc9th.global.apiPayload.exception.GeneralException; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GeneralExceptionAdvice { + + // 애플리케이션에서 발생하는 커스텀 예외를 처리 + @ExceptionHandler(GeneralException.class) + public ResponseEntity> handleException( + GeneralException ex + ) { + + return ResponseEntity.status(ex.getCode().getStatus()) + .body(ApiResponse.onFailure( + ex.getCode(), + null + ) + ); + } + + // 그 외의 정의되지 않은 모든 예외 처리 + @ExceptionHandler(Exception.class) + public ResponseEntity> handleException( + Exception ex + ) { + + BaseErrorCode code = GeneralErrorCode.INTERNAL_SERVER_ERROR; + return ResponseEntity.status(code.getStatus()) + .body(ApiResponse.onFailure( + code, + ex.getMessage() + ) + ); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" new file mode 100644 index 0000000..0ba8875 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/config/QuerydslConfig.java" @@ -0,0 +1,15 @@ +package com.example.umc9th.global.config; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QuerydslConfig { + + @Bean + public JPAQueryFactory jpaQueryFactory(EntityManager em) { + return new JPAQueryFactory(em); + } +} diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" new file mode 100644 index 0000000..70f7459 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/java/com/example/umc9th/global/entity/BaseEntity.java" @@ -0,0 +1,26 @@ +package com.example.umc9th.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; +} + diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" new file mode 100644 index 0000000..ec8fa85 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/main/resources/application.yml" @@ -0,0 +1,18 @@ +spring: + application: + name: umc9th + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: ${DB_URL} + username: ${DB_USER} + password: ${DB_PW} + + jpa: + database: mysql + show-sql: true + hibernate: + ddl-auto: update + properties: + hibernate: + format_sql: true diff --git "a/7\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" new file mode 100644 index 0000000..a96d2a7 --- /dev/null +++ "b/7\354\243\274\354\260\250\353\257\270\354\205\230/src/test/java/com/example/umc9th/Umc9thApplicationTests.java" @@ -0,0 +1,13 @@ +package com.example.umc9th; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class Umc9thApplicationTests { + + @Test + void contextLoads() { + } + +}