From 5b41cdc273990760df15e99f776b49a0738fb0b2 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Thu, 18 Sep 2025 12:51:41 +0900 Subject: [PATCH 1/9] {feat} : domain --- db_dev.mv.db | Bin 0 -> 20480 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 db_dev.mv.db diff --git a/db_dev.mv.db b/db_dev.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..9ca0f636fb0899f7125b2dbb2379dbec9f3b27b2 GIT binary patch literal 20480 zcmeHP%WmVy6(u!pk7CCOFi6&^Q9o=4ia-|MTn#1B7SVcmM9R}%2^3lEHd>YpS?;t0 z1eiruSp`8btI4W&0h0VekWWZ<*<_m!2!bqg`6!xtICf_2%m7_NLscvms}4``Qum%) z?v{zGqwzF&O-uLmXT%f*L8u0=E+?-|NvsBA;!jK{XT+bA&=d_rQFKFAqOclGXJ`K0 zl&WvY?BaAfiTg)mG7nynnHfn2F;qd_;@F2Vz!+c*Fa{U{i~+^~V}LQh7+?%A1{ed3 zfp3t37LEI9$>RTSa5dP}i~+^~V}LQh7+?%A1{ed30mcAhfHA-rco+uqB>$MiDgJZ+ zCAolX{+a*Qlmh|Ea}(>;*>pNL0~vM&2tp_+LUn$6ModN3B0(~Wss9OiJ2#c;d>WW? zB%piz#Cr(-$jRKJ633UgkI}OiuI-^l-?lt^SRXj;Cc+Y~pvulK__P%bT)U5)1Jvz# z$bR9to{K83RY9)R_Ry{(8Im6PqCf;)5J&nhYFTaz?W(dK5FF@+CP)h0M1(a>!;yh; zAQ(b`N1-nUzCh&2*FznLex!$yE=8g*iJ=^kU1T*oPM72Oe{x^){72j)AhCuwlW#38 z^rTHnzLn%#O}@3{J3VV`PW&@c8-6z_#?w*LpZnYNpyQwC^*)Jyn6yvN$;6xalM6qX z!(NPw^wPOM8k3sv{iMsBoSnC)Be?u~$?@eRoVKSgYvSS|P9`^pKZ-kT7ak!a`sL3v%_1KQ;KF-GRH zC%*cPkp%?}aYN$U>ok1Gr@4m;#Qz&V-}pE8XcOZ94>q9q_Gd$!osM;A4+s7BZT-53eY@!ZX}5Ij+YRUF zHi%Zc(QEbEL)Yuu-9xWcL3Vf0+1qV9hb?cnigr6N*Ps*Ey1ni&>+Uq-2DqlzJ&bF| zcK;+EB0K!dww~{xfXwu;uZOe7jQQFx>ZmZV=9+QDvy}q}*zqS7aJ>EIX9zD9~ zg~#rzJr1zmeGh%+cr7HNx*gB&4!zzmd8nVFk9R)JW<2V{n)FZ5bNi$)Y1TS~*5N?~ z!PC0V4i-#c{~3C^^EnTS9XuyD+73u=P1NXhfk!JgnBuUsF`lsiYj1HH{l-5^+;?(uP^T)PPb&efgtS8LrW@+{AMq7`$BU9&sv8z1 zxlE9gQr*yBqr_oVA_d(LgEYP(%;Df#H%x!{lF?YTv`+qagpCq zTqMJ#F5p@vFUGR6!in#wWh!>M(6M@3Txh?z(AT2&wM-0eoZK5F30BF+MXVyo#F-;2 z8zJ6KSx9B#v^}n?nN0izxc#4Syz`gD{pbJon}-Sm*tm=V#=v{Xz*793zr3RBzoJ(o zGEy{6y@w!rWr!^Phm_i)-w?n-Q`Bm(!9w??djwt9Rx3R0AR4azy-{Z zt%kh)lR9M5A>U4BWD<}k@jX4jjc;uiUmZWW3#JaF;}baWQ~zb@4}2kMpF7{t-JEag zje)ye*hEwG#!{ED=#4Ep-?#W;Y0`d8RvZ*JYJ7ODYZm1$Xt z%bN*`xYlkakeA%BVzz$44dXtCZ2hm()&0}2Zqm+J{0}>PSp1*uAEIybZ^6zW7XJ$@ z{!asb7XQavOVeLM7XKIh6;@{qFb3XF2D1D=jlZck521Aazv#(gC}J#&Un6+F@zSmT E05lSv4gdfE literal 0 HcmV?d00001 From 851480fc8e98f643f46809dc5ed30f60da888755 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Thu, 18 Sep 2025 13:06:18 +0900 Subject: [PATCH 2/9] {fix}:Cocktail-Wishlist relation --- src/main/java/com/back/domain/cocktail/entity/Cocktail.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java index d1761922..29ff9397 100644 --- a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java +++ b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java @@ -1,8 +1,12 @@ package com.back.domain.cocktail.entity; +<<<<<<< HEAD import com.back.domain.cocktail.enums.AlcoholBaseType; import com.back.domain.cocktail.enums.AlcoholStrength; import com.back.domain.cocktail.enums.CocktailType; +======= +import com.back.domain.wishlist.entity.Wishlist; +>>>>>>> a031134 ({fix}:Cocktail-Wishlist relation) import jakarta.persistence.*; import lombok.*; From 291fc273ad20fbf6273846d14b45f07a9a01fa08 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Thu, 18 Sep 2025 15:50:17 +0900 Subject: [PATCH 3/9] fix : enums --- db_dev.mv.db | Bin 20480 -> 24576 bytes .../domain/cocktail/dto/CocktailListDto.java | 17 +++++++++++++++++ .../cocktail/enums/AlcoholStrength.java | 1 - 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java diff --git a/db_dev.mv.db b/db_dev.mv.db index 9ca0f636fb0899f7125b2dbb2379dbec9f3b27b2..efe8a3b67dae0c6da78e132f0858f67db9fc45c8 100644 GIT binary patch literal 24576 zcmeHP&2QVt6_*q{tF_m=Nj61KZMoVcwzpc9oZ+W{0--3%Voga7Njou6fS@QUF=9)u zBd2kJ0()pLdnk$?3KS?%^irTjfgXF<%bt4KOVRdE=$}xu*S_JGC|R=QP15ZyMh6Z* zX5PH{&AcJsZ{Da`Mdj|{(0`hw_Q8*WD#x;H*?)36cv{7L**^@tL6s}}CxJH#dR0zQ z1VL7Kq2DX_hbKqgsEW(agOg_m!vV?PKMY3xli;Mvb4p+FS#c#te-r_V07ZZzKoOt_ zPy{Ff6ak6=MSvne5ugZsfe17czduQ-|NjN{2CbSRKoOt_Py{Ff6ak6=MSvne5ugZA z1SkTp2Z3~v|1cm+{Kwwo;2EsuA9*jT*k>UyK$J~2l>kgw?y6Wg|ZPzgC48o|y zl-7QdkM1(Nwr(*-gK2jhMt@}3j?I*8wZzz}=`ia8R*gkytG7eYTGzNkV-EA)i%PA9Z^k=X-3x_dU5Mqn_87dwm)AIS+F^z8|bJYQ1H& zbGiJ#a=*&wZ{?N�mm?ptAUIPBKFk++&$ zw7lc=+zR?%3-1q)gMoA64W4=a2x2jwMMXzm_b{li?}S-K!O^if>_YLk!|T&QZ)gr5 zSGdVb6jok!L%G#yx!)p1t7*|VFk~-@0Kt>b(YfdM!t$|R<)^_}6*>Y5h=sA_9aaUI z#a#gOZkP>P4%(j2)#rJMd`>~}M30rm@&K?fSKxI67D-X9oDg6|36w~= z81MPQ@+hz5#k`!yc_A+qFjv3`hUkB;{j88%&J{zus$l%aQ84l<2fgdWgeqK=pePZ3 zlaI|0$1ym3nV2Dp%@D2*o(DUjNphh{az4c6kee;APZ7>xI8`xQ4$V%C%+!ZGEGu{% z$HrzV^#ZYr%BO?VXF*RLjr(bAxsl0oGVYd#zJGe`4g9kz8|1mw*y;sQU{@p2EbAgQ0#um;2yjXg;KSJCMTf?`D+JBSnBBKoOt_Py{Ff6ak6=MSvoZATZ^B&y1oM z!1)w;;T1a5si>8>eiS+$lm5RH`xi)w9SfN_7994JjAOxb(%6eYks~66{=cZ;w3=6N z0{(yDr-g6i3ahzd;;I#~$8xN%C`BIk1WD+LMFHG;K@6l~;zSk`@2@B-JYisR5^P7Y&1LxD!p!{eR_Df=N+B~#1D7Qj)VVYp7NAF zqZgIfjSG6AQbeIU4ewdrd zgF^0lO3tteOT%5r()=M|Y1j#tCYdZ@>P%T0Ldd+R3K^0nqG*tq%#0zE8ZtC2OZdc? zq7kJ&i*QWQR0Uvc$i#Y%vEjyZEtDiAs{$4>CT#Gp6J5D&ZX{ z01?2lsMnR1qTH2Xi5Roti6lq?IUx)E-7#6>t+lt`xpDK>ySKjt!A0*g%-X+~;xH#o)tY*panzcrGo_u~nrUdIN=fTz z+m33OrHvIb`=-~fQ7TKg#;EIU$8g5?I&G%C zYnqI$KiJjVTDBg0-*)ttn>=wfK~S+IsV#nl_Kj8#F?covt!m@Fc( z94i;ban)VbDKU=G(rrg=?QDpf@#Ec{I?;08TW#qjMr*2;syPt+wWnJ9Mtf@m z2|^+&&1*XyYyXnWMoZn&-CfJPEMI%e((49*c1cD{*NmOZR8&o^)9je8?O1wy%W0Mv zy}jGoST~KWrn6pV)>}~5Zi}3?J8d`4ZfN8Nl|nwKHt#Wa*FMTaC?JfJ zxwZqbe04_av;jwz7)(}da+B1UQEOwe8pdeX^+%b4le(^hC4YMDVoN4*jCNwiYHiQ0 z>oDA)-x_8|bv6W?cI(Af^qLJ{M7+)klIGSpQF3|2*Ic<#Q(ReTNSIfVQbV9K3C7GA z{w0=ebwgIzph^o!hAp~_*YP#A;gc3_Pp*7Fr)=a;$ z8rwUXYVEZ22a?7Mk2*Udk7eF;B=vjoTr&OAO*PKE4JQU{c4}F=1x^3woVg{HG{5Z^ zs0Z)Jj-?x0ZSuh|N0;+fdV#=kdo8`8!}pn{!>)oEAKg=50qqWaq-)zt?*hyRb76L@ zx`?q*Gi|+LqOC_eHQBV-ElV0#JMnFkg0oQ~Q&ng|6Ug2MWIuZuWanx$g=|v&EHLNF z7`JLBn9=OJ5t;`~7$JbU+_it)d|1eTb8-PbT8HH&ZjB*dI8o#5Sc(a8%6xHzb(|3Q)d<2Upnd_f1=JhwmMNg1fVu_b!?qcu6cE`z z^5?JTu4N)KxFj+IEf$$^d9*_mnURflh$Azu6zmX2X3X46gT|2=Gh-j5G>Rnozuky( zPohZRYAT9^gx@8R8L_U)WMD=ZJ~1O6FA5u3NLQ4E>Sg0JBoe0)a{avLbNs}%pXfdZ z;dVYSf*(Pg#xJ4!?&tE~{XSgZ&n^A&cE}Vi|Mo_h(gQ_+B0v$K2v7tl0_PD(HvmT) Ue={rTYpS?;t0 z1eiruSp`8btI4W&0h0VekWWZ<*<_m!2!bqg`6!xtICf_2%m7_NLscvms}4``Qum%) z?v{zGqwzF&O-uLmXT%f*L8u0=E+?-|NvsBA;!jK{XT+bA&=d_rQFKFAqOclGXJ`K0 zl&WvY?BaAfiTg)mG7nynnHfn2F;qd_;@F2Vz!+c*Fa{U{i~+^~V}LQh7+?%A1{ed3 zfp3t37LEI9$>RTSa5dP}i~+^~V}LQh7+?%A1{ed30mcAhfHA-rco+uqB>$MiDgJZ+ zCAolX{+a*Qlmh|Ea}(>;*>pNL0~vM&2tp_+LUn$6ModN3B0(~Wss9OiJ2#c;d>WW? zB%piz#Cr(-$jRKJ633UgkI}OiuI-^l-?lt^SRXj;Cc+Y~pvulK__P%bT)U5)1Jvz# z$bR9to{K83RY9)R_Ry{(8Im6PqCf;)5J&nhYFTaz?W(dK5FF@+CP)h0M1(a>!;yh; zAQ(b`N1-nUzCh&2*FznLex!$yE=8g*iJ=^kU1T*oPM72Oe{x^){72j)AhCuwlW#38 z^rTHnzLn%#O}@3{J3VV`PW&@c8-6z_#?w*LpZnYNpyQwC^*)Jyn6yvN$;6xalM6qX z!(NPw^wPOM8k3sv{iMsBoSnC)Be?u~$?@eRoVKSgYvSS|P9`^pKZ-kT7ak!a`sL3v%_1KQ;KF-GRH zC%*cPkp%?}aYN$U>ok1Gr@4m;#Qz&V-}pE8XcOZ94>q9q_Gd$!osM;A4+s7BZT-53eY@!ZX}5Ij+YRUF zHi%Zc(QEbEL)Yuu-9xWcL3Vf0+1qV9hb?cnigr6N*Ps*Ey1ni&>+Uq-2DqlzJ&bF| zcK;+EB0K!dww~{xfXwu;uZOe7jQQFx>ZmZV=9+QDvy}q}*zqS7aJ>EIX9zD9~ zg~#rzJr1zmeGh%+cr7HNx*gB&4!zzmd8nVFk9R)JW<2V{n)FZ5bNi$)Y1TS~*5N?~ z!PC0V4i-#c{~3C^^EnTS9XuyD+73u=P1NXhfk!JgnBuUsF`lsiYj1HH{l-5^+;?(uP^T)PPb&efgtS8LrW@+{AMq7`$BU9&sv8z1 zxlE9gQr*yBqr_oVA_d(LgEYP(%;Df#H%x!{lF?YTv`+qagpCq zTqMJ#F5p@vFUGR6!in#wWh!>M(6M@3Txh?z(AT2&wM-0eoZK5F30BF+MXVyo#F-;2 z8zJ6KSx9B#v^}n?nN0izxc#4Syz`gD{pbJon}-Sm*tm=V#=v{Xz*793zr3RBzoJ(o zGEy{6y@w!rWr!^Phm_i)-w?n-Q`Bm(!9w??djwt9Rx3R0AR4azy-{Z zt%kh)lR9M5A>U4BWD<}k@jX4jjc;uiUmZWW3#JaF;}baWQ~zb@4}2kMpF7{t-JEag zje)ye*hEwG#!{ED=#4Ep-?#W;Y0`d8RvZ*JYJ7ODYZm1$Xt z%bN*`xYlkakeA%BVzz$44dXtCZ2hm()&0}2Zqm+J{0}>PSp1*uAEIybZ^6zW7XJ$@ z{!asb7XQavOVeLM7XKIh6;@{qFb3XF2D1D=jlZck521Aazv#(gC}J#&Un6+F@zSmT E05lSv4gdfE diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java new file mode 100644 index 00000000..11826a43 --- /dev/null +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java @@ -0,0 +1,17 @@ +package com.back.domain.cocktail.dto; + +import com.back.domain.cocktail.enums.AlcoholBaseType; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class CocktailListDto { + private Long cocktailId; + private String cocktailName; + private String cocktailImgUrl; + + private String alcoholStrength; + private String cocktailType; + private AlcoholBaseType alcoholBaseType; +} diff --git a/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java b/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java index d580b50b..68dbef47 100644 --- a/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java +++ b/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java @@ -17,5 +17,4 @@ public enum AlcoholStrength { public String getDescription() { return description; } - } From 012ea22b2797f5234533c2572257efaa0b51a0b3 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Thu, 18 Sep 2025 16:30:35 +0900 Subject: [PATCH 4/9] fix : bug --- .../java/com/back/domain/cocktail/dto/CocktailListDto.java | 3 +++ src/main/java/com/back/domain/cocktail/entity/Cocktail.java | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java index 11826a43..7369af75 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java @@ -4,6 +4,8 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.List; + @Getter @AllArgsConstructor public class CocktailListDto { @@ -14,4 +16,5 @@ public class CocktailListDto { private String alcoholStrength; private String cocktailType; private AlcoholBaseType alcoholBaseType; + private List ingredientNames; } diff --git a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java index 29ff9397..d1761922 100644 --- a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java +++ b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java @@ -1,12 +1,8 @@ package com.back.domain.cocktail.entity; -<<<<<<< HEAD import com.back.domain.cocktail.enums.AlcoholBaseType; import com.back.domain.cocktail.enums.AlcoholStrength; import com.back.domain.cocktail.enums.CocktailType; -======= -import com.back.domain.wishlist.entity.Wishlist; ->>>>>>> a031134 ({fix}:Cocktail-Wishlist relation) import jakarta.persistence.*; import lombok.*; From 11d9c06d7e8caab2bd9302b16b883cb57da22323 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Fri, 19 Sep 2025 12:52:14 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat=20:=20=EC=A1=B0=ED=9A=8C=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5,=20=EC=A1=B0init=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db_dev.mv.db | Bin 24576 -> 28672 bytes .../domain/cocktail/dto/CocktailListDto.java | 20 ------------------ .../cocktail/enums/AlcoholStrength.java | 1 + .../repository/CocktailRepository.java | 3 +++ .../cocktail/service/CocktailService.java | 2 ++ 5 files changed, 6 insertions(+), 20 deletions(-) delete mode 100644 src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java diff --git a/db_dev.mv.db b/db_dev.mv.db index efe8a3b67dae0c6da78e132f0858f67db9fc45c8..500f682ad0a5506cd68cfb22e68f462ced8ebf03 100644 GIT binary patch literal 28672 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 Z)w3zm=|pv#^s}+xkfMcXW5Lne{{ij$K=A+o diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java deleted file mode 100644 index 7369af75..00000000 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailListDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.back.domain.cocktail.dto; - -import com.back.domain.cocktail.enums.AlcoholBaseType; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.List; - -@Getter -@AllArgsConstructor -public class CocktailListDto { - private Long cocktailId; - private String cocktailName; - private String cocktailImgUrl; - - private String alcoholStrength; - private String cocktailType; - private AlcoholBaseType alcoholBaseType; - private List ingredientNames; -} diff --git a/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java b/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java index 68dbef47..d580b50b 100644 --- a/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java +++ b/src/main/java/com/back/domain/cocktail/enums/AlcoholStrength.java @@ -17,4 +17,5 @@ public enum AlcoholStrength { public String getDescription() { return description; } + } diff --git a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java index 9aa69286..6135aa00 100644 --- a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java +++ b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java @@ -4,6 +4,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import org.springframework.data.domain.Pageable; +import java.util.List; import java.util.List; @@ -17,4 +19,5 @@ public interface CocktailRepository extends JpaRepository { List findByCocktailIdLessThanOrderByCocktailIdDesc(Long lastId, Pageable pageable); List findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(String cocktailName, String ingredient); + } diff --git a/src/main/java/com/back/domain/cocktail/service/CocktailService.java b/src/main/java/com/back/domain/cocktail/service/CocktailService.java index 61d4ca9f..e436bfcc 100644 --- a/src/main/java/com/back/domain/cocktail/service/CocktailService.java +++ b/src/main/java/com/back/domain/cocktail/service/CocktailService.java @@ -20,6 +20,8 @@ public class CocktailService { @Transactional(readOnly = true) public Cocktail getCocktailById(Long id) { + + public Cocktail findById(Long id) { return cocktailRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("User not found. id=" + id)); } From 606967c5fd5aea63e146db12de9a0ac08b82ef7c Mon Sep 17 00:00:00 2001 From: LeeKW Date: Fri, 19 Sep 2025 16:53:59 +0900 Subject: [PATCH 6/9] feat : cocktailSearch --- db_dev.mv.db | Bin 28672 -> 0 bytes .../cocktail/repository/CocktailRepository.java | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 db_dev.mv.db diff --git a/db_dev.mv.db b/db_dev.mv.db deleted file mode 100644 index 500f682ad0a5506cd68cfb22e68f462ced8ebf03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 { List findByCocktailIdLessThanOrderByCocktailIdDesc(Long lastId, Pageable pageable); List findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(String cocktailName, String ingredient); - } From 37a4fd538de1bcfd496302b2c60933a1496bd1f4 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Mon, 22 Sep 2025 14:41:39 +0900 Subject: [PATCH 7/9] feat : search --- .../controller/CocktailController.java | 4 ++ .../cocktail/dto/CocktailDetailDto.java | 32 ++++++++++++ .../dto/CocktailFilterRequestDto.java | 42 ++++++++++++++++ .../cocktail/dto/CocktailResponseDto.java | 13 +++++ .../repository/CocktailRepository.java | 19 +++++++ .../cocktail/service/CocktailService.java | 50 +++++++++++++++++++ .../com/back/global/init/DevInitData.java | 9 ++++ 7 files changed, 169 insertions(+) create mode 100644 src/main/java/com/back/domain/cocktail/controller/CocktailController.java create mode 100644 src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java create mode 100644 src/main/java/com/back/domain/cocktail/dto/CocktailFilterRequestDto.java diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java new file mode 100644 index 00000000..edcde50e --- /dev/null +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java @@ -0,0 +1,4 @@ +package com.back.domain.cocktail.controller; + +public class CocktailController { +} diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java new file mode 100644 index 00000000..40d2906c --- /dev/null +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java @@ -0,0 +1,32 @@ +package com.back.domain.cocktail.dto; + +import com.back.domain.cocktail.entity.Cocktail; +import com.back.domain.cocktail.enums.AlcoholBaseType; +import com.back.domain.cocktail.enums.AlcoholStrength; +import com.back.domain.cocktail.enums.CocktailType; + +import java.time.LocalDateTime; + +public class CocktailDetailDto { + private Long cocktailId; + private String cocktailName; + private String ingredient; + private AlcoholStrength alcoholStrength; + private CocktailType cocktailType; + private AlcoholBaseType alcoholBaseType; + private String cocktailImgUrl; + private String cocktailStory; + private LocalDateTime createdAt; + + public CocktailDetailDto(Cocktail c) { + this.cocktailId = c.getCocktailId(); + this.cocktailName = c.getCocktailName(); + this.ingredient = c.getIngredient(); + this.alcoholStrength = c.getAlcoholStrength(); + this.cocktailType = c.getCocktailType(); + this.alcoholBaseType = c.getAlcoholBaseType(); + this.cocktailImgUrl = c.getCocktailImgUrl(); + this.cocktailStory = c.getCocktailStory(); + this.createdAt = c.getCreatedAt(); + } +} diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailFilterRequestDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailFilterRequestDto.java new file mode 100644 index 00000000..8b092451 --- /dev/null +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailFilterRequestDto.java @@ -0,0 +1,42 @@ +package com.back.domain.cocktail.dto; + +import com.back.domain.cocktail.enums.AlcoholBaseType; +import com.back.domain.cocktail.enums.AlcoholStrength; +import com.back.domain.cocktail.enums.CocktailType; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class CocktailFilterRequestDto { + + private String keyword; // 검색 키워드 + + private List alcoholStrengths; + + private List cocktailTypes; + + private List alcoholBaseTypes; + + // 페이징/정렬 추가하고 싶으면 여기 옵션 추가 + private Integer page; // 0-based 페이지 번호 + private Integer size; // 페이지 사이즈 + + // 생성자 + public CocktailFilterRequestDto(String keyword, + List alcoholStrengths, + List cocktailTypes, + List alcoholBaseTypes, + Integer page, Integer size) { + this.keyword = keyword; + this.alcoholStrengths = alcoholStrengths; + this.cocktailTypes = cocktailTypes; + this.alcoholBaseTypes = alcoholBaseTypes; + this.page = page; + this.size = size; + } +} diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailResponseDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailResponseDto.java index 3fb8b929..a89c642e 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailResponseDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailResponseDto.java @@ -26,4 +26,17 @@ public class CocktailResponseDto { private LocalDateTime createdAt; private LocalDateTime updatedAt; + public CocktailResponseDto(long cocktailId, String cocktailName, + AlcoholStrength alcoholStrength, CocktailType cocktailType, + AlcoholBaseType alcoholBaseType, String cocktailImgUrl, + String cocktailStory, LocalDateTime createdAt) { + this.cocktailId = cocktailId; + this.cocktailName = cocktailName; + this.alcoholStrength = alcoholStrength; + this.cocktailType = cocktailType; + this.alcoholBaseType = alcoholBaseType; + this.cocktailImgUrl = cocktailImgUrl; + this.cocktailStory = cocktailStory; + this.createdAt = createdAt; + } } \ No newline at end of file diff --git a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java index 20bb5b6d..737ea36f 100644 --- a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java +++ b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java @@ -1,8 +1,14 @@ package com.back.domain.cocktail.repository; import com.back.domain.cocktail.entity.Cocktail; +import com.back.domain.cocktail.enums.AlcoholBaseType; +import com.back.domain.cocktail.enums.AlcoholStrength; +import com.back.domain.cocktail.enums.CocktailType; +import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -19,4 +25,17 @@ public interface CocktailRepository extends JpaRepository { List findByCocktailIdLessThanOrderByCocktailIdDesc(Long lastId, Pageable pageable); List findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(String cocktailName, String ingredient); + + @Query("SELECT c FROM Cocktail c " + + "WHERE (:keyword IS NULL OR :keyword = '' OR " + + " LOWER(c.cocktailName) LIKE LOWER(CONCAT('%', :keyword, '%')) OR " + + " LOWER(c.ingredient) LIKE LOWER(CONCAT('%', :keyword, '%')))" + + " AND (:strengths IS NULL OR c.alcoholStrength IN :strengths) " + // 알코올 도수 필터를 담당 + " AND (:types IS NULL OR c.cocktailType IN :types) " + // 칵테일 타입 필터를 담당 + " AND (:bases IS NULL OR c.alcoholBaseType IN :bases) ") // 알코올 베이스 필터를 담당 + Page searchWithFilters(@Param("keyword") String keyword, + @Param("strengths") List strengths, + @Param("types") List types, + @Param("bases") List bases, + Pageable pageable); } diff --git a/src/main/java/com/back/domain/cocktail/service/CocktailService.java b/src/main/java/com/back/domain/cocktail/service/CocktailService.java index e436bfcc..5a4eafaa 100644 --- a/src/main/java/com/back/domain/cocktail/service/CocktailService.java +++ b/src/main/java/com/back/domain/cocktail/service/CocktailService.java @@ -1,12 +1,18 @@ package com.back.domain.cocktail.service; +import com.back.domain.cocktail.dto.CocktailDetailDto; +import com.back.domain.cocktail.dto.CocktailFilterRequestDto; +import com.back.domain.cocktail.dto.CocktailResponseDto; import com.back.domain.cocktail.dto.CocktailSummaryDto; import com.back.domain.cocktail.entity.Cocktail; import com.back.domain.cocktail.repository.CocktailRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; + import java.util.List; import java.util.stream.Collectors; @@ -46,6 +52,7 @@ public List getCocktails(Long lastId, Integer size) { // 무 } // 칵테일 검색기능 + @Transactional(readOnly = true) public List cocktailSearch(String keyword) { // cockTailName, ingredient이 하나만 있을 수도 있고 둘 다 있을 수도 있음 if (keyword == null || keyword.trim().isEmpty()) { @@ -56,4 +63,47 @@ public List cocktailSearch(String keyword) { return cocktailRepository.findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(keyword, keyword); } } + + // 칵테일 검색,필터기능 + @Transactional(readOnly = true) + public List searchAndFilter(CocktailFilterRequestDto cocktailFilterRequestDto) { + // 기본값 페이지/사이즈 정하기(PAGE 기본값 0, 사이즈 10) + int page = cocktailFilterRequestDto.getPage() != null && cocktailFilterRequestDto.getPage() >= 0 ? cocktailFilterRequestDto.getPage() : 0; + int size = cocktailFilterRequestDto.getSize() != null && cocktailFilterRequestDto.getSize() > 0 ? cocktailFilterRequestDto.getSize() : 10; + + // searchWithFilters에서 조회한 결과값을 pageResult에 저장. + Pageable pageable = PageRequest.of(page, size); + Page pageResult = cocktailRepository.searchWithFilters( + cocktailFilterRequestDto.getKeyword(), + cocktailFilterRequestDto.getAlcoholStrengths(), // List + cocktailFilterRequestDto.getCocktailTypes(), // List + cocktailFilterRequestDto.getAlcoholBaseTypes(), // List + pageable + ); + + //Cocktail 엔티티 → CocktailResponseDto 응답 DTO로 바꿔주는 과정 + List resultDtos = pageResult.stream() + .map(c -> new CocktailResponseDto( + c.getCocktailId(), + c.getCocktailName(), + c.getAlcoholStrength(), + c.getCocktailType(), + c.getAlcoholBaseType(), + c.getCocktailImgUrl(), + c.getCocktailStory(), + c.getCreatedAt() + )) + .collect(Collectors.toList()); + + return resultDtos; + } + + // 칵테일 상세조회 + @Transactional(readOnly = true) + public CocktailDetailDto getCocktailDetailById(Long cocktailId) { + Cocktail cocktail = cocktailRepository.findById(cocktailId) + .orElseThrow(() -> new RuntimeException("칵테일을 찾을 수 없습니다. id: " + cocktailId)); + + return new CocktailDetailDto(cocktail); + } } diff --git a/src/main/java/com/back/global/init/DevInitData.java b/src/main/java/com/back/global/init/DevInitData.java index fd7e71c4..69d0c462 100644 --- a/src/main/java/com/back/global/init/DevInitData.java +++ b/src/main/java/com/back/global/init/DevInitData.java @@ -1,5 +1,6 @@ package com.back.global.init; +import com.back.domain.cocktail.dto.CocktailFilterRequestDto; import com.back.domain.cocktail.entity.Cocktail; import com.back.domain.cocktail.enums.AlcoholStrength; import com.back.domain.cocktail.repository.CocktailRepository; @@ -13,6 +14,8 @@ import org.springframework.context.annotation.Profile; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; + @Configuration @Profile("dev") @RequiredArgsConstructor @@ -47,10 +50,16 @@ public void cocktailInit() { .alcoholStrength(AlcoholStrength.NON_ALCOHOLIC) .build()); } + + CocktailFilterRequestDto filterDto = new CocktailFilterRequestDto(); + filterDto.setKeyword("cocktail 4"); // 검색 키워드 설정 + filterDto.setAlcoholStrengths(Arrays.asList(AlcoholStrength.NON_ALCOHOLIC)); + System.out.println("DevInitData: 테스트 칵테일 20개 삽입"); System.out.println(cocktailService.getCocktailById(2l)); System.out.println(cocktailService.cocktailSearch("cocktail 3")); System.out.println(cocktailService.cocktailSearch("Ingredient 4")); + System.out.println("filterDTO 결과값"+cocktailService.searchAndFilter(filterDto)); } } From 945f802d99fe9877be80aaee7f0ccc5afb047390 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Mon, 22 Sep 2025 17:08:50 +0900 Subject: [PATCH 8/9] feat: get cocktailTest --- .../controller/CocktailController.java | 30 +++++++ .../cocktail/service/CocktailService.java | 36 ++++++-- .../controller/CocktailControllerTest.java | 90 +++++++++++++++++++ 3 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java index edcde50e..57e8b10e 100644 --- a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java @@ -1,4 +1,34 @@ package com.back.domain.cocktail.controller; +import com.back.domain.cocktail.dto.CocktailDetailDto; +import com.back.domain.cocktail.service.CocktailService; +import com.back.domain.user.service.UserService; +import com.back.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("api/cocktails") +@RequiredArgsConstructor public class CocktailController { + + private final CocktailService cocktailService; + private final UserService userService; + + @GetMapping("/{id}") + @Transactional + @Operation(summary = "칵테일 단건 조회") + public RsData getCocktailDetailById(@PathVariable long id) { + try { + CocktailDetailDto cocktailDetailDto = cocktailService.getCocktailDetailById(id); + return RsData.successOf(cocktailDetailDto); + } catch (RuntimeException e) { + return RsData.failOf("칵테일이 존재하지 않습니다."); + } + } } diff --git a/src/main/java/com/back/domain/cocktail/service/CocktailService.java b/src/main/java/com/back/domain/cocktail/service/CocktailService.java index 5a4eafaa..6ab4dd1b 100644 --- a/src/main/java/com/back/domain/cocktail/service/CocktailService.java +++ b/src/main/java/com/back/domain/cocktail/service/CocktailService.java @@ -5,6 +5,9 @@ import com.back.domain.cocktail.dto.CocktailResponseDto; import com.back.domain.cocktail.dto.CocktailSummaryDto; import com.back.domain.cocktail.entity.Cocktail; +import com.back.domain.cocktail.enums.AlcoholBaseType; +import com.back.domain.cocktail.enums.AlcoholStrength; +import com.back.domain.cocktail.enums.CocktailType; import com.back.domain.cocktail.repository.CocktailRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -12,6 +15,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; import java.util.List; import java.util.stream.Collectors; @@ -68,16 +72,34 @@ public List cocktailSearch(String keyword) { @Transactional(readOnly = true) public List searchAndFilter(CocktailFilterRequestDto cocktailFilterRequestDto) { // 기본값 페이지/사이즈 정하기(PAGE 기본값 0, 사이즈 10) - int page = cocktailFilterRequestDto.getPage() != null && cocktailFilterRequestDto.getPage() >= 0 ? cocktailFilterRequestDto.getPage() : 0; - int size = cocktailFilterRequestDto.getSize() != null && cocktailFilterRequestDto.getSize() > 0 ? cocktailFilterRequestDto.getSize() : 10; + int page = cocktailFilterRequestDto.getPage() != null && cocktailFilterRequestDto.getPage() >= 0 + ? cocktailFilterRequestDto.getPage() : 0; + + int size = cocktailFilterRequestDto.getSize() != null && cocktailFilterRequestDto.getSize() > 0 + ? cocktailFilterRequestDto.getSize() : DEFAULT_SIZE; // searchWithFilters에서 조회한 결과값을 pageResult에 저장. Pageable pageable = PageRequest.of(page, size); + + // 빈 리스트(null 또는 [])는 null로 변환 + List strengths = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholStrengths()) + ? null + : cocktailFilterRequestDto.getAlcoholStrengths(); + + List types = CollectionUtils.isEmpty(cocktailFilterRequestDto.getCocktailTypes()) + ? null + : cocktailFilterRequestDto.getCocktailTypes(); + + List bases = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholBaseTypes()) + ? null + : cocktailFilterRequestDto.getAlcoholBaseTypes(); + + // Repository 호출 Page pageResult = cocktailRepository.searchWithFilters( cocktailFilterRequestDto.getKeyword(), - cocktailFilterRequestDto.getAlcoholStrengths(), // List - cocktailFilterRequestDto.getCocktailTypes(), // List - cocktailFilterRequestDto.getAlcoholBaseTypes(), // List + strengths, // List + types, // List + bases, // List pageable ); @@ -98,6 +120,10 @@ public List searchAndFilter(CocktailFilterRequestDto cockta return resultDtos; } +// private List nullIfEmpty(List list) { +// return CollectionUtils.isEmpty(list) ? null : list; +// } + // 칵테일 상세조회 @Transactional(readOnly = true) public CocktailDetailDto getCocktailDetailById(Long cocktailId) { diff --git a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java new file mode 100644 index 00000000..530cd591 --- /dev/null +++ b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java @@ -0,0 +1,90 @@ +package com.back.domain.cocktail.controller; + +import com.back.domain.cocktail.entity.Cocktail; +import com.back.domain.cocktail.enums.AlcoholBaseType; +import com.back.domain.cocktail.enums.AlcoholStrength; +import com.back.domain.cocktail.enums.CocktailType; +import com.back.domain.cocktail.repository.CocktailRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +public class CocktailControllerTest { + @Autowired + private MockMvc mvc; + + @Autowired + private CocktailRepository cocktailRepository; + + +// @Autowired +// private UserService userService; + +@Test +@DisplayName("칵테일 단건 조회 - 성공") +void t1() throws Exception { + Cocktail savedCocktail = cocktailRepository.save( + Cocktail.builder() + .cocktailName("모히토") + .alcoholStrength(AlcoholStrength.WEAK) + .cocktailType(CocktailType.SHORT) + .alcoholBaseType(AlcoholBaseType.RUM) + .cocktailImgUrl("https://example.com/image.jpg") + .cocktailStory("상쾌한 라임과 민트") + .ingredient("라임, 민트, 럼, 설탕, 탄산수") + .recipe("라임과 민트를 섞고 럼을 넣고 탄산수로 완성") + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build() + ); + + // when: GET 요청 + ResultActions resultActions = mvc.perform( + get("/api/cocktails/{id}", savedCocktail.getCocktailId()) + .contentType(MediaType.APPLICATION_JSON) + ).andDo(print()); + + // then: 상태코드, JSON 구조 검증 + resultActions + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andExpect(jsonPath("$.message").value("success")) + .andExpect(jsonPath("$.data.cocktailName").value("모히토")) + .andExpect(jsonPath("$.data.alcoholStrength").value("WEAK")) + .andExpect(jsonPath("$.data.cocktailType").value("SHORT")) + .andExpect(jsonPath("$.data.alcoholBaseType").value("RUM")); +} + + @Test + @DisplayName("칵테일 단건 조회 - 실패 (존재하지 않는 ID)") + void t2() throws Exception { + long nonExistentId = 9999L; + + ResultActions resultActions = mvc.perform( + get("/api/v1/cocktails/{id}", nonExistentId) + .contentType(MediaType.APPLICATION_JSON) + ).andDo(print()); + + resultActions + .andExpect(status().isOk()) // RsData는 HTTP 200으로 반환됨 + .andExpect(jsonPath("$.code").value(500)) + .andExpect(jsonPath("$.message").value("칵테일이 존재하지 않습니다.")) + .andExpect(jsonPath("$.data").isEmpty()); + } +} From 2005a262d8fd2640a8a97c20afd591b9e54d7066 Mon Sep 17 00:00:00 2001 From: LeeKW Date: Tue, 23 Sep 2025 06:39:00 +0900 Subject: [PATCH 9/9] feat : controller --- .../controller/CocktailController.java | 5 +- .../cocktail/dto/CocktailDetailDto.java | 8 +- .../back/domain/cocktail/entity/Cocktail.java | 2 - .../repository/CocktailRepository.java | 2 - .../cocktail/service/CocktailService.java | 182 +++++++++--------- .../back/global/security/SecurityConfig.java | 2 +- .../controller/CocktailControllerTest.java | 78 ++++---- 7 files changed, 136 insertions(+), 143 deletions(-) diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java index 57e8b10e..62db435e 100644 --- a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java @@ -24,11 +24,8 @@ public class CocktailController { @Transactional @Operation(summary = "칵테일 단건 조회") public RsData getCocktailDetailById(@PathVariable long id) { - try { + CocktailDetailDto cocktailDetailDto = cocktailService.getCocktailDetailById(id); return RsData.successOf(cocktailDetailDto); - } catch (RuntimeException e) { - return RsData.failOf("칵테일이 존재하지 않습니다."); - } } } diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java index 40d2906c..033ceb8a 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailDto.java @@ -4,9 +4,11 @@ import com.back.domain.cocktail.enums.AlcoholBaseType; import com.back.domain.cocktail.enums.AlcoholStrength; import com.back.domain.cocktail.enums.CocktailType; +import lombok.Getter; +import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - +@Getter +@NoArgsConstructor public class CocktailDetailDto { private Long cocktailId; private String cocktailName; @@ -16,7 +18,6 @@ public class CocktailDetailDto { private AlcoholBaseType alcoholBaseType; private String cocktailImgUrl; private String cocktailStory; - private LocalDateTime createdAt; public CocktailDetailDto(Cocktail c) { this.cocktailId = c.getCocktailId(); @@ -27,6 +28,5 @@ public CocktailDetailDto(Cocktail c) { this.alcoholBaseType = c.getAlcoholBaseType(); this.cocktailImgUrl = c.getCocktailImgUrl(); this.cocktailStory = c.getCocktailStory(); - this.createdAt = c.getCreatedAt(); } } diff --git a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java index d1761922..918a8d4b 100644 --- a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java +++ b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java @@ -5,9 +5,7 @@ import com.back.domain.cocktail.enums.CocktailType; import jakarta.persistence.*; import lombok.*; - import java.time.LocalDateTime; - import static jakarta.persistence.GenerationType.IDENTITY; diff --git a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java index 737ea36f..285457f9 100644 --- a/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java +++ b/src/main/java/com/back/domain/cocktail/repository/CocktailRepository.java @@ -13,8 +13,6 @@ import java.util.List; -import java.util.List; - @Repository public interface CocktailRepository extends JpaRepository { diff --git a/src/main/java/com/back/domain/cocktail/service/CocktailService.java b/src/main/java/com/back/domain/cocktail/service/CocktailService.java index 6ab4dd1b..dc610593 100644 --- a/src/main/java/com/back/domain/cocktail/service/CocktailService.java +++ b/src/main/java/com/back/domain/cocktail/service/CocktailService.java @@ -18,6 +18,7 @@ import org.springframework.util.CollectionUtils; import java.util.List; +import java.util.NoSuchElementException; import java.util.stream.Collectors; @Service @@ -30,106 +31,103 @@ public class CocktailService { @Transactional(readOnly = true) public Cocktail getCocktailById(Long id) { - - public Cocktail findById(Long id) { - return cocktailRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("User not found. id=" + id)); - } - - // 칵테일 무한스크롤 조회 - @Transactional(readOnly = true) - public List getCocktails(Long lastId, Integer size) { // 무한스크롤 조회, 클라이언트 쪽에서 lastId와 size 정보를 받음.(스크롤 이벤트) - int fetchSize = (size != null) ? size : DEFAULT_SIZE; - - List cocktails; - if (lastId == null) { - // 첫 요청 → 최신 데이터부터 - cocktails = cocktailRepository.findAllByOrderByCocktailIdDesc(PageRequest.of(0, fetchSize)); - } else { - // 무한스크롤 → 마지막 ID보다 작은 데이터 조회 - cocktails = cocktailRepository.findByCocktailIdLessThanOrderByCocktailIdDesc(lastId, PageRequest.of(0, fetchSize)); + return cocktailRepository.findById(id) + .orElseThrow(() -> new IllegalArgumentException("User not found. id=" + id)); } - return cocktails.stream() - .map(c -> new CocktailSummaryDto(c.getCocktailId(), c.getCocktailName(), c.getCocktailImgUrl())) - .collect(Collectors.toList()); - } + // 칵테일 무한스크롤 조회 + @Transactional(readOnly = true) + public List getCocktails (Long lastId, Integer size) + { // 무한스크롤 조회, 클라이언트 쪽에서 lastId와 size 정보를 받음.(스크롤 이벤트) + int fetchSize = (size != null) ? size : DEFAULT_SIZE; + + List cocktails; + if (lastId == null) { + // 첫 요청 → 최신 데이터부터 + cocktails = cocktailRepository.findAllByOrderByCocktailIdDesc(PageRequest.of(0, fetchSize)); + } else { + // 무한스크롤 → 마지막 ID보다 작은 데이터 조회 + cocktails = cocktailRepository.findByCocktailIdLessThanOrderByCocktailIdDesc(lastId, PageRequest.of(0, fetchSize)); + } + return cocktails.stream() + .map(c -> new CocktailSummaryDto(c.getCocktailId(), c.getCocktailName(), c.getCocktailImgUrl())) + .collect(Collectors.toList()); + } - // 칵테일 검색기능 - @Transactional(readOnly = true) - public List cocktailSearch(String keyword) { - // cockTailName, ingredient이 하나만 있을 수도 있고 둘 다 있을 수도 있음 - if (keyword == null || keyword.trim().isEmpty()) { - // 아무 검색어 없으면 전체 반환 처리 - return cocktailRepository.findAll(); - } else { - // 이름 또는 재료 둘 중 하나라도 매칭되면 결과 반환 - return cocktailRepository.findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(keyword, keyword); + // 칵테일 검색기능 + @Transactional(readOnly = true) + public List cocktailSearch (String keyword){ + // cockTailName, ingredient이 하나만 있을 수도 있고 둘 다 있을 수도 있음 + if (keyword == null || keyword.trim().isEmpty()) { + // 아무 검색어 없으면 전체 반환 처리 + return cocktailRepository.findAll(); + } else { + // 이름 또는 재료 둘 중 하나라도 매칭되면 결과 반환 + return cocktailRepository.findByCocktailNameContainingIgnoreCaseOrIngredientContainingIgnoreCase(keyword, keyword); + } } - } - // 칵테일 검색,필터기능 - @Transactional(readOnly = true) - public List searchAndFilter(CocktailFilterRequestDto cocktailFilterRequestDto) { - // 기본값 페이지/사이즈 정하기(PAGE 기본값 0, 사이즈 10) - int page = cocktailFilterRequestDto.getPage() != null && cocktailFilterRequestDto.getPage() >= 0 - ? cocktailFilterRequestDto.getPage() : 0; - - int size = cocktailFilterRequestDto.getSize() != null && cocktailFilterRequestDto.getSize() > 0 - ? cocktailFilterRequestDto.getSize() : DEFAULT_SIZE; - - // searchWithFilters에서 조회한 결과값을 pageResult에 저장. - Pageable pageable = PageRequest.of(page, size); - - // 빈 리스트(null 또는 [])는 null로 변환 - List strengths = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholStrengths()) - ? null - : cocktailFilterRequestDto.getAlcoholStrengths(); - - List types = CollectionUtils.isEmpty(cocktailFilterRequestDto.getCocktailTypes()) - ? null - : cocktailFilterRequestDto.getCocktailTypes(); - - List bases = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholBaseTypes()) - ? null - : cocktailFilterRequestDto.getAlcoholBaseTypes(); - - // Repository 호출 - Page pageResult = cocktailRepository.searchWithFilters( - cocktailFilterRequestDto.getKeyword(), - strengths, // List - types, // List - bases, // List - pageable - ); - - //Cocktail 엔티티 → CocktailResponseDto 응답 DTO로 바꿔주는 과정 - List resultDtos = pageResult.stream() - .map(c -> new CocktailResponseDto( - c.getCocktailId(), - c.getCocktailName(), - c.getAlcoholStrength(), - c.getCocktailType(), - c.getAlcoholBaseType(), - c.getCocktailImgUrl(), - c.getCocktailStory(), - c.getCreatedAt() - )) - .collect(Collectors.toList()); - - return resultDtos; - } + // 칵테일 검색,필터기능 + @Transactional(readOnly = true) + public List searchAndFilter (CocktailFilterRequestDto cocktailFilterRequestDto){ + // 기본값 페이지/사이즈 정하기(PAGE 기본값 0, 사이즈 10) + int page = cocktailFilterRequestDto.getPage() != null && cocktailFilterRequestDto.getPage() >= 0 + ? cocktailFilterRequestDto.getPage() : 0; + + int size = cocktailFilterRequestDto.getSize() != null && cocktailFilterRequestDto.getSize() > 0 + ? cocktailFilterRequestDto.getSize() : DEFAULT_SIZE; + + // searchWithFilters에서 조회한 결과값을 pageResult에 저장. + Pageable pageable = PageRequest.of(page, size); + + // 빈 리스트(null 또는 [])는 null로 변환 + List strengths = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholStrengths()) + ? null + : cocktailFilterRequestDto.getAlcoholStrengths(); + + List types = CollectionUtils.isEmpty(cocktailFilterRequestDto.getCocktailTypes()) + ? null + : cocktailFilterRequestDto.getCocktailTypes(); + + List bases = CollectionUtils.isEmpty(cocktailFilterRequestDto.getAlcoholBaseTypes()) + ? null + : cocktailFilterRequestDto.getAlcoholBaseTypes(); + + // Repository 호출 + Page pageResult = cocktailRepository.searchWithFilters( + cocktailFilterRequestDto.getKeyword(), + strengths, // List + types, // List + bases, // List + pageable + ); + + //Cocktail 엔티티 → CocktailResponseDto 응답 DTO로 바꿔주는 과정 + List resultDtos = pageResult.stream() + .map(c -> new CocktailResponseDto( + c.getCocktailId(), + c.getCocktailName(), + c.getAlcoholStrength(), + c.getCocktailType(), + c.getAlcoholBaseType(), + c.getCocktailImgUrl(), + c.getCocktailStory(), + c.getCreatedAt() + )) + .collect(Collectors.toList()); + + return resultDtos; + } // private List nullIfEmpty(List list) { // return CollectionUtils.isEmpty(list) ? null : list; // } - // 칵테일 상세조회 - @Transactional(readOnly = true) - public CocktailDetailDto getCocktailDetailById(Long cocktailId) { - Cocktail cocktail = cocktailRepository.findById(cocktailId) - .orElseThrow(() -> new RuntimeException("칵테일을 찾을 수 없습니다. id: " + cocktailId)); - - return new CocktailDetailDto(cocktail); + // 칵테일 상세조회 + @Transactional(readOnly = true) + public CocktailDetailDto getCocktailDetailById (Long cocktailId){ + Cocktail cocktail = cocktailRepository.findById(cocktailId) + .orElseThrow(() -> new NoSuchElementException("칵테일을 찾을 수 없습니다. id: " + cocktailId)); + return new CocktailDetailDto(cocktail); + } } -} diff --git a/src/main/java/com/back/global/security/SecurityConfig.java b/src/main/java/com/back/global/security/SecurityConfig.java index dc469757..a0cf9f55 100644 --- a/src/main/java/com/back/global/security/SecurityConfig.java +++ b/src/main/java/com/back/global/security/SecurityConfig.java @@ -46,7 +46,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/login/oauth2/**").permitAll() .requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll() .requestMatchers("/api/user/**").permitAll() - .requestMatchers("/api/cocktail/**").permitAll() + .requestMatchers("/api/cocktails/**").permitAll() // 회원 or 인증된 사용자만 가능 diff --git a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java index 530cd591..fc44f4d2 100644 --- a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java +++ b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java @@ -11,6 +11,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.transaction.annotation.Transactional; @@ -22,13 +23,14 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@ActiveProfiles("test") @SpringBootTest -@AutoConfigureMockMvc +@AutoConfigureMockMvc(addFilters = false) @Transactional public class CocktailControllerTest { + @Autowired private MockMvc mvc; - @Autowired private CocktailRepository cocktailRepository; @@ -36,40 +38,40 @@ public class CocktailControllerTest { // @Autowired // private UserService userService; -@Test -@DisplayName("칵테일 단건 조회 - 성공") -void t1() throws Exception { - Cocktail savedCocktail = cocktailRepository.save( - Cocktail.builder() - .cocktailName("모히토") - .alcoholStrength(AlcoholStrength.WEAK) - .cocktailType(CocktailType.SHORT) - .alcoholBaseType(AlcoholBaseType.RUM) - .cocktailImgUrl("https://example.com/image.jpg") - .cocktailStory("상쾌한 라임과 민트") - .ingredient("라임, 민트, 럼, 설탕, 탄산수") - .recipe("라임과 민트를 섞고 럼을 넣고 탄산수로 완성") - .createdAt(LocalDateTime.now()) - .updatedAt(LocalDateTime.now()) - .build() - ); + @Test + @DisplayName("칵테일 단건 조회 - 로그인 없이 성공") + void t1() throws Exception { + Cocktail savedCocktail = cocktailRepository.save( + Cocktail.builder() + .cocktailName("모히토") + .alcoholStrength(AlcoholStrength.WEAK) + .cocktailType(CocktailType.SHORT) + .alcoholBaseType(AlcoholBaseType.RUM) + .cocktailImgUrl("https://example.com/image.jpg") + .cocktailStory("상쾌한 라임과 민트") + .ingredient("라임, 민트, 럼, 설탕, 탄산수") + .recipe("라임과 민트를 섞고 럼을 넣고 탄산수로 완성") + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .build() + ); - // when: GET 요청 - ResultActions resultActions = mvc.perform( - get("/api/cocktails/{id}", savedCocktail.getCocktailId()) - .contentType(MediaType.APPLICATION_JSON) - ).andDo(print()); + // when: GET 요청 + ResultActions resultActions = mvc.perform( + get("/api/cocktails/{id}", savedCocktail.getCocktailId()) + .contentType(MediaType.APPLICATION_JSON) + ).andDo(print()); - // then: 상태코드, JSON 구조 검증 - resultActions - .andExpect(status().isOk()) - .andExpect(jsonPath("$.code").value(200)) - .andExpect(jsonPath("$.message").value("success")) - .andExpect(jsonPath("$.data.cocktailName").value("모히토")) - .andExpect(jsonPath("$.data.alcoholStrength").value("WEAK")) - .andExpect(jsonPath("$.data.cocktailType").value("SHORT")) - .andExpect(jsonPath("$.data.alcoholBaseType").value("RUM")); -} + // then: 상태코드, JSON 구조 검증 + resultActions + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andExpect(jsonPath("$.message").value("success")) + .andExpect(jsonPath("$.data.cocktailName").value("모히토")) + .andExpect(jsonPath("$.data.alcoholStrength").value("WEAK")) + .andExpect(jsonPath("$.data.cocktailType").value("SHORT")) + .andExpect(jsonPath("$.data.alcoholBaseType").value("RUM")); + } @Test @DisplayName("칵테일 단건 조회 - 실패 (존재하지 않는 ID)") @@ -77,14 +79,14 @@ void t2() throws Exception { long nonExistentId = 9999L; ResultActions resultActions = mvc.perform( - get("/api/v1/cocktails/{id}", nonExistentId) + get("/api/cocktails/{id}", nonExistentId) .contentType(MediaType.APPLICATION_JSON) ).andDo(print()); resultActions - .andExpect(status().isOk()) // RsData는 HTTP 200으로 반환됨 - .andExpect(jsonPath("$.code").value(500)) - .andExpect(jsonPath("$.message").value("칵테일이 존재하지 않습니다.")) + .andExpect(status().isNotFound()) // 전역 예외 처리기에서 404 반환 + .andExpect(jsonPath("$.code").value(404)) + .andExpect(jsonPath("$.message").value("해당 데이터가 존재하지 않습니다")) .andExpect(jsonPath("$.data").isEmpty()); } }